Brian Coleman

  • Home
  • ABOUT
  • SERVICES
  • PORTFOLIO
  • BLOG
  • Contact

Tutorial 59

Tutorial: Building an Apple Watch Notification

Notifications on Apple Watch facilitate quick, lightweight interactions for local and remote notifications. These interactions occur in two stages, which are managed by the short-look and long-look interfaces. The short-look interface appears when a local or remote notification first arrives. A short look presents a discreet, minimal amount of information to the user—preserving a degree of privacy. If the wearer’s wrist is lowered, the short-look interface disappears. The long-look interface appears when the wearer’s wrist remains raised or when the wearer taps the short-look interface. It provides more detailed information and more functionality—and it must be actively dismissed by the wearer.

Static vs Dynamic Interfaces

The custom long-look notification interface consists of two separate interfaces: one static and one dynamic. The static interface is required and is a simple way to display the notification’s alert message and any static images and text that you configure at design time. The dynamic interface is optional and gives you a way to customize the display of your notification’s content.

notification_static_dynamic_2x

notification_process_2x

Use the static notification interface to define a simple version of your custom notification interface. The purpose of a static interface is to provide a fallback interface in the event that your WatchKit extension is unable to configure the dynamic interface in a timely manner.

A dynamic notification interface lets you provide a more enriched notification experience for the user. With a dynamic interface, you can display more than just the alert message. You can incorporate additional information, configure more than one label, display dynamically generated content, and so on.

To implement a dynamic notification interface, you must create a custom WKUserNotificationInterfaceController subclass. How you implement that subclass determines what information is displayed in the notification interface.

We’ll cover how to customize a dynamic notification, since for the static ones, “it just works”.

To build a Dynamic Notification you need to already have a Watch App, if you’d like to learn how to do that, read
Tutorial: Building an Apple Watch App In that tutorial we walk through building an app that shows the time across all four Canadian and U.S. timezones.

