Monday, October 13, 2014

Swift - Dealing with pointers in Swift

When using certain APIs in Objective-C and C, you often have to deal with pointers. For example, you can write data to the NSOutStream object using the write:maxLength: method:

-(void) writeToServer:(const uint8_t *) buf {
    [oStream write:buf maxLength:strlen((char*)buf)];

}

The write:maxLength: method takes in a pointer of type unint8_t, containing the data you want to send across the stream. The equivalent of the above function in Swift is:

func writeToServer(dataToWrite:NSData) { 
    oStream!.write(
        UnsafePointer(dataToWrite.bytes)
        maxLength: dataToWrite.length) 
}

For reading of data, in Objective-C, you would supply an array of uint8_t:

uint8_t buf[1024]; 
unsigned int len = 0; 
len = [(NSInputStream *)stream read:buf maxLength:1024];

In Swift, you can use the following:

let buf = NSMutableData(capacity: 1024) 
var buffer = UnsafeMutablePointer(buf.bytes) 
let len = (aStream as NSInputStream).read(buffer, maxLength: 1024)

Tuesday, October 07, 2014

iOS 8 - Display an alert

The UIAlertView class is deprecated in iOS8. In place of it is the more adaptive UIAlertController class. Here is a quick example of how to display an alert in iOS 8:

    func displayAlert(title:String, content:String) {
        var alertController = UIAlertController(
            title: title,
            message: content,
            preferredStyle: UIAlertControllerStyle.Alert)
        
        var okAction = UIAlertAction(
            title: "OK", style: UIAlertActionStyle.Default) {
                (action) -> Void in
                println("Tapped on OK")
        }
        
        alertController.addAction(okAction)
        self.presentViewController(alertController, animated: true, completion: nil)
    }

To display an alert, you can call the displayAlert() function like this:

self.displayAlert("Hello", content: "Hello, iOS 8")

The above will display an alert like the following:

Xcode 6 - iPhone Simulator Folder

In Xcode 6, the location of the applications on the iPhone Simulator has changed. Prior to iOS 8, the location of the Documents folder of your app can be found here:

/Users/weimenglee/Library/Application\ Support/iPhone\ Simulator/<iOS_Version>/Applications/<application_id>/Documents 

In xCode 6, the location of the simulator has changed to:

/Users/weimenglee/Library/Developer/CoreSimulator/

However, this location contains a list of folders for different types of simulators. If you go into this folder, you will see something like this:


Each folder correspond to a specific iPhone Simulator. To know which folder corresponds to which simulator, use the following command in Terminal:

Weis-Mac-mini:~ weimenglee$ xcrun simctl list
== Device Types ==
iPhone 4s (com.apple.CoreSimulator.SimDeviceType.iPhone-4s)
iPhone 5 (com.apple.CoreSimulator.SimDeviceType.iPhone-5)
iPhone 5s (com.apple.CoreSimulator.SimDeviceType.iPhone-5s)
iPhone 6 Plus (com.apple.CoreSimulator.SimDeviceType.iPhone-6-Plus)
iPhone 6 (com.apple.CoreSimulator.SimDeviceType.iPhone-6)
iPad 2 (com.apple.CoreSimulator.SimDeviceType.iPad-2)
iPad Retina (com.apple.CoreSimulator.SimDeviceType.iPad-Retina)
iPad Air (com.apple.CoreSimulator.SimDeviceType.iPad-Air)
Resizable iPhone (com.apple.CoreSimulator.SimDeviceType.Resizable-iPhone)
Resizable iPad (com.apple.CoreSimulator.SimDeviceType.Resizable-iPad)
== Runtimes ==
iOS 7.0 (7.0 - Unknown) (com.apple.CoreSimulator.SimRuntime.iOS-7-0) (unavailable, runtime path not found)
iOS 7.1 (7.1 - Unknown) (com.apple.CoreSimulator.SimRuntime.iOS-7-1) (unavailable, runtime path not found)
iOS 8.0 (8.0 - 12A365) (com.apple.CoreSimulator.SimRuntime.iOS-8-0)
== Devices ==
-- iOS 7.0 --
-- iOS 7.1 --
-- iOS 8.0 --
    iPhone 4s (8C1303A2-C590-4822-BB9B-12EC32035C8C) (Shutdown)
    iPhone 5 (402C822D-567F-4F3A-B113-1499C5A7949C) (Shutdown)
    iPhone 5s (B6D71F6A-E94B-47ED-AF25-882FDEF8E6F5) (Shutdown)
    iPhone 6 Plus (5BCD1507-6F06-4D66-B71D-47670EB703B2) (Shutdown)
    iPhone 6 (00100565-4E4D-4D9A-A875-544E0A6E4F4F) (Booted)
    iPad 2 (187D75DD-824D-4381-AE2F-BDF57FEB87E0) (Shutdown)
    iPad Retina (604667D3-8366-4147-B0AD-F7840198713C) (Shutdown)
    iPad Air (01D6AEBC-F12A-47EE-82CB-0140AF117AE0) (Shutdown)
    Resizable iPhone (9C138BCD-BFB9-4AEB-A218-F0F99F678220) (Shutdown)
    Resizable iPad (4966C908-AAA7-43EC-8E3A-EADF8BFA3C05) (Shutdown)
