Monday, February 6, 2012

Building Location-Based Applications for the iPhone

owadays, it is becoming common to find mobile devices equipped with GPS receivers. Using a GPS receiver, you can pinpoint your current location easily via the many satellites orbiting around earth courtesy of the US government. However, GPS receivers require a clear line-of-sight to the sky to work, so they tend to work poorly or not at all indoors.
Another effective way to locate one's position is through cell tower triangulation. When a mobile phone is on, it stays in constant contact with base stations within range. If you know the identity of these cell towers, it is possible to calculate a phone's physical location by using various databases that contain the cell towers' identity and their exact geographical location. Cell tower triangulation doesn't need satellites, so unlike GPS, it works indoors. However, it is not as accurate as GPS, because its accuracy depends on how closely cell towers are spaced in the area you are in—it works best in densely populated areas where the cell towers are close together.
Author's Note: The first generation iPhone was not equipped with a GPS receiver, and cell tower triangulation does not apply to the iPod Touch because it's not a cellular phone.

Yet a third method is to rely on Wi-Fi triangulation. Using this method, the device connects to a Wi-Fi network and checks the service provider against databases to determine the location serviced by the provider. There's no triangulation and no satellites involved, so this method works wherever the device can connect to a Wi-Fi network, but it's also the least accurate of the three methods.

Core Location Framework

On the iPhone, Apple provides the Core Location framework to help you determine your physical location. The beauty of this framework is that it makes use of all three approaches mentioned here; which method it actually uses at any given time is totally transparent to developers, who need only specify the accuracy they need, and Core Location will go about determining the best way to obtain those results.
Sound amazing? It is. The rest of this article shows how you can do this in code.




Obtaining Location Coordinates

Using Xcode, create a new View-based Application project and name it LBS. In the new project, double-click on the LBSViewController.xib file to edit it in Interface Builder.
Populate the View window with the following views (see Figure 1):
 
Figure 1. Example Location View: Populate the View window with TextField and Label views.
  • Label
  • TextField
Right-click on the Frameworks group in Xcode and select Add → Existing Frameworks.... Select Framework/CoreLocation.framework.
Add the statements in bold text in the following code to the LBSViewController.h file:
#import 
#import 
@interface LBSViewController : UIViewController
 {
IBOutlet UITextField *latitudeTextField;
IBOutlet UITextField *longitudeTextField;
IBOutlet UITextField *accuracyTextField;
CLLocationManager *lm;
}
@property (retain, nonatomic) UITextField *latitudeTextField;
@property (retain, nonatomic) UITextField *longitudeTextField;
@property (retain, nonatomic) UITextField *accuracyTextField;
@end
To use the CLLocationManager class, you need to implement the CLLocationManagerDelegate protocol in your view controller class. You also need to create three outlets that you'll connect to the three TextField views in the View window.
Back in Interface Builder, control-click and drag the File's Owner item to each of the three TextField views, then select latitudeTextField, longitudeTextField, and accuracyTextField, respectively.
Insert the statements shown in bold text below into the LBSViewController.m file:
#import "LBSViewController.h"
@implementation LBSViewController
@synthesize latitudeTextField, longitudeTextField, accuracyTextField;
- (void) viewDidLoad {
lm = [[CLLocationManager alloc] init];
if ([lm locationServicesEnabled]) {
lm.delegate = self;
lm.desiredAccuracy = kCLLocationAccuracyBest;
lm.distanceFilter = 1000.0f;
[lm startUpdatingLocation];
}
}
- (void) locationManager: (CLLocationManager *) manager
didUpdateToLocation: (CLLocation *) newLocation
fromLocation: (CLLocation *) oldLocation{
NSString *lat = [[NSString alloc] initWithFormat:@"%g",
newLocation.coordinate.latitude];
latitudeTextField.text = lat;
NSString *lng = [[NSString alloc] initWithFormat:@"%g",
newLocation.coordinate.longitude];
longitudeTextField.text = lng;
NSString *acc = [[NSString alloc] initWithFormat:@"%g",
newLocation.horizontalAccuracy];
accuracyTextField.text = acc;
[acc release];
[lat release];
[lng release];
}
- (void) locationManager: (CLLocationManager *) manager
didFailWithError: (NSError *) error {
NSString *msg = [[NSString alloc]
initWithString:@"Error obtaining location"];
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:@"Error"
message:msg
delegate:nil
cancelButtonTitle: @"Done"
otherButtonTitles:nil];
[alert show];
[msg release];
[alert release];
}
- (void) dealloc{
[lm release];
[latitudeTextField release];
[longitudeTextField release];
[accuracyTextField release];
[super dealloc];
}
The preceding code creates an instance of the CLLocationManager class when the View is loaded. Before using the object, you should check to see whether the user has enabled location services on the device. If so, you can then proceed to specify the desired accuracy using the desiredAccuracy property. Use the following constants to specify the accuracy that you want:
  • kCLLocationAccuracyBest
  • kCLLocationAccuracyNearestTenMeters
  • kCLLocationAccuracyHundredMeters
  • kCLLocationAccuracyKilometer
  • kCLLocationAccuracyThreeKilometers
You should note that while you're perfectly free to specify the best accuracy all the time, the actual accuracy—whatever you select—is not guaranteed. In addition, specifying a location with greater accuracy than you need takes up significant device time and battery power.
The distanceFilter property allows you to specify the distance a device must move laterally before it should generate a location update. The unit for this property is in meters, relative to its last position. If you want to be notified of all movements, use the kCLDistanceFilterNone constant. Finally, you start the location manager using the startUpdatingLocation method.
 
Figure 2. Location Test: When you test the sample application on the iPhone Simulator, you'll always get these (fixed) values.
To obtain location information, you need to handle two events:
  • locationManager:didUpdateToLocation:fromLocation:
  • locationManager:didFailWithError:
When a new location value is available, the device fires the locationManager:didUpdateToLocation:fromLocation: event. If the location manager cannot determine a location value, it will fire the locationManager:didFailWithError: event.
When the device can determine a location, you want to display its latitude, longitude, and accuracy, which you do using the CLLocation object. This object's horizontalAccuracy property specifies the radius of accuracy, in meters.
Press Command-r to test the application on the iPhone Simulator. Figure 2 shows the simulator displaying the latitude and longitude of the location returned. It also shows the accuracy of the result.
Author's Note: For the simulator, the device always reports a fixed position. There is no prize for guessing correctly where this position refers to.