Customize a Dynamic Notification

  1. Begin by adding all of the labels needed for the Interface within the Storyboard under the Dynamic Notification Interface.
  2. Drag in a Group object from the Object Library for each one of the timezones.
    Screen Shot 2015-04-20 at 3.55.05 PM

  3. Now that we have our UI defined, let’s connect the IBOutlets with the code in the “NotificationController.swift” file. You can do this many ways, just like an iOS app. Either Control-drag the UI object from the storyboard into the NotificationController.swift or define the code and link up using the Connections Inspector.
  4. After the UI is all hooked up, let’s add some code for the NotificationController.swift so when we receive a notification we’ll show the current timezone times to the user.
  5. The following is to define our labels that will be in the notification. Don’t forget to add the alertLabel and bodyLabel or else the user will not see the pay load for the remote notification sent to them.
        @IBOutlet var easternLabel : WKInterfaceLabel? = WKInterfaceLabel()
        @IBOutlet var centralLabel : WKInterfaceLabel? = WKInterfaceLabel()
        @IBOutlet var mountainLabel : WKInterfaceLabel? = WKInterfaceLabel()
        @IBOutlet var pacificLabel : WKInterfaceLabel? = WKInterfaceLabel()
        
        @IBOutlet var alertLabel : WKInterfaceLabel? = WKInterfaceLabel()
        @IBOutlet var bodyLabel : WKInterfaceLabel? = WKInterfaceLabel()
    
  6. Next are the methods for handling the local and remote notifications. You need to add code in here for the Dynamic Interface to be enabled, if you leave it blank you will get the Static Interface for the notification with the title displayed.
        override func didReceiveLocalNotification(localNotification: UILocalNotification, withCompletion completionHandler: ((WKUserNotificationInterfaceType) -> Void)) {
            // This method is called when a local notification needs to be presented.
            // Implement it if you use a dynamic notification interface.
            // Populate your dynamic notification interface as quickly as possible.
            
            self.alertLabel?.setText(localNotification.alertTitle)
            
            self.updateClocks()
            
            // After populating your dynamic notification interface call the completion block.
            completionHandler(.Custom)
        }
        
        override func didReceiveRemoteNotification(remoteNotification: [NSObject : AnyObject], withCompletion completionHandler: ((WKUserNotificationInterfaceType) -> Void)) {
            
            self.updateClocks()        
    
            if let remoteaps:NSDictionary = remoteNotification["aps"] as? NSDictionary{
                if let remoteAlert:NSDictionary = remoteaps["alert"] as? NSDictionary{
                    handleNotification( remoteAlert );
                }
            }
            
            completionHandler(.Custom)
        }
        
        func handleNotification( alert : AnyObject? ){
            
            if let alert: AnyObject = alert, let remotetitle = alert["title"] as? String{
                println( "didReceiveRemoteNotification::remoteNotification.alert \(remotetitle)" )
                self.alertLabel!.setText(remotetitle);
            }
            if let alert: AnyObject = alert, let remotebody = alert["body"] as? String{
                //println( "didReceiveRemoteNotification::remoteNotification.alert \(remotetitle)" )
                self.bodyLabel!.setText(remotebody);
            }
        }
    
  7. Lastly below is the method to return the time per timezone to be displayed in the notification.
        func updateClocks() {
            var time: NSDate = NSDate()
            
            let formatter:NSDateFormatter = NSDateFormatter();
            var timeZone = NSTimeZone(name: "UTC")
            formatter.timeZone = timeZone
            formatter.dateFormat = "h:mm a"
            var formattedString = formatter.stringFromDate(time)
            var formatDateString = formattedString.stringByReplacingOccurrencesOfString(" p", withString: "PM", options: nil, range: nil)
            formattedString = formattedString.stringByReplacingOccurrencesOfString(" a", withString: "AM", options: nil, range: nil)
            
            timeZone = NSTimeZone(name: "US/Eastern")
            formatter.timeZone = timeZone
            formatter.dateFormat = "h:mm a"
            formattedString = formatter.stringFromDate(time)
            formatDateString = formattedString.stringByReplacingOccurrencesOfString(" p", withString: "PM", options: nil, range: nil)
            formattedString = formattedString.stringByReplacingOccurrencesOfString(" a", withString: "AM", options: nil, range: nil)
            self.easternLabel?.setText(formatDateString)
            
            timeZone = NSTimeZone(name: "US/Pacific")
            formatter.timeZone = timeZone
            formatter.dateFormat = "h:mm a"
            formattedString = formatter.stringFromDate(time)
            formatDateString = formattedString.stringByReplacingOccurrencesOfString(" p", withString: "PM", options: nil, range: nil)
            formattedString = formattedString.stringByReplacingOccurrencesOfString(" a", withString: "AM", options: nil, range: nil)
            self.pacificLabel?.setText(formatDateString)
            
            timeZone = NSTimeZone(name: "US/Mountain")
            formatter.timeZone = timeZone
            formatter.dateFormat = "h:mm a"
            formattedString = formatter.stringFromDate(time)
            formatDateString = formattedString.stringByReplacingOccurrencesOfString(" p", withString: "PM", options: nil, range: nil)
            formattedString = formattedString.stringByReplacingOccurrencesOfString(" a", withString: "AM", options: nil, range: nil)
            self.mountainLabel?.setText(formatDateString)
            
            timeZone = NSTimeZone(name: "US/Central")
            formatter.timeZone = timeZone
            formatter.dateFormat = "h:mm a"
            formattedString = formatter.stringFromDate(time)
            formatDateString = formattedString.stringByReplacingOccurrencesOfString(" p", withString: "PM", options: nil, range: nil)
            formattedString = formattedString.stringByReplacingOccurrencesOfString(" a", withString: "AM", options: nil, range: nil)
            self.centralLabel?.setText(formatDateString)
        }
    

    Test Your Notification

    1. When you run the app you’ll see a blank view since our app doesn’t do anything except create the Watch App and the watch is shown in an External Display.
    2. Build and Run your app against the Notification target.
      Screen Shot 2015-04-20 at 4.00.35 PM

    3. Then, switch over to your simulator and check that you have the External Display set for the watch. iOS Simulator > Hardware > External Displays (try both sizes to see how it looks).
      Screen Shot 2015-04-17 at 1.44.26 PM

    4. You should see your app in the Notification in the Watch simulator. Since it’s in the simulator it will provide some sample payload “Optional title” and “Test message” to be displayed.
      Screen Shot 2015-04-20 at 4.02.20 PM

    You can grab the full source code for this tutorial. Note: Built for Xcode 6.3 (Swift 1.2).