Weis-Mac-mini:~ weimenglee$ 

In my example here, I am looking for iPhone 6, which has the device id of 00100565-4E4D-4D9A-A875-544E0A6E4F4FYou can then go into this folder and the following path shows the folder that contains all the applications installed on this simulator:

/Users/weimenglee/Library/Developer/CoreSimulator/Devices/00100565-4E4D-4D9A-A875-544E0A6E4F4F/data/Containers/Data/Application/

You can now locate your specific application and find the Documents folder:

/Users/weimenglee/Library/Developer/CoreSimulator/Devices/00100565-4E4D-4D9A-A875-544E0A6E4F4F/data/Containers/Data/Application/FD7949EA-7D39-4BC6-95F4-77F320592651/Documents/


Tuesday, September 30, 2014

Swift - Calling Objective-C code

In Xcode 6, you now have the option to create a project using either Swift or Objective-C. In addition, you can also use Objective-C code in your Swift project. This post shows you how. 

1. First, create an iOS project that uses the Swift language

2. Add a Objective-C File file to your project. Name it as MyClass

3. You will be prompted with the following:


4. This will add a file named UsingObjC-Bridging-Header.h to your project. Behind the scene, Xcode automatically sets the Objective-C Bridging Header setting to this file:


5. Add a Header File file to your project. Name it as MyClass

6. Populate the MyClass.h with the following:

#import

@interface MyClass: NSObject

@property (strong, nonatomic) NSString *property;

- (void) method;

@end

7. Populate the MyClass.m with the following:

#import "MyClass.h"

@implementation MyClass

- (void) method {
    NSLog(@"In method now");
}

@end

8. Populate the UsingObjC-Bridging-Header.h with the following:

#import "MyClass.h"

9. To use the Objective-C class that you have added to your project, add the following statements in bold to the ViewController.swift file:

    override func viewDidLoad() {
        super.viewDidLoad()

        // create an instance of the class
        var myClass: MyClass = MyClass()

        // set its property
        myClass.property = "some random strings here"

        // call its method
        myClass.method()
        
        // retrieve its property
        println(myClass.property)

    }

Monday, September 29, 2014

Swift - Checking if a method exists

A lot of changes has happened in iOS 8, and a lot of APIs require that you call certain new methods before they can work. Examples are locations, notifications, and more.

To ensure that your app can work on older versions of iOS as well as the new iOS 8, it is important that you only call the new API when your app is running on iOS 8. The best way is to test if a method exists. You can do so via the respondsToSelector() method. The following example tests to see if the UIApplication object contains the registerUserNotificationSettings() method:

if application.respondsToSelector("registerUserNotificationSettings") {

}

Another example:

if self.locationManager.respondsToSelector("requestAlwaysAuthorization") {


}

iOS 8 - Displaying Local Notifications

Displaying local notifications has changed a little in iOS 8. You now need to seek the user's permission in order to display notifications. You can do so via the AppDelegate, like this:

    func application(application: UIApplication
    didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        
        application.registerUserNotificationSettings(
            UIUserNotificationSettings(
                forTypes:
                UIUserNotificationType.Sound |
                UIUserNotificationType.Alert |
                UIUserNotificationType.Badge, categories: nil))
            
        return true

    }