Displaying Maps

While obtaining the location coordinates of a position is interesting, such information is much more useful if you can visually locate it on a map. Fortunately, the iPhone SDK 3.0 ships with the Map Kit API, which makes displaying Google Maps in your application a snap. Here's an example.
Using the same project you created in the previous section, add a Button view to the View window in the LBSViewController.xib file (see Figure 3).
 
Figure 3. View Map Button: Here's how the sample project looks after adding a "View Map" Button view to the View window.
Right-click on the Frameworks group in Xcode and add a new framework called MapKit.framework.
Add the statement shown below in bold to the LBSViewController.h file:
#import 
#import 
#import 
@interface LBSViewController : UIViewController
 {
IBOutlet UITextField *accuracyTextField;
IBOutlet UITextField *latitudeTextField;
IBOutlet UITextField *longitudeTextField;
CLLocationManager *lm;
MKMapView *mapView;
}
@property (retain, nonatomic) UITextField *accuracyTextField;
@property (retain, nonatomic) UITextField *latitudeTextField;
@property (retain, nonatomic) UITextField *longitudeTextField;
-(IBAction) btnViewMap: (id) sender;
@end
Back in Interface Builder, control-click, and drag the Button view to the File's Owner item, and then select btnViewMap:.
In the LBSViewController.m file, add the statements in bold from the following code:
-(IBAction) btnViewMap: (id) sender {
[self.view addSubview:mapView];
}
- (void) viewDidLoad {
lm = [[CLLocationManager alloc] init];
lm.delegate = self;
lm.desiredAccuracy = kCLLocationAccuracyBest;
lm.distanceFilter = 1000.0f;
[lm startUpdatingLocation];
mapView = [[MKMapView alloc] initWithFrame:self.view.bounds];
mapView.mapType = MKMapTypeHybrid; 
}
- (void) locationManager: (CLLocationManager *) manager
didUpdateToLocation: (CLLocation *) newLocation
fromLocation: (CLLocation *) oldLocation{
NSString *lat = [[NSString alloc] initWithFormat:@"%g",
newLocation.coordinate.latitude];
latitudeTextField.text = lat;
NSString *lng = [[NSString alloc] initWithFormat:@"%g",
newLocation.coordinate.longitude];
longitudeTextField.text = lng;
NSString *acc = [[NSString alloc] initWithFormat:@"%g",
newLocation.horizontalAccuracy];
accuracyTextField.text = acc;
[acc release];
[lat release];
[lng release];
MKCoordinateSpan span;
span.latitudeDelta=.005;
span.longitudeDelta=.005;
MKCoordinateRegion region;
region.center = newLocation.coordinate;
region.span=span;
[mapView setRegion:region animated:TRUE]; 
}
- (void) dealloc{
[mapView release];
[lm release];
[latitudeTextField release];
[longitudeTextField release];
[accuracyTextField release];
[super dealloc];
}
 
Figure 4. Mapped Location: Display the map of the location reported by Core Location framework.
Basically, the preceding code:
  • Creates an instance of the MKMapView class when the view has loaded, and sets the map type (hybrid: map and satellite in this case) to display.
  • Adds the mapView object to the current view when a user taps the View Map button.
  • Zooms into the location using the mapView object's setRegion: method whenever the location information gets updated.
Press Command-r to test the application on the iPhone Simulator. Now, tapping on the View Map button will show a map containing the location reported by the location manager (see Figure 4).
Because the simulator always provides the same fixed location, this is as far as you can go without testing on a real device. When you do that, you'll be able to see the map update itself dynamically as you move the device around. Be sure to alter the distanceFilter property to a smaller number so that you will be able to track small changes in distance.
As you've seen, the iPhone SDK's Core Location framework makes it easy to implement location-based services. In addition, the MapKit (also in the iPhone 3.0 SDK) makes displaying maps a snap. If you have not yet had an opportunity to build a location-based application, you're coming to the field at the right time. With all these new features, now is the perfect time to begin!

iPhone Coding – Turbo Charging Your Apps With NSOperation

What do I mean by this? Well, I am essentially talking about multithreading your application.  If you don’t know what is meant by multithreading, I suggest you read up on it and return to this post OR don’t worry about it because you don’t need much threading knowledge for this tutorial.  Let’s dig in and I’ll give you an example of the problem.

The Problem

When you create an application, the iPhone spawns a new process containing the main thread of your application.  All of interface components are run inside of this thread (table views, tab bars, alerts, etc…).  At some point in your application, you will want to populate these views with data.  This data can be retrieved from the disk, the web, a database, etc… The problem is: How do you efficiently load this data into your interface while still allowing the user to have control of the application.
Many applications in the store simply ‘freeze’ while their application data is being loaded.  This could be anywhere from a tenth of a second to much longer. Even the smallest amount of time is noticeable to the user.
Now, don’t get me wrong, I am not talking about applications that display  a loading message on the screen while the data populates.  In most cases, this is acceptable, but can not be done effectively unless the data is loaded in another thread besides the main one.
Here is a look at the application we will be creating today:

Let’s take a look at the incorrect way to load data into a UITableView from data loaded from the web.   The example below reads a plist file from icodeblog.com containing 10,000 entries and populates a UITableView with those entries.  This happens when the user presses the “Load” button.

@implementation RootViewController
@synthesize array;
 
- (void)viewDidLoad {
    [super viewDidLoad];
 
    /* Adding the button */
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Load"
        style:UIBarButtonItemStyleDone
        target:self
        action:@selector(loadData)];
 
    /* Initialize our array */
    NSMutableArray *_array = [[NSMutableArray alloc] initWithCapacity:10000];
    self.array = _array;
    [_array release];
}
 
// Fires when the user presses the load button
- (void) loadData {
 
    /* Grab web data */
    NSURL *dataURL = [NSURL URLWithString:@"http://icodeblog.com/samples/nsoperation/data.plist"];
 
    NSArray *tmp_array = [NSArray arrayWithContentsOfURL:dataURL];
 
    /* Populate our array with the web data */
    for(NSString *str in tmp_array) {
        [self.array addObject:str];
    }
 
    /* reload the table */
    [self.tableView reloadData];
}
 