April 20, 2015 Swift, Tutorials, Watchios8, swift, tutorial, watch

Tutorial: Upgrading to Swift 1.2

Apple has just released it’s new and improved version of Swift. They have been listening to a lot of developer feedback and continue to make Swift better and easier to use. If you upgraded to the Xcode 6.3 and ran your project you’ll notice a lot of new errors, hopefully the details below will make it easier to upgrade your project.

What’s New in Swift 1.2

You’ll now notice that Xcode is really really fast again. Those of you who work on large scale projects will notice how fast it compiles now. In Xcode 6.2 our current project took 1:45 – 2:00 minutes to compile, making incremental changes infuriating, now it takes seconds to compile, saving so much time.

  • Incremental builds — Source files that haven’t changed will no longer be re-compiled by default, which will significantly improve build times for most common cases. Larger structural changes to your code may still require multiple files to be rebuilt.
  • Faster executables — Debug builds produce binaries that run considerably faster, and new optimizations deliver even better Release build performance.

Other than speed you’ll notice its a lot more reliable and easier to write code in Swift.

  • Better compiler diagnostics — Clearer error and warning messages, along with new Fix-its, make it easier to write proper Swift 1.2 code.
  • Stability improvements — The most common compiler crashes have been fixed. You should also see fewer SourceKit warnings within the Xcode editor.

Convert to the Latest Swift Syntax

The first step you may want to try is to let Xcode take care of as much as possible itself.

From the menu bar in Xcode > Edit > Convert > To Swift 1.2

Screen Shot 2015-04-13 at 9.52.36 AM

A little instructions and warning that this will not fix all of the issues in your project for Swift 1.2.

Screen Shot 2015-04-13 at 9.52.51 AM

Select your target and then it’s the same as how refactoring works – Xcode will work away and then come back with a preview of the code that needs to be changed.

Screen Shot 2015-04-13 at 9.53.00 AM

You’ll see the old code and new code side-by-side with the changes needed.

Screen Shot 2015-04-13 at 10.13.30 AM

Down Casting Improvements

as! for failable casts — Casts that can fail at runtime are now expressed with the new as! operator to make their potential for runtime failure clear to readers and maintainers of your code.

You’ll need to use the as! to convert between types, which used to work before.

var appVersion = NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleShortVersionString") as String

Apple wants you to be more explicit with optional vs. non-optional type conversions

ViewController.swift:61:105: 'AnyObject?' is not convertible to 'String'; did you mean to use 'as!' to force downcast?

Use as! instead of as

var appVersion = NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleShortVersionString") as! String

let Constants

let constants are now more powerful and consistent — The new rule is that a let constant must be initialized before use (like a var), and that it may only be initialized, not reassigned or mutated after initialization.

Take enables patterns like this:

let x : SomeThing
if condition {
	x = foo()
} else {
	x = bar()
}
use(x)

This formerly required the use of a var even though there is no mutation taking place. Properties have been folded into this model to simplify their semantics in initializers as well.

if let Improvements

Prior to Swift 1.2 you could only optionally bind one at a time, now you can unwrap multiple optionals at once, as well as include intervening boolean conditions. This lets you express conditional control flow without lots of if – else nesting needed.

Here’s an example of if-let in a single statement:

if let language = swift?.language where language.type == kSwift, let objC = language.old? {
  doSomething()
}

New Set Data Type

New native Set data structure — An unordered collection of unique elements that bridges with NSSet and provides value semantics like Array and Dictionary.

just like String, Array, and Dictionary are bridged to their corresponding Objective-C classes, the new Set data type is bridged to Objective-C’s NSSet class. Sets are generic collections so you need to provide the type of object to store; however, they store unique elements so you won’t see any duplicates.

var languages = Set()

languages.insert("Objective-C")
languages.insert("Swift")
languages.insert("PHP")
languages.insert("Perl")

