Category Archives: Swift

What’s new in Swift 5.0

A new version of the Swift programming language is coming: Swift 5.0. It’s slated to be released early 2019, with a fair number of changes. How does this Swift update affect practical iOS development? And who’s making these changes anyway?

In this article, we’ll walk through some of the proposed and accepted changes for Swift 5.0. We’ll also discuss how the process of making changes to the Swift language works, and why that’s relevant for iOS developers.

Version 5 of Apple’s Swift language used for iOS and MacOS application development will arrive in 2019 with ABI (application binary interface) stability in the standard Swift library a primary focus.

ABI stability is half of what is needed to support binary frameworks. The other half, module stability, will be a “stretch goal” for Swift 5 and may not make it into the release, Apple’s roadmap notes.

Continue reading What’s new in Swift 5.0

iPhone Device & Screen Sizes and Resolutions +Xr

To get the screen dimensions (in points) of the current device:

Objective-C: 
CGRect screenBounds = [[UIScreen mainScreen] bounds]; 
// Macros: 
#define screen_width [ [ UIScreen mainScreen ] bounds ].size.width #define screen_height [ [ UIScreen mainScreen ] bounds ].size.height 
Swift: 
let screenBounds = UIScreen.main.bounds 
let screen_width = screenBounds.width 
let screen_height = screenBounds.height 

To get the screen scale:

Objective-C: 
CGFloat screenScale = [[UIScreen mainScreen] scale]; Swift: let screenScale = UIScreen.main.scale

Non-retina devices have a scale of 1.0. Retina devices have a scale of 2.0 or 3.0.

Some dimensions common to all screen sizes:

Status Bar
20 pts
Navigation Bar44 pts
Nav Bar/Toolbar Icon20 x 20 pts (transparent PNG)
Tab Bar49 pts
Tab Bar Icon30 x 30 pts (transparent PNGs)

Points vs. Pixels

Apple introduced retina displays starting with the iPhone 4. You don’t have to modify your code to support high-res displays; the iOS coordinate system uses points rather than pixels, so the dimensions and position in points of all UI elements remains the same across all devices.

iOS supports high resolution displays via the scale property on UIScreen, UIView, UIImage, and CALayer classes. If you load an image from a file whose name includes the @2x modifier, its scale property is set to 2.0. Similarly an image with a @3x modifier has a scale of 3.0. Otherwise the scale defaults to 1.0.

Retina Graphics

To support high-resolution graphics on devices with retina displays, you need @2x and @3x sized images:

@1x:
button.png
60 x 20
@2x:
button@2x.png
120 x 40
@3x:
button@3x.png
180 x 60

To refer to an image in your code (or in Interface Builder), just use the filename of the standard sized image. iOS will automatically detect and use the @2x or @3x version if the device supports it:

Objective-C: 
<br>imageView.image = [UIImage imageNamed: @"button.png"]; Swift: imageView.image = UIImage(named: @"button.png") 

How to use Swift classes all across an Objective-C project

The most universal solution is to change SWIFT_OBJC_INTERFACE_HEADER_NAME (“Objective-C Generated Interface Header Name”) under Project’s, not Targets, Build Settings, to:

  • $(PROJECT_NAME)-Swift.h — one per project;
  • $(SWIFT_MODULE_NAME)-Swift.h — one per module (default value).

Then import the Project Header, example:

#import MyProjectName-Swift.h

How to debug deep linking in iOS

What is deep linking?

Deep linking basically enables you to open an app from another app or a website while passing on parameters. This mechanism works with custom URL schemes which you can define in the .plist of your app.

Why deep linking?

If you have an app with lookup functionality (e.g. an app for finding song lyrics) you might want to perform a lookup without having to navigate to the designated screen and typing in the query. This can be achieved by opening the following example URL MyAppScheme://myAction=lookup&myQuery=What%20is%20the%20meaning%20of%20life in another app of the browser. In this case the app is programmed to read the ‘myAction’-parameter on startup to determine the action and the ‘myQuery’-parameter for the search query. Often, deep linking doesn’t go as planned and you might need to debug your app.