#pragma mark Table view methods
 
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}
 
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [self.array count];
}
 
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
 
    static NSString *CellIdentifier = @"Cell";
 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                reuseIdentifier:CellIdentifier] autorelease];
    }
 
    /* Display the text of the array */
    [cell.textLabel setText:[self.array objectAtIndex:indexPath.row]];
 
    return cell;
}
 
- (void)dealloc {
    [super dealloc];
    [array release];
}
 
@end
“Looks good to me”, you may say.  But that is incorrect.  If you run the code above, pressing the “Load” button will result in the interface ‘freezing’ while the data is being retrieved from the web.  During that time, the user is unable to scroll or do anything since the main thread is off downloading data.

About NSOperationQueue And NSOperation

Before I show you the solution, I though I would bring you up to speed on NSOperation.
According to Apple…
The NSOperation and NSOperationQueue classes alleviate much of the pain of multi-threading, allowing you to simply define your tasks, set any dependencies that exist, and fire them off. Each task, or operation, is represented by an instance of an NSOperation class; the NSOperationQueue class takes care of starting the operations, ensuring that they are run in the appropriate order, and accounting for any priorities that have been set.
The way it works is, you create a new NSOperationQueue and add NSOperations to it.  The NSOperationQueue creates a new thread for each operation and runs them in the order they are added (or a specified order (advanced)).  It takes care of all of the autorelease pools and other garbage that gets confusing when doing multithreading and greatly simplifies the process.
Here is the process for using the NSOperationQueue.
  1. Instantiate a new NSOperationQueue object
  2. Create an instance of your NSOperation
  3. Add your operation to the queue
  4. Release your operation
There are a few ways to work with NSOperations.  Today, I will show you the simplest one: NSInvocationOperation.  NSInvocationOperation is a subclass of NSOperation which allows you to specify a target and selector that will run as an operation.
Here is an example of how to execute an NSInvocationOperation:
NSOperationQueue *queue = [NSOperationQueue new];
 
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self
    selector:@selector(methodToCall)
    object:objectToPassToMethod];
 
[queue addOperation:operation];
[operation release];
This will call the method “methodToCall” passing in the object “objectToPassToMethod” in a separate thread.  Let’s see how this can be added to our code above to make it run smoother.

The Solution

Here we still have a method being fired when the user presses the “Load” button, but instead of fetching the data, this method fires off an NSOperation to fetch the data.  Check out the updated code.

Correct (Download the source code here)

@implementation RootViewController
@synthesize array;
 
- (void)viewDidLoad {
    [super viewDidLoad];
 
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Load"
       style:UIBarButtonItemStyleDone
       target:self
       action:@selector(loadData)];
 
    NSMutableArray *_array = [[NSMutableArray alloc] initWithCapacity:10000];
    self.array = _array;
    [_array release];
}
 
- (void) loadData {
 
    /* Operation Queue init (autorelease) */
    NSOperationQueue *queue = [NSOperationQueue new];
 
    /* Create our NSInvocationOperation to call loadDataWithOperation, passing in nil */
    NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self
        selector:@selector(loadDataWithOperation)
        object:nil];
 
    /* Add the operation to the queue */
    [queue addOperation:operation];
    [operation release];
}
 
- (void) loadDataWithOperation {
    NSURL *dataURL = [NSURL URLWithString:@"http://icodeblog.com/samples/nsoperation/data.plist"];
 
    NSArray *tmp_array = [NSArray arrayWithContentsOfURL:dataURL];
 
    for(NSString *str in tmp_array) {
        [self.array addObject:str];
    }
 
    [self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES];
}
 
#pragma mark Table view methods
 
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}
 
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [self.array count];
}
 
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
 
    static NSString *CellIdentifier = @"Cell";
 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }
 
    [cell.textLabel setText:[self.array objectAtIndex:indexPath.row]];
 
    return cell;
}
 
- (void)dealloc {
    [super dealloc];
    [array release];
}
As you can see, we haven’t added much code here, but we have GREATLY improved the overall user experience.  So, what did I do exactly?
  1. Moved all of the processing (downloading) code from the loadData method to another method that could be run asynchronously
  2. Created a new instance of NSOperationQueue by calling [NSOperationQueue new]
  3. Created an NSInvocationOperation to call our method loadDataWithOperation
  4. Added the operation to the queue
  5. Released the operation
  6. When the Data has been downloaded, we reload the table data in the main thread since it’s a UI manipulation
One thing to note here is we never actually tell the operation to run.  This is handled automatically in the queue.   The queue will figure out the optimal time run the operation and do it for you.
Now that you have your downloading and processing in a separate thread, you are now free to add things such as a loading view.
I will be expanding on this tutorial in the coming week and showing you how to cache data and display old data to the user while the new is loading.  This is a popular technique used in many Twitter and News applications.
That concludes today’s tutorial.

AUTOMATIC REFERENCE COUNTING IN OBJECTIVE-C

Automatic Reference Counting (ARC) largely removes the burden of manual memory management, not to mention the chore of tracking down bugs caused by leaking or over-released objects! Despite its awesomeness, ARC does not let you ignore memory management altogether.
This post covers the following key aspects of ARC to help you get up and running quickly.
  1. Reference Counted Memory: Quick Revision
  2. How Automatic Reference Counting Works
  3. Enabling ARC in Your Project
  4. New Rules Enforced by ARC
  5. ARC Qualifiers – Declared Properties
  6. ARC Qualifiers – Regular Variables
  7. Migrating Existing Projects to ARC
  8. Including Code that is not ARC Compliant
  9. Should I Use ARC?

What Has Changed?

ARC Related changes to Xcode 4.2
In the time before ARC, you had to manually retain/release/autorelease objects to ensure they would “stick around” for as long as you needed them. Forgetting to send retain to an object, or releasing it too many times would cause your app to leak memory or crash.
In Xcode 4.2, in addition to syntax checking as you type, the new Apple LLVM compiler makes it possible to offload the burden of manual memory management to the compiler, introspecting your code to decide when to release objects. Apple’s documentation describes ARC as follows:
“Automatic Reference Counting (ARC) is a compiler-level feature that simplifies the process of managing object lifetimes (memory management) in Cocoa applications.”
This feature makes the memory management trivial most of the time, but you still need to take some responsibility for how your classes manage references to other objects.
Let’s start at the beginning …