if languages.isEmpty {
    println("I don't know any computer languages.")
}
else {
    if languages.contains("Objective-C") || languages.contains("Swift")
    {
        println("I know how to make iOS apps.")
    }
}
April 13, 2015 Swift, Tutorials, Uncategorizedios8, swift, tutorial

Tutorial: NSDate in Swift

NSDate objects represent a single point in time. NSDate is a class cluster; its single public superclass, NSDate, declares the programmatic interface for specific and relative time values. The objects you create using NSDate are referred to as date objects.

NSDate is an abstract class that provides behavior for creating dates, comparing dates, representing dates, computing intervals, and similar functionality. NSDate presents a programmatic interface through which suitable date objects are requested and returned. Date objects returned from NSDate are lightweight and immutable since they represent an invariant point in time.

Using NSDate

In objective-c, the following code results in the UTC date time information using the date API.

NSDate *currentUTCDate = [NSDate date]

In Swift however,

let date = NSDate()

Results in local date and time.

UTC vs Local Time

NSDate is a specific point in time without a time zone. Think of it as the number of seconds that have passed since a reference date. How many seconds have passed in one time zone vs. another since a particular reference date? The answer is the same.

Depending on how you output that date (including looking at the debugger), you may get an answer in a different time zone.

If they ran at the same moment, the values of these are the same. They’re both the number of seconds since the reference date, which may be formatted on output to UTC or local time. Within the date variable, they’re both UTC.

To explain this, we can use a NSDateFormatter in a playground:

import UIKit

let date = NSDate();
// "Apr 1, 2015, 8:53 AM" <-- local without seconds

var formatter = NSDateFormatter();
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss ZZZ";
let defaultTimeZoneStr = formatter.stringFromDate(date);
// "2015-04-01 08:52:00 -0400" <-- same date, local, but with seconds
formatter.timeZone = NSTimeZone(abbreviation: "UTC");
let utcTimeZoneStr = formatter.stringFromDate(date);
// "2015-04-01 12:52:00 +0000" <-- same date, now in UTC

Compare NSDate

If you need to compare two dates, you can use the method below. This example shows comparing the current date against an endDate. It will give you all possible results so you can handle each situation.

// Date comparision to compare current date and end date.
var dateComparisionResult:NSComparisonResult = NSDate().compare(endDate)

if dateComparisionResult == NSComparisonResult.OrderedAscending
{
    // Current date is smaller than end date.
}
else if dateComparisionResult == NSComparisonResult.OrderedDescending
{
    // Current date is greater than end date.
}
else if dateComparisionResult == NSComparisonResult.OrderedSame
{
    // Current date and end date are same.
}

There are several useful methods in NSCalendar in iOS 8.0+:

startOfDayForDate, isDateInToday, isDateInYesterday, isDateInTomorrow

And even to compare days:

func isDate(date1: NSDate!, inSameDayAsDate date2: NSDate!) -> Bool

To ignore the time element you can use this:

var toDay = NSCalendar.currentCalendar().startOfDayForDate(NSDate())

Formatting NSDate

If you have a string and want to convert it to an NSDate.

var dataString = "April 1, 2015" as String
var dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "MM-dd-yyyy"
dateFormatter.timeZone = NSTimeZone.localTimeZone()

// convert string into date
let dateValue = dateFormatter.dateFromString(dataString) as NSDate!

println(dateValue)

This might help you also formatting your dates:
Sg0tZ

Convert Unix TimeStamp to NSDate in Swift

If you have a timestamp "/Date(1427909016000-0800)" and you need to convert it to an NSDate, you can use the following extension. This will also convert it to your local time. The first part "1427909016000" is the time since the Unix epoch in milliseconds, and the second part "-0800" is a time zone specification.

