1. http://nshipster.com/launch-arguments-and-environment-variables/ →

  2. • Flags: very useful when debugging with... →

  3. Key-Value Observing

    Key-Value coding is great, but coupled with Key-Value Observing is even better. Key-Value Observing is a mechanism that enables objects to be notified of changes of the properties of associated objects.

    The key APIs for KVO are -addObserver:forKeyPath:options:context: and -observeValueForKeyPath:ofObject:change:context:

    When calling -addObserver:forKeyPath:options:context:, the receiver will start sending messages to the caller as soon as the property specified in the keyPath parameter changes. The context parameter is a void pointer to a piece of data that is pass untouched to the observer in -observeValueForKeyPath:ofObject:change:context:, sometimes useful to share states, or validation. The options parameter is a combination of NSKeyValueObservingOptions specifying what the observer wants to hear from the subject. Here the possible values:

    Constant Meaning
    NSKeyValueObservingOptionNew The change dict should contain the new value for the property
    NSKeyValueObservingOptionOld The change dict should include the attribute that is being changed for the property
    NSKeyValueObservingOptionInitial If specified, a notification should be sent to the observer immediately, before the observer registration method even returns. If also specified by NSKeyValueChangeNewKey the current value of the property is dispatched. This should be specified if the observer wants to know right away the value of the property under examination
    NSKeyValueObservingOptionPrior Whether separate notifications should be sent to the observer before and after each change, instead of a single notification after the change. The change dictionary in a notification sent before a change always contains an NSKeyValueChangeNotificationIsPriorKey entry whose value is [NSNumber numberWithBool:YES], but never contains an NSKeyValueChangeNewKey entry. The content of change dispatched after the change contains the exact same payload that it would contains even if this option was not specified.

    The reference created between the observer and the subject is strong. That’s why an object should remove itself as observer when it no longer needs to hear about changes in the subject, or it is about to be deallocated. The appropriate APIs to do that are either -removeObserver:forKeyPath: or -removeObserver:forKeyPath:context: if a context has been provided.

    -observeValueForKeyPath:ofObject:change:context: is sent to observers when the value of the specified key path changes (and before the change if NSKeyValueObservingOptionPrior has been specified).

    The entries of change describe what has been changed, and how. The available entries are:

    Constant Meaning
    NSKeyValueChangeKindKey An NSNumber containing a value from NSKeyValueChange enum. A value of NSKeyValueChangeSetting indicates that the observed object has received a setValue:forKey: message, or that the key-value-coding-compliant set method for the key has been invoked, or that one of the willChangeValueForKey: or didChangeValueForKey: methods has otherwise been invoked. A value of NSKeyValueChangeInsertion, NSKeyValueChangeRemoval, or NSKeyValueChangeReplacement indicates that mutating messages have been sent a key-value observing compliant collection proxy, or that one of the key-value-coding-compliant collection mutation methods for the key has been invoked, or a collection will change or did change method has been otherwise been invoked.
    NSKeyValueChangeNewKey This is the new value for the attribute
    NSKeyValueChangeNewKey This is the new value for the attribute. For collection properties, the value is an NSArray instance containing the values that has been added or replaced.
    NSKeyValueChangeOldKey This is the value before the attribute has been changed. For collections, this will be an NSArray containing either the objects that has been removed, or the ones that has been replaced
    NSKeyValueChangeIndexesKey For collection properties, this will contain an NSIndexSet with the indexes of the objects that has been removed, inserted or replaced
    NSKeyValueChangeNotificationIsPriorKey As discussed previously, this will mark the change dictionary that is send prior to the change.

    Manual dispatch

    Unless specifically instructed otherwise, the system automatically dispatches the changes notifications. To manually perform the notifications, you need to override + automaticallyNotifiesObserversForKey: (the default implementation returns YES), and then call -willChangeValueForKey:, -willChange:valuesAtIndexes:forKey: (for ordered collections) or willChangeValueForKey:withSetMutation:usingObjects: (for unordered collections). After the change property has been changed, you have to call –didChangeValueForKey:, –didChange:valuesAtIndexes:forKey: (ordered collections) or – didChangeValueForKey:withSetMutation:usingObjects: (unordered collections).

    Dependency

    Sometimes, a property value depends on other property values. Let’s say you change your mind, and ask for duck instead of curry, then it might be a good idea to replace your Riesling by a Syrah. Dependencies are signaled with +keyPathsForValuesAffectingValueForKey:

    + (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key {
    
     NSSet *keyPathsAffected = [super keyPathsForValuesAffectingValueForKey:key];
        if ( [key isEqualToString:@"meat"] ) {
    
          keyPathsAffected = [keyPathsAffected setByAddingObject:@"wine"];
    
        }
    
      return keyPathsAffected;
    
    }
    

    More granularly, dependencies can be identified with -keyPathsForValuesAffectingKey.

    Notifications vs. KVO

    For some, KCO looks awful close to notifications. A given object wants to know what’s happening somewhere else, and set itself as an observer. Well, there are two major difference between notifications and KVO.

    First, notifications are not bound to properties, they can be used to notify about everything, including, properties.

    Second, the architecture is somewhat different. The notification paradigm is a broadcast operation. Somewhere, an objects feels the urge to let the world knows about something. It doesn’t matter if no one is listening, the message is send. KVO is more like a two way conversation. Lastly, notifications are asynchronous. That might be good or bad, depending on your needs.

  4. Key-Value Coding

    Key-Value coding is a set of APIs that grant access to an object properties indirectly. You use a key to access the property value, instead of the getter (or setter).

    Why bother? Aren’t setter/getter good enough? For the most part, yes, but sometimes, is nice to let the runtime do the heavy lifting.

    Consider the following scenario. You are showing a list of restaurants. You get the list from a web service, and after parsing the response you get a bunch of dictionary that you want to back to a custom class model. You could go setting all the properties one by one. Or you could instead iterate through the dictionary and just set let the restaurant set the values:

    Restaurant *restaurant = [Restaurant new];
    NSDictionary *rawRestaurant = @{@"name":@"some name",@"address":@"some address"};
    [rawRestaurant enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
        @autoreleasepool {
    
            [restaurant setValue:obj
                          forKey:key];
    
        }
    }];
    

    Loosing the coupling components is a neat trick to simplify many interactions.

    The whole secret here is the key. A key is nothing more than a string that, somehow (we are going to see exactly how in a moment), allow the outside world to gain access to the inner state of an object.

    The mechanism that map keys to properties is implemented though the informal protocol NSKeyValueCoding. Since NSObject provides a basic implementation of NSKeyValueCoding, all the objects that subclass it have KVC right out of the box.

    Search Pattern

    When querying an object property, the runtime will try to use an accessor whenever possible. If no accessor is available, and +accessInstanceVariablesDirectly returns YES (default behavior), it will try to gain access to the ivars themselves.

    To allow KVC to find the appropriate accessor (or ivar) the following name convention had to be followed:

    • A getter is named after the property. If the property name is “address” then the getter is -address. No getAddress.
    • The setter name is composed by the word set followed by the property name, capitalized. If the proper is “address”, then the setter is -setAddress:
    • The name of the ivar might be preceded by an underscore. _address. For booleans it is also allowed to use the for _is<Key>, for instance, _isValid.
    • For aggregates properties, there a bunch of methods that should be implemented for KVC. For properties that need to retain the order, the required method are: -countOfKey, -objectInKeyAtIndex:, -getKey:range:, -insertObject:inKeyAtIndex:, -removeObjectFromKeyAtIndex:, and -replaceObjectInKeyAtIndex:withObject:. For properties where the order is not important, the methods are: -countOfKey, -enumeratorOfKey, -memberOfKey:, -addKeyObject: and -removeKeyObject:

    By default, when setting a property, the compiler will introduce all the accessors and corresponding ivars. No need to worry about that.

    Following the naming convention, the runtime will be able to access a property or an ivar:

    1. First it will query the receiver class to know if the class responds to the accessor.
    2. If no accessor is available, and + accessInstanceVariablesDirectly returns YES, it will search for the corresponding ivar.
    3. If no accessor, neither ivar is found, the system send a -setValue:forUndefinedKey: to the receiver. The default implementation just raise a NSUndefinedKeyException. But NSObjects subclasses can override it to implement custom logic.

    Validation

    The runtime also provides infrastructure to validate property values. The API to trigger the validation is -validateValue:forKey:error:, thou, the method -validateKey:error: is also expected. KVC does not trigger the validation automatically. You code is expected to invoke the appropriate API.

    NSError *error = nil;
    
    NSString *restaurantName = @"Restaurant Name";
    BOOL validRestaurantName = [restaurant validateValue:&restaurantName forKey:@"name" error:&error];
    
    if ( validRestaurantName ) {
    
        [restaurant setValue:restaurantName forKey:@"name"];
    
    }
    

    KVC Collection Operators

    They are a concise way to perform action on a collection using special notation in the key path -valueForKeyPath:. They are identified with @ and can be divided in:

    Simple collection operations

    They process the collection to produce a single result.

    Operator Action
    @avg Returns as an NSNumber the average of the property specified by the key path to the right of the operator. If any instance of the traversed collection is nil, 0 is assumed.
    @count Returns the number of objects in the left key path collection as an instance of NSNumber. If present, the key path to the left of the operator is ignored.
    @max Compares the objects that compose the collection to the right of the operator, and returns the maximum value found. The maximum value is determined with compare:. Properties set to nil are ignored.
    @min Compares the values of the property specified by the key path to the right of the operator and produces the minimum value. Properties set to nil are ignored. Comparison is performed sending compare: message.
    @sum Produce the sum of the values of the property specified by the key path to the right of the operator. Each number is converted to double. The return value is an instance of NSNumber

    Object operations

    They queried the collection and return with an array of the elements that match.

    Operator Action
    @distinctUnionOfObjects Returns an array containing the distinct objects in the property specified by the key path to the right of the operator
    @ unionOfObjects Similar to @distinctUnionOfObjects, but this one returns an array with all the objects, even duplicates.

    Array and set operations

    They operate on nested collections, i.e. a collection where each entry contains a collection

    Operator Action
    @distinctUnionOfArrays Returns an array containing the district objects in the property specified by the key path to the right of the operator.
    @unionOfArrays Similar to @distinctUnionOfArrays, but does not remove duplicates
    @distinctUnionOfSets Similar to @distinctUnionOfArrays, but expect instances of NSSet

  5. Run Objective-C, run

    Objetive-C provides a powerful platform. It is not just a robust superset of ANSI C, but it also implements a runtime that enables, amongst many other features, great flexibility. You don’t really knows how to handle something when writing the program? The scenario might change because the inputs you have to work with might vary? Don’t you worry, the program can evaluate the best way at running time.

    Dynamic typing

    Sometimes it is hard to know in advance the type of the object that needs to be assigned to a variable. Perhaps the object is the result of a computation that can return either an NSNumber or an NSString. With dynamic typing you can just ask the returned object the class it belongs to, if it adheres with a protocol, or if it can perform some selector.

    Objective-C provides support for dynamic typing via the id data type. The id type can hold a pointer to any object. When defining an object as id the compiler is unable to perform any type check. All the checking is performed at runtime.

    id myObject = someOtherObject; 
    

    Here, someOtherObject could be of any type. The compiler have no means to know more about it. The actual type of myObject is determined at runtime. When Programming to an interface, you can hint the compiler about the protocol the variable had to adhere to be consider.

    - (void)someMethod:(id<InterfaceProtocol>)someParam;
    

    Furthermore, at runtime, you can introspect any object checking the class or if it can handle a selector:

    Method Description
    +class You can only refer to a class by its name when it is the receiver of a message. In any other situation, you have to query the Class object through this method
    +superclass Returns the receiver superclass Class object
    +isSubclassOfClass: Returns YES if the receiver is either member of the given class, or a subclass
    +instancesRespondToSelector: This class method will return YES if its instances are able to handle the the given selector
    +conformsToProtocol: Return YES if the class adhere to the given protocol. There is also an instance method
    -isKindOfClass: Returns YES if the object queried belongs to the given class or any of its superclasses
    -isMemberOfClass: Returns YES only if the receiver is an instance of the given class
    -respondsToSelector: returns YES if the receiver is able to handle the given selector
    -conformsToProtocol: returns YES if the target adheres to the given protocol

    Dynamic Binding

    In Objective-C, messages are not mapped to a method at compile time. The whole process is always handled at runtime. Once the receiver type has been figured out, the runtime tries to find an appropriate method for the selector. First, the receiver class is queried, and if no matching method is found, then the runtime starts to climb up the class ladder.

    But you can also implement and inject methods at runtime. For instance, when you set a property to be @dynamic you are telling the compiler that the getter/setter is going to be generated. Somewhere, someone (i.e. Core Data) is going to handle that.

    Since Objective-C translate the methods to pure C functions, you can write your own C function, and let the runtime knows that you want to use it whenever a given message is received.

    To add a new implementation to the class, you have to import objc/runtime.h and use the class_addMethod function. The function maps the selector to the given implementation. If an implementation for the method is present in the superclass, then it will override it. Nothing will happens if the implementation is present in the same class (to change the implementation of a class from within the class itself, you have to use method_setImplementation

    As discussed previously, the method implementation is just a C function. It receives at least two parameters, self, and the selector.

    class_addMethod takes four arguments:

    • cls: The class to which the method is going to be added.
    • name: A selector specifying the name of the method.
    • imp: Pure C function that implements the method being added.
    • types: Array of characters that describe the returning value of the implementation, and the type of all the params. Since the implementation takes at least two arguments, the second and the third elements of the array are always “@:” (the first is the return type). The values to encode the types can be found in here.

    You can subclass +resolveInstanceMethod in order to hijack the message send to the target, and evaluate if you need to add a new class implementation (or swap the one you already have).

    + (BOOL)resolveInstanceMethod:(SEL)selector {
    
        BOOL resolveInstanceMethod = NO;
        NSString *method = NSStringFromSelector(selector);
    
        if ( [method isEqualToString:@"allCaps:"]) {
    
            resolveInstanceMethod = class_addMethod([self class], selector, (IMP)allCaps, "@@:@");
    
        } else {
    
            resolveInstanceMethod = [super resolveInstanceMethod:selector];
    
        }
    
        return resolveInstanceMethod;
    
    }
    

    As discussed before, the implementation is just a C function:

    id allCaps(id self, SEL _cmd, id string) {
    
        NSString *allCaps = nil;
        if ( [string isKindOfClass:[NSString class]] ) {
    
           allCaps = [string uppercaseString];
    
        }
    
        return allCaps;
    
    }
    

    Dynamic Loading

    Instead of having all the executables and resources loaded on startup, Objective-C enables to load them on request.

    Executables and resources needs to be added as bundle to the package. A bundle is nothing more than a folder with a special layout. Here the basic layout of a loadable bundle:

    - MyLoadableBundle
    Contents/
            Info.plist
        MacOS/
                MyLoadableBundle
        Resources/
            Lizard.jpg
            English.lproj/
                MyLoadableBundle.nib
                InfoPlist.strings
            Japanese.lproj/
                MyLoadableBundle.nib
                InfoPlist.strings 
    

    Every bundle contains one folder, Contents, and inside it, it is recommended to have a plist with information about the bundle itself. The most relevant information you will be storing in the plist is:

    * `CFBundleExecutable`: the name of the executable, typically the same as the bundle directory without the extension
    * `CFBundleIdentifier`: the globally unique identifier for the bundle, in reverse-DNS order
    * `CFBundleName`: the short display name of the bundle, used as a human-readable identifier (should be localized)
    * `CFBundleDisplayName`: the display name of the bundle, used to represent the bundle in the Finder unless overridden by the user (should be localized)
    

    Unfortunately, you cannot link against custom bundles in iOS.

    Cautionary Buoy

    Because it is there, it doesn’t mean you have to use, and if you use it, beware. Whenever possible, is really good to have the compiler as an ally. If static typing is not making things harder, then, by all means, type your variables. Include all the methods that you might need. Don’t resort to fancy just because. This is like a chainsaw. It is a bit scary, and it really makes no sense to use to cut a butter block in half. But if you need it, then just use it.

  6. Type Encoding

    Code Meaning
    c A char
    i An int
    s A short
    l A long. l is treated as a 32-bit quantity on 64-bit programs.
    q A long long
    C An unsigned char
    I An unsigned int
    S An unsigned short
    L An unsigned long
    Q An unsigned long long
    f A float
    d A double
    B A C++ bool or a C99 _Bool
    v A void
    * A character string (char *)
    @ An object (whether statically typed or typed id)
    # A class object (Class)
    : A method selector (SEL)
    [array type] An array
    {name=type…} A structure
    (name=type…) A union
    bnum A bit field of num bits
    ^type A pointer to type
    ? An unknown type (among other things, this code is used for function pointers)

    Use Notes

    @encode is the compiler directive that is used to create the internal representation of a given type. In some regards, is similar to ANSI C typeof.

    When encoding an array, the returned char buff will be composed by the number of items in the array, and the data type of them, enclosed in square brackets

    int ints[4] = {1,2,4,5};
    char *buff = @encode(typeof(ints));  // -> [4i]
    
    char chars[4] = {'a','b','c','d'};
        char *buff = @encode(typeof(chars)); // -> [4c]
    

    structs are encoded between curly braces, with the name of the struct followed by the code for the types of the structure fields’

    typedef struct _struct {
        __unsafe_unretained NSString *nsString;
        char *charString;
        int  Int;
    } Struct;
    
    char *buff = @encode(typeof(Struct)); // -> {_struct=@*i}
    

    Objects are treated like structs with at least one field, the isa of type Class.

  7. Debugging custom classes

    Xcode is a wonderful tool. One of the best IDE I’ve ever use. It makes debugging so much easier.

    Sometimes, is hard to know what’s happening. You set a breakpoint, you stop the app, and you just get a pointer to a custom object.

    Summary format

    Sure, you can subclass -description to have more information in the debugger. But the problem is that you are injecting code to the program. You are calling a method, and you don’t really know about the side effects of that. A simple way to mitigate the problem is to set the summary format for the object to call an ivar though the associated property. You are still injecting code, you are still calling a method from within the debugger, but reducing the scope of the call, your chances of changing something as a side effect are slimmer.

    To set the summary of an object, you need to double click the variable in the debugger panel. A new popup is shown.

    Set Summary Popup

    In the text field, you have to type the new format. Is a dictionary where $VAR is the placeholder for the object instance. If you want to show only the firstName ivar from your object, then you can set the summary format to:

    {(NSString *)[$VAR firstName]}:s 
    

    Python API

    But Xcode can go a little deeper thanks to the powerful LLDB. LLDB is a great debugger. It is tightly integrated with the compiler. This allows, amongst many other things, to have access to the ABI details. Having access to the actual data layout, you can create a custom summary for opaque objects. The trick is to leverage the Python API and extend LLDB importing a script.

    The basic structure of the script is quite simple:

    import lldb # 1
    
    def custom_object_summary(valueObject, dictionary):
    return "summary" # 4
    
    def __lldb_init_module(debugger, dict): # 2
    debugger.HandleCommand('type summary add VBCustomObject -F FileName.custom_object_summary') # 3
    

    First, we need to import the LLDB API. Once the script is imported, the debugger will call __lldb_init_module. Here we let the debugger run the command type summary add VBCustomObject -F FileName.custom_object_summary. Notice that the command is pointing to the script with the class name, and the function name (FileName.custom_object_summary). The function will receive two parameters, the valueObject is the one that encapsulates all the instance information. And it should return a string. The string that will be used as the new summary.

    Why bother to write a script to change the summary when we can change it double clicking the instance and setting the new format? Well, the script can be saved to be used in the future, and it can also be used to compute some values given the raw data. Here, for instance, we compute the age of a person using the date of birth:

    import lldb
    import datetime
    
    def person_summary(valueObject, dictionary):
        dobAsString = valueObject.GetChildMemberWithName('_dateOfBirth').GetSummary()
        first_name = valueObject.GetChildMemberWithName('_firstName').GetSummary().replace("@","").replace("\"","")
        last_name = valueObject.GetChildMemberWithName('_lastName').GetSummary().replace("@","").replace("\"","")
    
        name = " ".join([first_name, last_name])
    
        dob = datetime.datetime.strptime(dobAsString,"%Y-%m-%d %H:%M:%S %Z")
        now = datetime.datetime.now()
        delta = now-dob
    
        summary = "name: %(name)s age: %(age)d" % {"age":int((delta.days)/365.25), "name":name}
    
        return summary
    
    def __lldb_init_module(debugger, dict):
        debugger.HandleCommand('type summary add VBPerson -F PersonCustomSummaries.person_summary')
    

    To import the script, you need to stop the run, and type in the lldb command line:

    command script import /path/to/Python/script/PythonScript.py
    

    A neat trick to get the path to the script, is to drag and drop it from the project navigator to the console.

    A last thing to remember, at least in my own experience, you will have to restart Xcode to update the Python script used.

    You can take a look at some code here

  8. EventKit

    EventKit is a high level API that give access to calendar on device. Actually, as a function of how Apple develops iOS, it is presented in two separate sets of APIs. One that allows us to interact with calendars (EventKit) and a set of view controllers to show calendars to users, and let users edit them.

    EKEventStore

    Obviously, if we are going to talk to the calendar data store, we are going to need to create a connection to it. And thus, we are going to instantiate a EKEventStore. Well, the thing is a little more convoluted. We cannot talk to the calendar data store, because the app is living in a sandbox. We are going to talk to a daemon (calaccessd), which, in turn, will be handling the interactions with the calendar data store. Most of the times, an instance of the daemon is going to be around, but this should not be taken for granted. And since the cost of open the daemon is not negligible, it is recommended to keep EKEventSore objects around for as much as needed. Also, event objects are bound to the store they came from. If you close the store, you cannot access the events anymore.

    EKCalendar

    Instances of EKCalendar are the windows to the actual calendar. Many different formats are supported (Exchange, MobileMe, CalDAV, Local). The syncing is automatically handle by the framework. To get a hold to the calendars, you start by instantiating a store:

    EKEventStore = [[EKEventStore alloc] init];
    

    And then, you can either get a list of all the available calendars:

    NSArray *calendars = [store calendars];
    

    Or just the default calendar:

    EKCalendar *defaultCalendar = [store defaultCalendarForNewEvents];
    

    The flag allowsContentModification will let us know if the calendar is writable.

    EKEvent

    Represents occurrence of an event. If, for instance, you get a recurrent event, then each instance of the event is represented by a different EKEvent. To crete an event you need a store:

    EKEvent *event = [EKEvent eventWithEventStore:store];
    

    And then, you can set all the values. The calendar, and the start and end dates, are mandatory.

    NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    
    NSDateComponents *startDateComponents = [[NSDateComponents alloc] init];
    [startDateComponents setDay:1];
    [startDateComponents setMonth:1];
    [startDateComponents setYear:2001];
    [startDateComponents setHour:12];
    [startDateComponents setMinute:0];
    
    NSDateComponents *endDateComponents = [[NSDateComponents alloc] init];
    [endDateComponents setHour:1];
    
    NSDate *startDate = [gregorianCalendar dateFromComponents:startDateComponents];
    NSDate *endDate = [gregorianCalendar dateByAddingComponents:endDateComponents
                                                         toDate:startDate
                                                        options:0];
    
    EKEventStore *store = [[EKEventStore alloc] init];
    EKCalendar *defaultCalendar = [store defaultCalendarForNewEvents];
    
    EKEvent *event = [EKEvent eventWithEventStore:store];
    [event setTitle:@"Some title"];
    [event setStartDate:startDate];
    [event setEndDate:endDate];
    [event setCalendar:defaultCalendar];
    

    To save (and sync) an event, you can use:

    NSError *saveEventError = nil;
    if ( ![store saveEvent:event
                      span:EKSpanThisEvent
                     error:&saveEventError] ) {
    
        NSLog(@"%@", saveEventError);
    
    }
    

    The span parameter of the message is not important when creating an event, but let the store knows how to behave when saving a recurrent event edit (possible values are EKSpanThisEvent and EKSpanFutureEvents, pretty self explanatory).

    All events has an identifier. The problem is that identifier is unique, but not permanent. It will change if the event is moved from between calendars. If you query for a particular identifier, and you came back empty handed, it might be useful to try again searching for something else, like the event title. Identifiers are assigned after the event has been saved. Also, for recurrent events, all the events in the series, has the same identifier.

    Alarms can be specified in reference to the start data, and in seconds. A negative value means before the start date. That’s why, most of the time, you are going to set a negative value. Because some types of calendars support only one alarm per event, and there is no way to know if the calendar supports more than one, it is advised to stick to just one.

    EKAlarm *alarm = [EKAlarm alarmWithRelativeOffset:-900];
    

    [event addAlarm:alarm];

    Recurrence rules

    To set a simple recurrence rule we use the simpler initializer -initRecurrenceWithFrequency:interval:end:.

    The frequency is simply an integer from the enum

    typedef enum {
    EKRecurrenceFrequencyDaily,
        EKRecurrenceFrequencyWeekly,
        EKRecurrenceFrequencyMonthly,
        EKRecurrenceFrequencyYearly
    } EKRecurrenceFrequency;
    

    The interval indicates the number of units we need to set aside between each recurrence. If we want the event to popup every week, then we use EKRecurrenceFrequencyWeekly for the frequency, and 1 for the interval. If we want it to triggers every other week, then the interval is going to be 2.

    The end parameter has to be an instance of EKRecurrenceEnd (or nil, if we don’t want the event to ever stop). We can either set the number of occurrences we want:

    EKRecurrenceEnd *end = [EKRecurrenceEnd recurrenceEndWithOccurrenceCount:3];
    

    Or the specifically set the date:

    EKRecurrenceEnd *end = [EKRecurrenceEnd recurrenceEndWithEndDate:endDate];
    

    Data Store changes

    When the store is modified, the daemon push a notification named EKEventStoreChangedNotification. Unfortunately, the notification has little information about the actual changes. And that’s why it is recommended to treat each event and calendar as invalid. EKEvent has a method called refresh, that can be called to test validity of the event instance, but it is not cheap. Rule of thumb. Use refresh only if you are showing an event, and on that specific event. For the rest, just refetch.

    Isolation

    Starting with iOS 6, calendars are isolated and users are asked if they want to grant access to them. A very important thing to remember, is that the user is prompted when the store is initialized. That means do not initialize the store until you really need it. While the prompt is visible, the app should not be blocked. The easiest way to prevent blocks is to trigger the request, and then listen for the EKEventStoreChangeNotification.

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(handleEventStoreAccessChanged:)
                                                 name:EKEventStoreChangedNotification
                                               object:nil];
    
    EKEventStore *store = [[EKEventStore alloc] init];
    

    And then, when the notification is issued, we can check the new authorization status:

    EKAuthorizationStatus authorizationStatus = [EKEventStore authorizationStatusForEntityType:EKEntityTypeEvent];
    

    The possible values are:

    Constant Description
    EKAuthorizationStatusNotDetermined The user has not yet made a choice regarding whether this application the service.
    EKAuthorizationStatusRestricted This application is not authorized to access the service. The user cannot change this application’s status, possibly due to active restrictions such as parental controls being in place.
    EKAuthorizationStatusDenied The user explicitly denied access to the service for this application.
    EKAuthorizationStatusAuthorized This application is authorized to access the service.

    Info.plist

    It is encourage to add usage description to the Info.plist (the key is NSCalendarsUsageDescription and its value is a string) to let users know what we want to do with the calendars. The prompt is going to be shown only once in the app lifetime, and it needs to be descriptive of the various points where the app might need to access the calendars, and why.

  9. Core Data Phantom Breakpoints

    So you are a good guy, you set up your project and you set a breakpoint to catch all exceptions. Life is pretty simple, and then, you decide you might like to have a taste of Core Data. You recompile, and run and the compiler stops you all the time during normal operations. Perhaps you realize the the exception is thrown by core data, specially when you are handling NSManagedObjectID or saving the context.

    Turns out that under the hood, core data uses exceptions to control the flow. Perhaps a vestige of Java, i don’t really know, but it is pretty annoying. The good thing is that you can configure the condition of the symbolic breakpoint used to catch the exceptions. The idea is to ignore any private Core Data exception. The values for the condition are:

    (BOOL)(! (BOOL)[[(NSException *)$eax className] hasPrefix:@”_NSCoreData”])
    

    for the simulator, and:

    (BOOL)(! (BOOL)[[(NSException *)$r0 className] hasPrefix:@”_NSCoreData”])
    

    For the device (notice that the register has been changed from $eax to $r0)

    @0xced @secboffin (via @akosma) mention this article. Truth be told, i didn’t knew about the article. The conditional was taught to me in a Core Data lab at Big Nerd Ranch a few years ago. About Restkit, unfortunately, i have nothing to say. I used only once many years ago, and i didn’t like it. Never used again, and because of that, it is not in my information source.

    Bottom line, i didn’t know about the restkit article. It is better than mine, for starters, it have a screenshot for newbies to see exactly how to configure the breakpoint. I learn this somewhere else (Big Nerd Ranch). But i am happy to say that there is a better source in restkit.

  10. bounds != frame →