Reference Counted Memory: Quick Review

Manually managed, reference counted memory works in iOS as follows: when creating an object using alloc/init (or other similar method), the object is returned with a retainCount of 1, meaning you havetaken ownership of the object.
1
2
3
NSObject *obj = [[NSObject alloc] init];
// do some stuff
[obj release];
In between alloc/init’ing an object (i.e. taking ownership) and releasing an object (i.e. relinquishing ownership), you can do with it as you wish, safe in the knowledge the object will not be deallocated whilst still in use.
Similarly, by adding an object to an autorelease pool, your object will stick around when needed and be deallocated sometime in the future when no longer needed.
1
2
3
4
-(NSObject*) someMethod {
  NSObject *obj = [[[NSObject alloc] init] autorelease];
  return obj; // will be deallocated by autorelease pool later
}

How Automatic Reference Counting Works

Most programmers new to iOS have trouble getting their heads around reference counted memory. ARC is a pre-compilation step that adds retain/release/autorelease statements to your code for you.
This is not Garbage Collection, and reference counted memory has not disappeared, it has simply been automated. It may sound like a bit of an after thought, but considering how many features in Objective-C are implemented by pre-processing source files before compiling, ARC is really par for the course.
When writing code with ARC enabled your code will look like this:
1
2
NSObject *obj = [[NSObject alloc] init];
// do some stuff
The ARC pre-compilation step will auto-magically turn it into this:
1
2
3
NSObject *obj = [[NSObject alloc] init];
// do some stuff
[obj release]; // **Added by ARC**
The diagram below (from Apple’s documentation) seems to imply that writing operative code takes almost as long to write as retain/release logic. Whilst this is not true for experienced Objective-C coders, it is probably a conservative estimate if you are new to Objective-C. Also, when they do pop-up, memory problems can be a PITA to track down.
Source: Programming With ARC Release Notes

Enabling ARC in Your Project

To enable ARC simply set the Objective-C Automatic Reference Counting option in your Xcode project’s Build Settings to YES. Behind the scenes this sets the -fobjc-arc compiler flag that enables ARC.

New Rules Enforced by ARC

There are a few rules you need to abide by in order to compile with ARC enabled.
1. Alloc/Init Objects
As described above, creating objects is done as before, however you must not make anyretain/release/autorelease/retainCount calls. You also cannot be sneaky by calling their selectors indirectly: use of @selector(retain) and @selector(release) are prohibited.
2. Dealloc Methods
Generally these will be created for you. You must not make a dealloc call directly. However you can still create a custom dealloc method if you need to release resources other than instance variables. When creating a custom dealloc method, do not call the [super dealloc] method. This will be done for you and is enforced by the compiler.
3. Declared Properties
Before ARC, we told the compiler how to memory manage declared public properties using theassign/retain/copy parameters with the @property directive. These parameters are no longer used in ARC. Instead we have the weak/strong parameters to tell the compiler how we want our properties treated.
4. Object Pointers in C Structures
This is also a taboo. The docs suggest storing them in a class instead of a struct. This makes sense since they would otherwise be unknown to ARC. It might cause extra some migration headaches. However, ARC can be disabled on a file by file basis. See the section on “Including Code that is not ARC Compliant” below.
5. Casual Casting Between id and void*
Casting between id and void* data types is frequently done when handing objects between Core Foundation’s C library functions and Foundation Kit’s Objective-C library methods. This is known asToll Free Bridging.
With ARC you must provide hints/qualifiers to tell the compiler when CF objects are moving into and out of its control for memory management. These qualifiers include __bridge, __bridge_retain and__bridge_transfer. Also you still need to call CFRetain and CFRelease to memory manage Core Foundation objects.
This is a more advanced topic, so if you don’t know what CF objects are, don’t worry for now.
6. @autoreleasepool instead of NSAutoReleasePool
ARC compliant code must not use NSAutoReleasePool objects, instead use the @autoreleasepool{}blocks. A good example is in the main.m file of any ARC compliant/migrated project.
1
2
3
4
5
6
int main(int argc, char *argv[])
{
  @autoreleasepool {
    return UIApplicationMain(argc, argv, nil, NSStringFromClass([ExampleAppDelegate class]));
  }
}
7. Other Gotchas
Zone based memory is gone (apparently it’s not in the runtime anymore either); you cannot use NSAllocateObject or NSDeallocateObject.

ARC Qualifiers – Declared Properties

As programmers, we are used to making decisions like whether to make something a variable or a constant, locally or globally defined, etc. So too, we must decide how our properties relate to other objects. We use the strong/weak qualifiers to notify the compiler of these relationships.
Strong References
A strong reference is a reference to an object that stops it from being deallocated. In other words it creates a owner relationship. Whereas previously you would do this:
1
2
// Non-ARC Compliant Declaration
@property(retain) NSObject *obj;
Under ARC we do the following to ensure a class instance takes an ownership interest a referenced object (i.e. so it cannot be deallocated until the owner is).
1
2
// ARC Compliant Declaration
@property(strong) NSObject *obj;
Weak References
A weak reference is a reference to an object that does not stop it from being deallocated. In other words, it does not create an owner relationship. Whereas previously you would do this:
1
2
// Non-ARC Compliant Declaration
@property(assign) NSObject *parentObj;
Under ARC you would do the following to ensure you do not “own” the object being referred to (e.g. typically a child object should not own its parent, so we would use a weak reference).
1
2
// ARC Compliant Declaration
@property(weak) NSObject *parentObj;

ARC Qualifiers – Regular Variables

Variable Qualifiers
The above examples illustrate declaring how our declared properties should be managed. For regular variables we have:
1
2
3
4
__strong
__weak
__unsafe_unretained
__autoreleasing
Generally speaking, these extra qualifiers don’t need to be used very often. You might first encounter these qualifiers and others when using the migration tool. For new projects however, you generally you won’t need them and will mostly use strong/weak with your declared properties.
  • __strong – is the default so you don’t need to type it. This means any object created usingalloc/init is retained for the lifetime of its current scope. The “current scope” usually means the braces in which the variable is declared (i.e. a method, for loop, if block, etc…)
  • __weak – means the object can be destroyed at anytime. This is only useful if the object is somehow strongly referenced somewhere else. When destroyed, a variable with __weak is set tonil.
  • __unsafe_unretained – is just like __weak but the poiner is not set to nil when the object is deallocated. Instead the pointer is left dangling (i.e. it no longer points to anything useful).
  • __autoreleasing, not to be confused with calling autorelease on an object before returning it from a method, this is used for passing objects by reference, for example when passing NSError objects by reference such as [myObject performOperationWithError:&tmp];