extension NSDate {
    convenience init?(jsonDate: String) {
        let prefix = "/Date("
        let suffix = ")/"
        let scanner = NSScanner(string: jsonDate)
        
        // Check prefix:
        if scanner.scanString(prefix, intoString: nil) {
            
            // Read milliseconds part:
            var milliseconds : Int64 = 0
            if scanner.scanLongLong(&milliseconds) {
                // Milliseconds to seconds:
                var timeStamp = NSTimeInterval(milliseconds)/1000.0
                
                // Read optional timezone part:
                var timeZoneOffset : Int = 0
                if scanner.scanInteger(&timeZoneOffset) {
                    let hours = timeZoneOffset / 100
                    let minutes = timeZoneOffset % 100
                    // Adjust timestamp according to timezone:
                    timeStamp += NSTimeInterval(3600 * hours + 60 * minutes)
                }
                
                // Check suffix:
                if scanner.scanString(suffix, intoString: nil) {
                    // Success! Create NSDate and return.
                    self.init(timeIntervalSince1970: timeStamp)
                    return
                }
            }
        }
        
        // Wrong format, return nil. (The compiler requires us to
        // do an initialization first.)
        self.init(timeIntervalSince1970: 0)
        return nil
    }
}

Here's an example of it in use:

if let theDate = NSDate(jsonDate: "/Date(1427909016000-0800)/")
{
    println(theDate)
}
else
{
    println("wrong format")
}

Result

2015-04-01 09:23:36 +0000
April 1, 2015 Swift, Tutorialsios8, swift, tutorial

Tutorial: How To Share in Facebook SDK 4.1.x for Swift

There are a couple of ways to integrate Facebook Sharing into your app. The first and easiest is using the existing Social Framework that is embedded in iOS. If you want to go this route, read my article about it here: Tutorial: Share on Twitter and Facebook in Swift.

The other option is to use the native Facebook SDK. This will require that a user is logged into Facebook using Facebook Login. In this tutorial we’ll cover how to integrate Facebook Share into your app using the native Facebook 4.0 SDK using Swift.

You can share three different types of content using Facebook, they are Links, Photos & Videos. Let’s cover each of them.

To begin, follow the steps in this article to integrate the Facebook SDK and implement Facebook Login: Tutorial: How To Use Login in Facebook SDK 4.0 for Swift.

Import the Share Kit Framework

  1. Add the FacebookSDKShareKit.Framework & Bolts.framework to your project just like your did with the FacebookSDKCoreKit.Framework. Drag it or add it using the “Linked Frameworks and Libraries” within your target settings.
  2. Add the following import statement to your Bridging-Header.h, right below the Core Kit entry.
    #import 
    
  3. Add the Facebook Share buttons to your ViewController.swift.

Share a Link on Facebook

When people share links from your app to Facebook, it includes attributes that show up in the post:

contentURL – the link to be shared
contentTitle – represents the title of the content in the link
imageURL – the URL of thumbnail image that appears on the post
contentDescription – of the content, usually 2-4 sentences

Here’s the code to show and execute the Link button:

let content : FBSDKShareLinkContent = FBSDKShareLinkContent()
content.contentURL = NSURL(string: "")
content.contentTitle = ""
content.contentDescription = ""
content.imageURL = NSURL(string: "")

let button : FBSDKShareButton = FBSDKShareButton()
button.shareContent = content
button.frame = CGRectMake((UIScreen.mainScreen().bounds.width - 100) * 0.5, 50, 100, 25)
self.view.addSubview(button)

Share a Photo on Facebook

People can share photos from your app to Facebook with the Share Dialog or with a custom interface:

  • Photos must be less than 12MB in size
  • People need the native Facebook for iOS app installed, version 7.0 or higher

Build your share content for photos with the FBSDKSharePhotoContent model.

Note: You will not be able to test this in the Simulator, you’ll need to test on your device.

Here’s the code to show and execute the Photo button from an image picker:

First you’ll need to add the UIImagePickerControllerDelgate and UINavigationController Delegate to your class definition.

class ViewController: UIViewController, FBSDKLoginButtonDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate

Then add the code to display a button on the screen for the User to select a photo:

let button : UIButton = UIButton()
button.backgroundColor = UIColor.blueColor()
button.setTitle("Choose Photo", forState: .Normal)
button.frame = CGRectMake((UIScreen.mainScreen().bounds.width - 150) * 0.5, 125, 150, 25)
button.addTarget(self, action: "photoBtnClicked", forControlEvents: .TouchUpInside)
self.view.addSubview(button)