Why is debugging this difficult?

Deep linking might occur in three kinds of scenarios:

  1. The app hasn’t been installed yet
  2. The app is running in the background (or foreground for that matters)
  3. The app is installed but not running at all

Scenario 1 is irrelevant in this case, so we’ll skip this one. Scenario 2 should be no problem since the app is running on the device (or simulator) while in a debug session. Scenario 3 requires you not to have the app running, but you need the debug session to be able to debug. This is a problem because Xcode starts the app automatically when starting a debug session. Instead of letting Xcode start the app, you want to do it yourself using the deep link URL.

So… tell me how to do this

There is a convenient option which enables you to start a debug session by manually starting the app. To achieve this, go to the ‘Edit scheme’ screen and tick the ‘Wait for MyApp.app to be launched manually’ option on in the ‘Run’ configuration.

Image

Whenever you run the target in Xcode, the app doesn’t automatically starts and the debug session will only start when you manually start the app.

NSOperation – Tutorial

Operation Queues

GCD is a low-level C API that enables developers to execute tasks concurrently. Operation queues, on the other hand, are high level abstraction of the queue model, and is built on top of GCD. That means you can execute tasks concurrently just like GCD, but in an object-oriented fashion. In short, operation queues just make developers’ life even simpler.

Unlike GCD, they don’t conform to the First-In-First-Out order. Here are how operation queues are different from dispatch queues:

  1. Don’t follow FIFO: in operation queues, you can set an execution priority for operations and you can add dependencies between operations which means you can define that some operations will only be executed after the completion of other operations. This is why they don’t follow First-In-First-Out.
  2. By default, they operate concurrently: while you can’t change its type to serial queues, there is still a workaround to execute tasks in operation queues in sequence by using dependencies between operations.
  3. Operation queues are instances of class NSOperationQueue and its tasks are encapsulated in instances of NSOperation.

NSOperation

Tasks submitted to operation queues are in the form of NSOperation instances. We discussed in GCD that tasks are submitted in block. The same can be done here but should be bundled inside NSOperation instance. You can simply think of NSOperation as a single unit of work.

NSOperation is an abstract class which can’t be used directly so you have to use NSOperation subclasses. In the iOS SDK, we are provided with two concrete subclasses of NSOperation. These classes can be used directly, but you can also subclass NSOperation and create your own class to perform the operations. The two classes that we can use directly are:

  1. NSBlockOperation – Use this class to initiate operation with one or more blocks. The operation itself can contain more than one block and the operation will be considered as finish when all blocks are executed.
  2. NSInvocationOperation – Use this class to initiate an operation that consists of invoking a selector on a specified object.

So what’s the advantages of NSOperation?

    1. First, they support dependencies through the method addDependency(op: NSOperation) in the NSOperation class. When you need to start an operation that depends on the execution of the other, you will want to use NSOperation.
NSOperation Illustration
  1. Secondly, you can change the execution priority by setting the property queuePrioritywith one of these values:

    The operations with high priority will be executed first.

  2. You can cancel a particular operation or all operations for any given queue. The operation can be cancelled after being added to the queue. Cancellation is done by calling method cancel() in the NSOperation class. When you cancel any operation, we have three scenarios that one of them will happen:
    • Your operation is already finished. In that case, the cancel method has no effect.
    • Your operation is already being executing. In that case, system will NOT force your operation code to stop but instead, cancelled property will be set to true.
    • Your operation is still in the queue waiting to be executed. In that case, your operation will not be executed.
  3. NSOperation has 3 helpful boolean properties which are finished, cancelled, and ready. finished will be set to true once operation execution is done. cancelled is set to true once the operation has been cancelled. ready is set to true once the operation is about to be executed now.
  4. Any NSOperation has an option to set completion block to be called once the task being finished. The block will be called once the property finished is set to true in NSOperation.