Once user's permission is granted, you would now be able to display a notification as usual:

        var localNotification =  UILocalNotification()
        //---the message to display for the alert---
        localNotification.alertBody =
            "You have entered the region you are monitoring"
        
        //---uses the default sound---
        localNotification.soundName = UILocalNotificationDefaultSoundName
        
        //---title for the button to display---
        localNotification.alertAction = "Details"
        
        //---display the notification---

        UIApplication.sharedApplication().presentLocalNotificationNow(localNotification)

Sunday, September 28, 2014

Swift - Using Selector in Swift

In Objective-C, you often encounter methods that accepts a Selector as the argument. A good example is the NSTimer's NSTimer.scheduledTimerWithTimeInterval() method:

- (void)onTimer {
}

    [NSTimer scheduledTimerWithTimeInterval:0.05
                                     target:self
                                   selector:@selector(onTimer)
                                   userInfo:nil
                                    repeats:YES];   


A selector is basically a name of a method that will be executed by another method. In Objective-C, to pass in a selector argument you use the @selector() keyword together with the name of the method. 

In Swift, you can simply pass in the name of the method as a string, like this:

func onTimer() {
}

        NSTimer.scheduledTimerWithTimeInterval(0.05,
            target:self,
            selector:"onTimer",
            userInfo:nil,
        repeats:true)

Swift - Generating a random number

If you want to generate a random number in Swift, use the arc4random_uniform() function. The following code snippet generates a number from 0 to 9:

var i = Int(arc4random_uniform(10))

Thursday, September 25, 2014

iOS 8 - Getting Location Data

Getting location data in iOS 8 has changed drastically. Here is what you need to do if you are using the CLLocationManager class to get a location in iOS 8.

In iOS 8, you need to add the following two keys in your info.plist file:

For getting location in the foreground

Key
NSLocationWhenInUseUsageDescription

Value
"This app will display your current location" (up to you to write anything you want here)

For getting location in the background

Key
NSLocationAlwaysUsageDescription

Value
"This app will log your location into a database" (up to you to write anything you want here)

Before you use the startUpdatingLocation() method, you have to request for user's permission. To use the location in the foreground, call the requestWhenInUseAuthorization() method:

var lm: CLLocationManager!
...
        if (UIDevice.currentDevice().systemVersion as NSString).floatValue>=8.0 {            
            //---request for foreground location use---
            lm.requestWhenInUseAuthorization()
        }
        
        lm.startUpdatingLocation()


If you want to continue getting location data in the background, call the requestAlwaysAuthorization() method:

        if (UIDevice.currentDevice().systemVersion as NSString).floatValue>=8.0 {
            //---request for background location use---
            lm.requestAlwaysAuthorization()
        }


Note that if you want the app to access location information both in the foreground and in the background, it is sufficient to call the requestAlwaysAuthorization() method.

Saturday, September 13, 2014

Schedule for Oct to Dec 2014 Released

I am happy to announce the new schedule for courses from Oct to Dec 2014.

Sep 2014
Sun
Mon
Tue
Wed
Thu
Fri
Sat

1
2
3
4
5
6

7
8
S$699/pax
9-10
S$1,097/pax
11
S$699/pax
12
S$699/pax
13

14
15-16
S$1,097/pax
17
S$699/pax
18-19
S$1,495/pax

20

21
22-23
S$1,097/pax
24-25
S$1,097/pax
26
S$699/pax
27
28
29-30 Sep, 1 Oct
S$1,695/pax




Oct 2014

Sun
Mon
Tue
Wed
Thu
Fri
Sat

29-30 Sep, 1 Oct
S$1,695/pax
2
S$699/pax
3
4

5
6
7-8
S$1,097/pax
9-10
S$1,097/pax

11

12
13-14
S$1,097/pax
15
16-17
S$1,395/pax
18

19
20
21
22
23
24
25

26
27
28
29
30
31



Nov 2014
Sun
Mon
Tue
Wed
Thu
Fri
Sat






1


2
3
4
5
6
7
8


9
10-11
S$1,097/pax
12-13
S$1,097/pax
14
15


16
17
18
19
20
S$699/pax
21
S$699/pax
22


23


24
25
26
27
28
29
30








Dec 2014

Sun
Mon
Tue
Wed
Thu
Fri
Sat

1-2
S$1,097/pax
3-4
S$1,097/pax
5
S$699/pax
6


7
8-9
S$1,097/pax
10
S$699/pax
11
S$699/pax
12
13


14
15
16
17


18
19
20

21

22-23
S$1,495/pax
24


25
26
S$699/pax
27
28

29-30
S$1,097/pax
31