let label : UILabel = UILabel()
label.frame = CGRectMake((UIScreen.mainScreen().bounds.width - 200) * 0.5, 100, 200, 25)
label.text = "Photos Example"
label.textAlignment = .Center
self.view.addSubview(label)

When the User clicks the button, the following method is called to show the iOS image picker:

func photoBtnClicked(){
    if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.SavedPhotosAlbum){
        println("Photo capture")
        imagePicker.delegate = self
        imagePicker.sourceType = UIImagePickerControllerSourceType.SavedPhotosAlbum;
        imagePicker.allowsEditing = false
        self.presentViewController(imagePicker, animated: true, completion: nil)
    }   
}

Once the User selects a photo, the following delegate method is called.

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {
    
    let photo : FBSDKSharePhoto = FBSDKSharePhoto()
    photo.image = info[UIImagePickerControllerOriginalImage] as! UIImage
    photo.userGenerated = true
    let content : FBSDKSharePhotoContent = FBSDKSharePhotoContent()
    content.photos = [photo]
}

Share a Video on Facebook

People using your app can share videos to Facebook with the Share dialog or with your own custom interface:

  • Videos must be less than 12MB in size
  • People who share should have Facebook for iOS client installed, version 26.0 or higher.

Build your share content for photos with the FBSDKShareVideoContent model.

Note: You will not be able to test this in the Simulator, you’ll need to test on your device.

Here’s the code to show and execute the Video button from an image picker:

First you’ll need to add the UIImagePickerControllerDelgate and UINavigationController Delegate to your class definition.

class ViewController: UIViewController, FBSDKLoginButtonDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate

Then add the code to display a button on the screen for the User to select a video:

let button : UIButton = UIButton()
button.backgroundColor = UIColor.blueColor()
button.setTitle("Choose Video", forState: .Normal)
button.frame = CGRectMake((UIScreen.mainScreen().bounds.width - 150) * 0.5, 200, 150, 25)
button.addTarget(self, action: "videoBtnClicked", forControlEvents: .TouchUpInside)
self.view.addSubview(button)

let label : UILabel = UILabel()
label.frame = CGRectMake((UIScreen.mainScreen().bounds.width - 200) * 0.5, 175, 200, 25)
label.text = "Video Example"
label.textAlignment = .Center
self.view.addSubview(label)

When the User clicks the button, the following method is called to show the iOS video picker:

func videoBtnClicked(){
    if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.SavedPhotosAlbum){
        println("Video capture")
        imagePicker.delegate = self
        imagePicker.sourceType = UIImagePickerControllerSourceType.SavedPhotosAlbum
        imagePicker.allowsEditing = false
        self.presentViewController(imagePicker, animated: true, completion: nil)
    }
    
}

Once the User selects a video, the following delegate method is called.

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {
    
        let video : FBSDKShareVideo = FBSDKShareVideo()
        video.videoURL = info[UIImagePickerControllerMediaURL] as! NSURL
        let content : FBSDKShareVideoContent = FBSDKShareVideoContent()
        content.video = video
}


You can grab the full source code for this tutorial. Note: Created using XCode 6.3 (Swift 1.2).
If you need it built using Xcode 6.2 (Swift 1.1).

Screen Shot 2015-03-27 at 4.06.27 PM

March 27, 2015 Frameworks, Swift, Tutorialsfacebook, ios8, swift, tutorial

Tutorial: How To Use Login in Facebook SDK 4.1.x for Swift

It’s been a long time but Facebook has finally released a new version of their SDK. It’s not built using Swift, I guess that still makes it compatible with Objective-C. In this tutorial we’ll go through the steps to install the SDK and implement Facebook Login using the SDK in Swift.