Now let’s rewrite our project demo but this time we’ll use NSOperationQueues. First declare the variable below in the ViewController class:

Next, replace the didClickOnStart method with the code below and see how we perform operations in NSOperationQueue:

As you see in the above code, you use the method addOperationWithBlock to create a new operation with the given block (or as we call it in Swift, a closure). It’s very simple, isn’t it? To perform a task in the main queue, instead of calling dispatch_async() as when using GCD, we can do the same from NSOperationQueue (NSOperationQueue.mainQueue()) and submit the operation you want to execute in the main queue.

You can run the app to have a quick test. If the code was entered correctly, the app should be able to download the images in background without blocking the UI.

In the previous example, we used the method addOperationWithBlock to add operation in the queue. Let’s see how we can use NSBlockOperation to do the same, but at the same time, giving us more functionalities and options such as setting completion handler. The didClickOnStart method is rewritten like this:

For each operation, we create a new instance of NSBlockOperation to encapsulate the task into a block. By using NSBlockOperation, you’re allowed to set the completion handler. Now when the operation is done, the completion handler will be called. For simplicity, we just log a simple message to indicate the operation is done. If you run the demo, you would see something like this in console:

Canceling Operations

As mentioned before, NSBlockOperation allows you to manage the operations. Now let’s see how to cancel an operation. To do that, first add a bar button item to the navigation bar and name it Cancel. In order to demonstrate the cancel operation, we will add a dependency between Operation #2 and Operation #1, and another dependency between Operation #3 and Operation #2. This means Operation #2 will start after finishing of Operation #1, and Operation #3 will start after Operation #2 completes. Operation #4 has no dependency and will work concurrently. To cancel the operations all you need to do is call cancelAllOperations() of NSOperationQueue. Insert the following method in the ViewController class:

Remember you need to associate the Cancel button you added to the navigation bar with the didClickOnCancel method. You can do this by returning to the Main.storyboard file and opening the Connections Inspector. There you will see the unlink didSelectCancel() in the Received Actions section. Click + drag from the empty circle to the Cancel bar button. Then create the dependencies in the didClickOnStart method like this:

Next change the completion block of operation #1 to log the cancelled state like this:

You may change the log statement for operation #2, #3 and #4, so you will have a better idea of the process. Now let’s build and run. After you hit the Start button, press the Cancel button. This will cancel all operations after operation #1 completes. Here is what happens:

  • As operation #1 already executed, cancelling will do nothing. This is why the cancelled value is logged false, and the app still shows image #1.
  • If you hit the Cancel button quick enough, operation #2 is cancelled. The cancelAllOperations() call will stop its execution, so image #2 is not downloaded.
  • Operation #3 was already in the queue, waiting for operation #2 to complete. As it depends on the completion of operation #2 and operation #2 was cancelled, operation #3 will not be executed and kicked out immediately from the queue.
  • There is no dependency configured for operation #4. It just runs concurrently to download image #4.
ios-concurrency-cancel-demo

Where to go from here?

In this tutorial, I have walked you through the concept of iOS concurrency and how you can implement it in iOS. I have given you a good introduction about concurrency, explained GCD, and showed you how to create series and concurrent queues. Furthermore, we have checked out NSOperationQueues. You should now be comfortable with the difference between Grand Central Dispatch and NSOperationQueue.

To dive further into iOS concurrency, I advise you to check out Apple’s Concurrency Guide.

Original article in: http://www.appcoda.com/ios-concurrency/

UIAlertView in Swift

In Swift and iOS 8 SDK you can present an alert view as shown in the code below :

 

var alert = UIAlertController(title: “Alert Title”, message: “Message”, preferredStyle: UIAlertControllerStyle.Alert)alert.addAction(UIAlertAction(title: “OK”, style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)

You can also add destructive and cancel actions by setting the style property to Destructive and Cancel respectively.