Source: LLVM Clang Objective-C Automatic Reference Counting Documentation
NB: We have found @property declarations using ‘retain’ with ARC enabled (i.e. instead of ‘strong’) do not cause compiler warnings and yield the same compiled result. This could change in future so stick to ‘strong’ for clarity.

Migrating Existing Projects to ARC

Xcode 4.2 provides a conversion tool that migrates existing code to ARC, and helps you manually convert code that cannot be automatically migrated.
1. Open your non-ARC compliant project and go to Edit > Refactor > Convert to Objective-C ARC.

2. Select the build targets and contained files to convert (you exclude files in laters steps too)

3. Run Precheck and press next.

NB: When you press next the LLVM compiler will build the project in order to analyse it. If your project has any errors, you cannot proceed to the next step. If you are opening a project from a previous Xcode version for the first time, remember to Clean.
4. Inspect the proposed changes and choose to include/exclude any files. Then press save.

NB: You will also be notified of any files that cannot be migrated. Not all files (including existing libraries) need to be migrated. ARC works on a file by file basis, so see the section below on how to exclude them at compile time.
5. The migration tool will automagically set the compiler flag enabling ARC to on. You can confirm this in your project’s build settings (search for ‘reference counting’).

Including Code that is not ARC Compliant

According to Apple’s documentation: “ARC interoperates with manual reference counting code on a per-file basis. If you want to continue using manual reference counting for some files, you can do so.”
This means some files can use ARC and some files can be spared from it’s magical grasp. Here are the steps for bulk excluding files from ARC at compile time. At the time of writing, many popular libraries are not ARC ready, to get around this follow these steps:
  1. Click on your Project in the Xcode project tree
  2. Click on the Target
  3. Select the Build Phases tab
  4. Expand the Compile Sources section
  5. Select one or more files you want to exclude from ARC
  6. Press the return key
  7. Type -fno-objc-arc
  8. Press the return key again
  9. Each file selected now has a -fno-objc-arc compiler flag set and will be excluded from ARC

Should I Use ARC?

If you are new to Objective-C, you will certainly welcome it. There is more than enough to learn at first without worrying about reference counted memory. Once you start using existing libraries though, you are sure to experience pain until you get accustomed to explicitly excluding them from ARC pre-compilation.
If you’re already coding happily without ARC, you’re probably thinking “I don’t need it!” This may be the right answer for you — for now. Most popular libraries haven’t been converted to ARC and it does not play well with Core Foundation classes. There are specific limitations when using CF classes listed in Apple’s documentation, and a bunch of extra qualifiers are needed to make Toll Free Bridging work when migrating code.
From what I have seen and read, ARC is ready to use right now. However, it is probably best left to new projects until you get familiar with it. Whilst ARC is backwards compatible with iOS 4.0 onwards, weak references are only supported in iOS 5.0 onwards — possibly another reason not to migrate everything just yet (there are work arounds to this, see the “Resources” section at the bottom of this post).
Performance wise, some early reports claim ARC can make your projects faster – possibly due to less reliance on autorelease. However, you can also do that yourself by “coding better” and using retain/release more judiciously. But that’s just the point: ARC should always choose the most optimised approach for your code automatically.
Right now there is some pain involved in moving to ARC, but not a lot. At Long Weekend we will leave it for new projects at first, but this is Apple’s “new” recommended approach, so you can be sure future design decisions will build on ARC and move further away from manual reference counting.

push notifications

In iOS, apps can’t do a lot in the background. Apps are only allowed to do limited set of activities so battery life is conserved.
But what if something interesting happens and you wish to let the user know about this, even if they’re not currently using your app?
For example, maybe the user received a new tweet, their favorite team won the game, or their dinner is ready. Since the app isn’t currently running, it cannot check for these events.
Luckily, Apple has provided a solution to this. Instead of your app continuously checking for events or doing work in the background, you can write a server-side component to do this instead.
And when an event of interest occurs, the server-side component can send the app a push notification! There are three things a push notification can do:
  • Display a short text message
  • Play a brief sound
  • Set a number in a badge on the app’s icon
You can combine these however you see fit; for example, play a sound and set the badge but not display a message.
In this 2-part tutorial series, you’ll get to try this out for yourself by making a simple app that uses APNS!
In this first part, you’ll learn how to configure your app to receive push notifications and receive a test message.
This tutorial is for intermediate or advanced iOS developers. If you are still a beginner to iOS, you should check out some of the other tutorials on this site first. Also, it’s highly recommended that you review these two tutorials first (or have equivalent knowledge):
Without further ado, let’s push through this!

Brief Overview

Getting push to work for your app takes quite a bit of effort. This is a puzzle with many pieces. Here is an overview:
Apple Push Notification Services (APNS) Overview
  1. An app enables push notifications. The user has to confirm that he wishes to receive these notifications.
  2. The app receives a “device token”. You can think of the device token as the address that push notifications will be sent to.
  3. The app sends the device token to your server.
  4. When something of interest to your app happens, the server sends a push notification to the Apple Push Notification Service, or APNS for short.
  5. APNS sends the push notification to the user’s device.
When the user’s device receives the push notification, it shows an alert, plays a sound and/or updates the app’s icon. The user can launch the app from the alert. The app is given the contents of the push notification and can handle it as it sees fit.
Are push notifications still worth it now that we have OS 4 with its local notifications and multitasking? You bet!
Local notifications are limited to scheduling timed events and unlimited background processing is only available to apps that do VOIP, navigation or background audio. If you want to notify the users of your app about external events while the app is closed, you still need push notifications.
In this tutorial, I will explain in detail how the push notification system works and how to build push into your own app. There is a lot to explain, so take your time to let it all sink in.

What You Need for Push Notifications