Get your Application Setup with the Facebook SDK

  1. Visit the Getting Started with the Facebook iOS SDK documentation to download the Facebook SDK and install it.
  2. Add the FacebookSDKCoreKit.Framework to your project as you normally would. Drag it or add it using the “Linked Frameworks and Libraries” within your target settings.
  3. You won’t be able to use the normal #import <FBSDKCoreKit/FBSDKCoreKit.h> to link the framework so you need to do a work around by creating a Bridging Header.
  4. Create a new “Objective-C” Header file by clicking “File > New”
    Screen Shot 2015-03-27 at 9.17.15 AM
    Screen Shot 2015-03-27 at 9.18.41 AM

  5. All you need in the Bridging-Header.h is the import statement for the Facebook SDK.
    //
    //  Bridging-Header.h
    //  FacebookTutorial
    //
    //  Created by Brian Coleman on 2015-03-27.
    //  Copyright (c) 2015 Brian Coleman. All rights reserved.
    //
    
    #ifndef FacebookTutorial_Bridging_Header_h
    #define FacebookTutorial_Bridging_Header_h
    
    #import 
    
    #endif
    
  6. Add it to your target’s build settings:In Xcode, if you go into the build settings for your target, and scroll all the way down you’ll find a “Swift Compiler – Code Generation” section.

    Set “Objective-C Bridging Header” to <#PROJECT_NAME>/Bridging-Header.h

    “Install Objective-C Compatibility Header”, should be set to “Yes”.

    Here’s what it looks like:
    Screen Shot 2015-03-27 at 9.24.17 AM

  7. Now your app should be able to access all of the APIs in the Facebook SDK.
  8. Add the following to your AppDelegate.swift. The “OpenURL” method allows your app to open again after the user has validated their login credentials.
  9. The FBSDKAppEvents.activateApp() method allows Facebook to capture events within your application including Ads clicked on from Facebook to track downloads from Facebook and events like how many times your app was opened.
    //
    //  AppDelegate.swift
    //  FacebookTutorial
    //
    //  Created by Brian Coleman on 2015-03-27.
    //  Copyright (c) 2015 Brian Coleman. All rights reserved.
    //
    
    import UIKit
    
    @UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate {
    
        var window: UIWindow?
    
        func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
            // Override point for customization after application launch.
            return FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
        }
        
        func application(application: UIApplication,
            openURL url: NSURL,
            sourceApplication: String?,
            annotation: AnyObject?) -> Bool {
                return FBSDKApplicationDelegate.sharedInstance().application(
                    application,
                    openURL: url,
                    sourceApplication: sourceApplication,
                    annotation: annotation)
        }
    
        func applicationWillResignActive(application: UIApplication) {
            // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
            // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
        }
    
        func applicationDidEnterBackground(application: UIApplication) {
            // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
            // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
        }
    
        func applicationWillEnterForeground(application: UIApplication) {
            // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
        }
    
        func applicationDidBecomeActive(application: UIApplication) {
            // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
            FBSDKAppEvents.activateApp()
        }
    
        func applicationWillTerminate(application: UIApplication) {
            // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
        }
    
    }
    

Facebook Login for iOS

Now we’ll setup our app to use Facebook Login.

  1. Add the FacebookSDKLoginKit.Framework & Bolts.framework to your project just like your did with the FacebookSDKCoreKit.Framework. Drag it or add it using the “Linked Frameworks and Libraries” within your target settings.
  2. Add the following import statement to your Bridging-Header.h, right below the Core Kit entry.
    #import 
    
  3. Add the Facebook Login button to your ViewController.swift.
  4. After you add the button, you should update your view controller to check for an existing token at load. This eliminates an unnecessary app switch to Facebook if someone already granted permissions to your app.
  5. When you add Facebook Login, your app can ask someone for permissions on a subset of that person’s data. Use the readPermissions or publishPermissions property of the FBSDKLoginButton.
    //
    //  ViewController.swift
    //  FacebookTutorial
    //
    //  Created by Brian Coleman on 2015-03-27.
    //  Copyright (c) 2015 Brian Coleman. All rights reserved.
    //
    
    import UIKit
    
    class ViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
            
            if (FBSDKAccessToken.currentAccessToken() != nil)
            {
                // User is already logged in, do work such as go to next view controller.
            }
            else
            {
                let loginView : FBSDKLoginButton = FBSDKLoginButton()
                self.view.addSubview(loginView)
                loginView.center = self.view.center
                loginView.readPermissions = ["public_profile", "email", "user_friends"]
                loginView.delegate = self
            }
            
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }
    
    }
    

