Tuesday, November 18, 2014

Today Extension in Swift


Today Extension also known as widget and its appear in the notification centre. It is used to show some quick information or to perform some quick task.

In this Tutorial, you will learn how to create Today extension and sharing data between containing app and Extension.  Also, you will learn how to open the containing app from Today Extension.

Create Today Extension-

Create a project with “Single View Application” template  and select languages as Swift and set the project name “TodayExtensionSample”.





Add Target-

In the Xcode project navigator, select the project and add new target to the project. Choose TodayExtension in Application Extension and named it “Photo Extension”. Also make sure that you have select the language Swift for both Project and Extension. 



This target will comprises of 3 files- 
1) TodayViewController.swift
2) MainInterface.storyboard 
3) Info.plist

TodayViewController.swift is subclass of UIViewController & adopting the NCWidgetProviding protocol and includes the method-

func widgetPerformUpdateWithCompletionHandler(completionHandler: ((NCUpdateResult) -> Void)!)

This method is called to give an opportunity to update the contents of Widget and redraw its view before taking snapshot.When the widget is finished updating its contents, it should call the completion handler block and pass the appropriate NCUpdateResult value.


Run Extension-

Now, if you run your extension then it will gives you the option to run the host app. Choose Today and it will launch the Today Notification centre  & your extension is showing Hello World.



In the notification centre there is a button Edit. When you tap on it, it will show all the available Today Extension. From here, you can enable & disable the extension. Also, you can recorder them.




Design User Interface-

Add a label & button named ”Open” in your extension with appropriate Constraints.

Note- Always use Autolayout for designing your Extension layout.  

Add a textfield & button named “Done” in the View Controller of your Containing App with appropriate Constraints. 

I have added the textField in Containing app so that user can enter some number in textField & when user taps on Done button, i have saved it to user Defaults and when user sees the Widget in Extension, i will show this number and user can open the Containing app by tapping the Open Button in Extension.


Share Data-

You can share the data between containing app & extension using App Group. You need to enable the AppGroup in both application & Extension.

To enable the App Group, select the project Navigation and choose your Application target  and taps on Capability from the top Menu and turns on the AppGroup.




Now, select your Development Team to use for provisioning and click Choose. It will add the “App Groups” entitlement to your App ID. You can add the New Group or choose from the existing one. I have given the Group name “ group.CompanyName.TodayExtension” in my sample app.




Now Repeat the same process for your Extension & choose the same AppGroup which you have selected for your application.


Note- AppGroup Name should be Unique.

Application code-

Select Your View Controller and implement the Done button-

@IBAction func doneButtonPressed (sender: UIButton){
if (textField?.isFirstResponder() != nil){
textField?.resignFirstResponder()
}
if  textField?.text.utf16Count > 0 {
var userDefaults: NSUserDefaults = NSUserDefaults(suiteName: "group.companyName.todayExtensionSample")
userDefaults.setObject(textField?.text, forKey:"Score")
userDefaults.synchronize()
}
}

Here, we have initialised the user Defaults with AppGroup & save the number entered in the textfield in the user Defaults.


Extension Code -

Now, open the TodayViewController and add this code in ViewDidLoad & widgetPerformUpdateWithCompletionHandler.

var userDefaults: NSUserDefaults = NSUserDefaults(suiteName: "group.companyName.todayExtensionSample")
var score = userDefaults.objectForKey("Score")! as? String ?? "0"
println("\(score)")
scoreLabel?.text = "Score- \(score)"

Here, again we have initialised the user Defaults with AppGroup & access the same value which we have saved from the Application.


Open App from Extension-

You can open the containing app from Widget by using openURL:completionHandler: method of NSExtensionContext. This method will work only for Today Extension. So you can 

openURL:completionHandler: method of NSExtensionContext to tell the system to open its containing app.

To open the application from your extension-

1) In the project Navigation,select the Application target & choose Info from the Top Menu.

2) Set the custom UrlScheme “todayExtensionSample”.

3) Implement the Open button in your TodayViewComntroller.

@IBAction func openButtonPressed(){
var url =  NSURL(string:"todayExtensionSample://")
self.extensionContext?.openURL(url, completionHandler:{(success: Bool) -> Void in
println("task done!")
})
}


Now, run your application and enter some number in the Text field and taps the Done Button. Now run your Extension, it will show the same Number which you have save in your application.

If you taps the Open Button, it will open your Application. 




You can download the sample app from Github.



1 comment:

  1. Good stuff! One of the most complete tutorials I have come across for the Today Extension, good on you and thanks for sharing.

    ReplyDelete