To add push notifications to your app, you need:
An iPhone or iPad. Push notifications do not work in the simulator, so you will need to test on the device.
An iOS Developer Program membership. You need to make a new App ID and provisioning profile for each app that uses push, as well as an SSL certificate for the server. You do this at the iOS Provisioning Portal.
If you want to follow along with the examples in this tutorial, you will need to create your own provisioning profile and SSL certificate; you cannot use mine. Because it’s important to get the certificate right, I’ll explain in detailed steps how to obtain one.
A server that is connected to the internet. Push notifications are always sent by a server. For development you can use your Mac as the server (which we’ll do in this tutorial) but for production use, you need at least something like a VPS (Virtual Private Server).
A cheap shared hosting account is not good enough. You need to be able to run a background process on the server, install an SSL certificate, and be able to make outgoing TLS connections on certain ports.
Most shared hosting providers do not let you do this, although they might if you ask. However, I really recommend using a VPS host such as Linode.

Anatomy of a Push Notification

Your server is responsible for creating the push notification messages, so it’s useful to know what they look like.
A push notification is a short message that consists of the device token, a payload, and a few other bits and bytes. The payload is what we are interested in, as that contains the actual data we will be sending around.
Your server should provide the payload as a JSON dictionary. The payload for a simple push message looks like this:
{
 "aps":
 {
  "alert": "Hello, world!",
  "sound": "default"
 }
}
For the JSON uninitiated, a block delimited by curly { } brackets contains a dictionary that consists of key/value pairs (just like an NSDictionary).
The payload is a dictionary that contains at least one item, “aps”, which itself is also a dictionary. In our example, “aps” contains the fields “alert” and “sound”. When this push notification is received, it shows an alert view with the text “Hello, world!” and plays the standard sound effect.
There are other items you can add to the “aps” section to configure the notification. For example:
{
 "aps":
 {
  "alert":
  {
   "action-loc-key": "Open",
   "body": "Hello, world!"
  },
  "badge": 2
 }
}
Now “alert” is a dictionary of its own. The “action-loc-key” provides an alternative text for the “View” button. The “badge” field contains the number that will be shown on the application icon. This notification will not play a sound.
There are many more ways to configure the JSON payload. You can change the sound that is played, you can provide localized text, and you can add fields of your own. For more information, check out the official Local and Push Notification Programming Guide.
Push notifications are intended to be small; the payload size can be no more than 256 bytes. That leaves you about as much room as fits in an SMS message or a tweet. A smart push server won’t waste space on newlines and whitespace and generates something that looks like:
{"aps":{"alert":"Hello, world!","sound":"default"}}
It’s less easy to read for us humans, but it saves enough bytes to make it worth it. Push notifications whose payload exceeds 256 bytes will not be accepted by APNS.

Push Notification Gotchas

Push Notifications Are Unreliable!
Push Notifications Are Unreliable!
They are not reliable! There is no guarantee that push notifications will actually be delivered, even if the APNS server accepted them.
As far as your server is concerned, push notifications are fire-and-forget; there is no way to find out what the status of a notification is after you’ve sent it to APNS. The delivery time may also vary, from seconds up to half an hour.
Also, the user’s iPhone may not be able to receive push notifications all the time. They could be on a WiFi network that does not allow connections to be made to APNS because the required ports are blocked. Or the phone could be turned off.
APNS will try to deliver the last notification it received for that device when it comes back online, but it will only try for a limited time. Once it times out, the push notification will be lost forever!
After looking at the APNS Server Bill
After looking at the APNS Server Bill
They can be expensive! Adding push functionality to your app is fairly easy and inexpensive if you own the data, but can be expensive if you have a lot of users or data you need to poll.
For example, it’s no problem if you want to notify your users when the contents of your own RSS feed change. Because you control that RSS feed and know when it changes — when you update the content on your web site — your server can send out the notifications at the right moment.
But what if your app is an RSS feed reader that allows users to put in their own URLs? In that case you need to come up with some mechanism to detect updates to those feeds.
In practice this means your server will need to continuously poll those feeds for changes. If you have a lot of users, you may have to install a bunch of new servers to handle all that processing and bandwidth. For apps such as these, push can become quite expensive and may not be worth it for you.
OK, enough theory. It’s time to learn how to do this push thing. Before we can get to the good stuff – programming! – there is some boring set-up work to be done on the iOS Provisioning Portal, so let’s get that over with as quickly as possible.

Provisioning Profiles and Certificates, Oh My!

APNS needs a certificate!
APNS needs a certificate!
To enable push notifications in your app, it needs to be signed with a provisioning profile that is configured for push. In addition, your server needs to sign its communications to APNS with an SSL certificate.
The provisioning profile and SSL certificate are closely tied together and are only valid for a single App ID. This is a protection that ensures only your server can send push notifications to instances of your app, and no one else.
As you know, apps use different provisioning profiles for development and distribution. There are also two types of push server certificates:
  • Development. If your app is running in Debug mode and is signed with the Development provisioning profile (Code Signing Identity is “iPhone Developer”), then your server must be using the Development certificate.
  • Production. Apps that are distributed as Ad Hoc or on the App Store (when Code Signing Identify is “iPhone Distribution”) must talk to a server that uses the Production certificate. If there is a mismatch between these, push notifications cannot be delivered to your app.
In this tutorial, we won’t bother with the distribution profiles and certificates and just use the ones for development.

Generating the Certificate Signing Request (CSR)

Remember how you had to go to the iOS Provisioning Portal and make a Development Certificate after you signed up for the iOS Developer Program? If so, then these next steps should be familiar. Still, I advise you to follow them exactly. Most of the problems people have with getting push notifications to work are due to problems with the certificates.
Digital certificates are based on public-private key cryptography. You don’t need to know anything about cryptography to use certificates, but you do need to be aware that a certificate always works in combination with a private key.
The certificate is the public part of this key pair. It is safe to give it to others, which is exactly what happens when you communicate over SSL. The private key, however, should be kept… private. It’s a secret. Your private key is nobody’s business but your own. It’s important to know that you can’t use the certificate if you don’t have the private key.
Whenever you apply for a digital certificate, you need to provide a Certificate Signing Request, or CSR for short. When you create the CSR, a new private key is made that is put into your keychain. You then send the CSR to a certificate authority (in this case that is the iOS Developer Portal), which will generate the SSL certificate for you based on the information in the CSR.
Open Keychain Access on your Mac (it is in Applications/Utilities) and choose the menu option Request a Certificate from a Certificate Authority….
Requesting a certificate with Keychain Access
If you do not have this menu option or it says “Request a Certificate from a Certificate Authority with key”, then download and install the WWDR Intermediate Certificate first. Also make sure no private key is selected in the main Keychain Access window.
You should now see the following window:
Generating a certificate sign request with Keychain Access
Enter your email address here. I’ve heard people recommended you use the same email address that you used to sign up for the iOS Developer Program, but it seems to accept any email address just fine.
Enter “PushChat” for Common Name. You can type anything you want here, but choose something descriptive. This allows us to easily find the private key later.
Check Saved to disk and click Continue. Save the file as “PushChat.certSigningRequest”.
If you go to the Keys section of Keychain Access, you will see that a new private key has appeared in your keychain. Right click it and choose Export.
Exporting your private key with keychain access
Save the private key as “PushChatKey.p12” and enter a passphrase.
For the convenience of this tutorial, I used the passphrase “pushchat” to protect the p12 file but you should really choose something that is less easy to guess. The private key needs to be a secret, remember? Do choose a passphrase that you can recall, or you won’t be able to use the private key later.