Using the FBSDKLoginButtonDelegate Methods

  1. Add in the additional code for the FBSDKLoginButtonDelegate. This is helpful to know if the user did login correctly and if they did you can grab their information.
  2. First add the delegate FBSDKLoginButtonDelegate to the class definition.
    class ViewController: UIViewController, FBSDKLoginButtonDelegate {
    
  3. Add the following callback methods to your View Controller.
        // Facebook Delegate Methods
        
        func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!) {
            println("User Logged In")
            
            if ((error) != nil)
            {
                // Process error
            }
            else if result.isCancelled {
                // Handle cancellations
            }
            else {
                // If you ask for multiple permissions at once, you
                // should check if specific permissions missing
                if result.grantedPermissions.contains("email")
                {
                     // Do work
                }
            }   
        }
        
        func loginButtonDidLogOut(loginButton: FBSDKLoginButton!) {
            println("User Logged Out")
        }
    
  4. Here is an extra method to grab the Users Facebook data. You can call this method anytime after a user has logged in by calling self.returnUserData().
        func returnUserData()
        {
            let graphRequest : FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: nil)
            graphRequest.startWithCompletionHandler({ (connection, result, error) -> Void in
               
                if ((error) != nil)
                {
                    // Process error
                    println("Error: \(error)")
                }
                else
                {
                    println("fetched user: \(result)")
                    let userName : NSString = result.valueForKey("name") as! NSString
                    println("User Name is: \(userName)")
                    let userEmail : NSString = result.valueForKey("email") as! NSString
                    println("User Email is: \(userEmail)")
                }
            })
        }
    

Enter your Facebook App Information

  1. There is one final step needed to be performed, and that is to add three new keys to the project’s .plist file. So, open it by clicking on the Supporting Files group in the Project Navigator and then on the Info.plist file. Add a new key named FacebookAppID, and as its value paste the App ID value which you can copy from the Facebook dashboard, at the top of it. Similarly, add the FacebookDisplayName key, and in its value paste the Display Name.Finally, create a new key named URL Types, and set its type to array with one item only. Give it the URL Schemes title and make it an array too. In the one and only item that should be contained, set the app ID value you copied from the Facebook dashboard, prefixing it with the fb literal. The image below shows all the three additions on the .plist file:
    Screen Shot 2015-03-27 at 10.12.39 AM
  2. Compile your project and you should see the following screen. Once you click the “Log in with Facebook” button, it should kick you out to the Facebook App or the Facebook website for the user to login. After they have, it’ll kick back to your app and you’ll see the user information in the console.
    Screen Shot 2015-03-27 at 11.43.09 AM
    Now it’s up to you to use the users information as you wish. Maybe to populate a user profile or to pull the users Facebook friends so you can build a leaderboard.


You can grab the full source code for this tutorial. Note: Created using XCode 6.3 (Swift 1.2).
If you need it built using Xcode 6.2 (Swift 1.1).

March 27, 2015 Frameworks, Swift, Tutorialsfacebook, ios8, swift, tutorial
Page 3 of 12«12345...10...»Last »
Recent Posts
  • Classix for iPhone, iPad & Apple TV
  • Tutorial: How to test your app for IPv6 compatibility
  • Tutorial: Testing SSL using Charles Proxy on an iOS Device
  • Tutorial: 3D Touch – Quick Actions in Swift
  • tvOS Tutorial: Top Shelf in Swift
Featured Apps
Classix
Sportsnet
TAGS
tutorialswiftios8iosobjective-cvideogamesstrategynewsframeworkappsmonitizefacebookwatchappleios7toolstvosios9apiprovisionsocialtutorialsbooksdesignbookiapIPv6iTunes Connect
Search
TAGS
tutorialswiftios8iosobjective-cvideogamesstrategynewsframeworkappsmonitizefacebookwatchappleios7toolstvosios9apiprovisionsocialtutorialsbooksdesignbookiapIPv6iTunes Connect
ABOUT
Brian is a Lead iOS/tvOS Developer from Toronto with over 18 years of multifaceted experience including development, design, business analysis and project management.

FOLLOW ME
    
Email Subscription
Sign up for my newsletter to receive the latest news and tutorials posted.

Enter your email address:

2023 © Brian Coleman