Making the App ID and SSL certificate

Log in to the iOS Provisioning Portal.
First, we are going to make a new App ID. Each push app needs its own unique ID because push notifications are sent to a specific application. (You cannot use a wildcard ID.)
Go to App IDs in the sidebar and click the New App ID button.
Creating a new App ID
I filled in the fields as follows:
  • Description: PushChat
  • Bundle Seed ID: Generate New (this is the default option)
  • Bundle Identifier: com.hollance.PushChat
It is probably best if you choose your own Bundle Identifier here – com.yoursite.PushChat – instead of using mine. You will need to set this same bundle ID in your Xcode project.
In a few moments, we will generate the SSL certificate that your push server uses to make a secure connection to APNS. This certificate is linked with your App ID. Your server can only send push notifications to that particular app, not to any other apps.
After you have made the App ID, it shows up like this in the list:
List of App IDs in the iOS Provisioning Portal
In the “Apple Push Notification service” column, there are two orange lights that say “Configurable for Development” and “Configurable for Production”. This means our App ID can be used with push, but we still need to set this up. Click on the Configure link to open the Configure App ID screen.
Configuring your App ID in the iOS Provisioning Portal
Check the Enable for Apple Push Notification service box and click on the Configure button for the Development Push SSL Certificate. The “Apple Push Notification service SSL Certificate Assistant” pops up:
Uploading your CSR with the SSL Assistant
The first thing it asks you is to generate a Certificate Signing Request. We already did that, so click Continue. In the next step you upload the CSR. Choose the CSR file that you generated earlier and click Generate.
Generating a Certificate with the SSL Assistant
It takes a few seconds to generate the SSL certificate. Click Continue when it’s done.
Downloading a certificate with the SSL assistant
Now click Download to get the certificate – it is named “aps_developer_identity.cer”. Click Done to close the assistant and return to the Configure App ID screen.
Screenshot after the SSL Assistant is Complete
As you can see, we have a valid certificate and push is now available for development. You can download the certificate again here if necessary. The development certificate is only valid for 3 months.
When you are ready to release your app, repeat this process for the production certificate. The steps are the same.
Note: The production certificate remains valid for a year, but you want to renew it before the year is over to ensure there is no downtime for your app.
You don’t have to add the certificate to your Keychain, although you could if you wanted to by double-clicking the downloaded aps_developer_identity.cer file. If you do, you’ll see that it is now associated with the private key.

Making a PEM file

So now we have three files:
  • The CSR
  • The private key as a p12 file (PushChatKey.p12)
  • The SSL certificate, aps_developer_identity.cer
Store these three files in a safe place. You could throw away the CSR but in my opinion it is easier to keep it. When your certificate expires, you can use the same CSR to generate a new one. If you were to generate a new CSR, you would also get a new private key. By re-using the CSR you can keep using your existing private key and only the .cer file will change.
We have to convert the certificate and private key into a format that is more usable for us. Because the push part of our server will be written in PHP, we will combine the certificate and the private key into a single file that uses the PEM format.
The specifics of what PEM is doesn’t really matter (in fact, I have no idea) but it makes it easier for PHP to use our certificate. If you write your push server in another language, these following steps may not apply to you.
We’re going to use the command-line OpenSSL tools for this. Open a Terminal and execute the following steps.
Go to the folder where you downloaded the files, in my case the Desktop:
$ cd /Users/matthijs/Desktop
Convert the .cer file into a .pem file:
$ openssl x509 -in aps_developer_identity.cer -inform der
    -out PushChatCert.pem
Convert the private key’s .p12 file into a .pem file:
$ openssl pkcs12 -nocerts -out PushChatKey.pem -in PushChatKey.p12
Enter Import Password: 
MAC verified OK
Enter PEM pass phrase: 
Verifying - Enter PEM pass phrase: 
You first need to enter the passphrase for the .p12 file so that openssl can read it. Then you need to enter a new passphrase that will be used to encrypt the PEM file. Again for this tutorial I used “pushchat” as the PEM passphrase. You should choose something more secure.
Note: if you don’t enter a PEM passphrase, openssl will not give an error message but the generated .pem file will not have the private key in it.
Finally, combine the certificate and key into a single .pem file:
$ cat PushChatCert.pem PushChatKey.pem > ck.pem
At this point it’s a good idea to test whether the certificate works. Execute the following command:
$ telnet gateway.sandbox.push.apple.com 2195
Trying 17.172.232.226...
Connected to gateway.sandbox.push-apple.com.akadns.net.
Escape character is '^]'.
This tries to make a regular, unencrypted, connection to the APNS server. If you see the above response, then your Mac can reach APNS. Press Ctrl+C to close the connection. If you get an error message, then make sure your firewall allows outgoing connections on port 2195.
Let’s try connecting again, this time using our SSL certificate and private key to set up a secure connection:
$ openssl s_client -connect gateway.sandbox.push.apple.com:2195
    -cert PushChatCert.pem -key PushChatKey.pem
Enter pass phrase for PushChatKey.pem: 
You should see a whole bunch of output, which is openssl letting you know what is going on under the hood.
If the connection is successful, you should be able to type a few characters. When you press enter, the server should disconnect. If there was a problem establishing the connection, openssl will give you an error message but you may have to scroll up through the output to find it.
Note that there are actually two different APNS servers: the “sandbox” server that you can use for testing, and the live server that you use in production mode. Above, we used the sandbox server because our certificate is intended for development, not production use.

Making the Provisioning Profile

We’re not done yet in the Provisioning Portal. Go to Provisioning in the sidebar and click New Profile.
Creating a Provisioning Profile in the iOS Provisioning Portal
This is how I filled in the fields:
  • Profile Name: PushChat Development
  • Certificates: check your certificate
  • App ID: PushChat
  • Devices: check your devices
This isn’t different from generating any other provisioning profile, which you’ve probably done before. We’re making a new profile because each push app needs to have its own profile that is connected to the proper App ID.
Click Submit and the profile will be generated. The new profile will be in the Pending state. Refresh the Development Provisioning Profiles page; the status should have changed to Active and you can download the file (named PushChat_Development.mobileprovision).
Add the provisioning profile to Xcode by double-clicking it or dragging it onto the Xcode icon.
If you’re reading to release your app to the public, you will have to repeat this process to make an Ad Hoc or App Store distribution profile.

A Very Basic App

So far things haven’t been really exciting, but those preliminaries are necessary. I wanted to show you in detail how to generate the certificate because it’s not something you do every day and push won’t work without it.
We’ve already established that our certificate is valid by connecting to the sandbox server. Let’s test if we can actually send some push notifications!
Fire up Xcode and choose File, New Project. In the assistant, pick View-based Application and continue to the next step.
Creating a View-Based Application with Xcode 4
I filled in these fields as follows:
  • Product Name: PushChat
  • Company Identifier: com.hollance
  • Device Family: iPhone
The Product Name and Company Identifier together form the Bundle ID. In my case that is “com.hollance.PushChat”. You should choose a Product Name and Company Identifier that correspond to the App ID that you made earlier in the Provisioning Portal (com.yourname.PushChat).
Finish the assistant and open PushChatAppDelegate.m. Change the didFinishLaunchingWithOptions method to look like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
 self.window.rootViewController = self.viewController;
 [self.window makeKeyAndVisible];
 
 // Let the device know we want to receive push notifications
 [[UIApplication sharedApplication] registerForRemoteNotificationTypes:
  (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
 
    return YES;
}
The new call to registerForRemoteNotificationTypes tells the OS that this app wants to receive push notifications.
Build & Run the app. You need to do this on your device because the simulator does not support push notifications. Xcode should automatically have selected the new provisioning profile. If you get a code sign error, then make sure the proper profile is selected in the Code Signing build settings.
When the app starts and registers for push notifications, it shows a message to inform the user that this app wishes to send push notifications.
A Simple iPhone App Requesting Permission to Deliver Notifications
The app asks this only once. If the user picks “OK”, then we should be all set. However, if they choose “Don’t Allow” then our app will never receive push notifications. The user can reverse their decision in the phone’s Settings.
Viewing Push Notification Permissions in iPhone Settings
The name of your app will be added to the phone’s Settings, under Notifications. The user can enable or disable the notifications for your app here, including individual settings for badges, sounds, and alerts.
A single app's Push Notification Settings
Your app can find out which types of push notifications are enabled through:
UIRemoteNotificationType enabledTypes = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
There is one more thing we need to add to the app in order to be able to receive push notifications. Add the following to PushChatAppDelegate.m:
- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken
{
 NSLog(@"My token is: %@", deviceToken);
}
 
- (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error
{
 NSLog(@"Failed to get token, error: %@", error);
}
When your app registers for remote (push) notifications, it tries to obtain a “device token”. This is a 32-byte number that uniquely identifies your device. Think of the device token as the address that a push notification will be delivered to.
Run the app again and you should see something like this in Xcode’s console window:
My token is:
<740f4707 bebcf74f 9b7c25d4 8e335894 5f6aa01d a5ddb387 462c7eaf 61bb78ad>
The token is an opaque binary data structure, stuffed into an NSData object. Apple doesn’t want you to mess around with its internals. For our purposes it is enough to know that it is currently 32 bytes long. As you can see above, the token can be represented by 64 hexadecimal characters. We will be using it in that format, although we still strip off the brackets and leave out the spaces.
If you run the app in the simulator, the didFailToRegisterForRemoteNotificationsWithError: method will be called as push notifications are not supported in the simulator.
That’s it for the app. There is one more thing to do and then we can finally see some push notifications in action!

Sending our first push notification

As I’ve mentioned a few times before, you need to set up a server that sends the push notifications to your app. For this first test, we’re not going to set up a server just yet. Instead, I’ll give you a very simple PHP script that sets up a connection to APNS and sends a push notification to a device token that you specify. You can run this straight from your Mac.
Download the SimplePush code and unzip it. You need to make some changes to simplepush.php.
// Put your device token here (without spaces):
$deviceToken = '0f744707bebcf74f9b7c25d48e3358945f6aa01da5ddb387462c7eaf61bbad78';
 
// Put your private key's passphrase here:
$passphrase = 'pushchat';
 
// Put your alert message here:
$message = 'My first push notification!';
You should copy the device token from the app into the $deviceToken variable. Be sure to leave out the spaces and brackets; it should just be 64 hexadecimal characters. Put your private key’s passphrase into $passphrase, and the text you wish to send in $message.
Copy your ck.pem file into the SimplePush folder. Remember, the ck.pem file contains both your certificate and the private key.
Then open a Terminal and type:
$ php simplepush.php
If all goes well, the script should say:
Connected to APNS
Message successfully delivered
And within a few seconds you should receive your first push notification:
Simple app receiving a Push Notification
Note that you won’t see anything when the app is open. The push message is delivered but we did not build anything in the app to handle it yet. Close the app and try again.
If the simplepush.php script exits with an error message, then check that you have made the PEM file correctly, and that you can connect to the sandbox server without problems (see above).
For now, it is not important what the script exactly does. I will talk more about this in the second part of the series when we build a true push server.

Where To Go From Here?

At this point, you’ve successfully set up an app to receive push notifications, and delievered your first push notification through custom PHP code!
Next check out Part 2 of the tutorial series, where I’ll cover how to make a simple direct messaging app called PushChat that uses push notifications to deliver the messages.
There you’ll learn how to make a complete server side API that delivers push notifications continuously in the background!