1. 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.

  2. bounds != frame →

  3. Hay un lenguaje llamado COBOL →

    Maravilloso artículo de Adrian Kosmaczewski. Realmente fantástico. Será usado de acá en más para explicar a qué me dedico.

    Entedamonos, cualquier artículo que contenga una frase como la siguiente:

    Lo que quedo del buen señor Al-Khowarizmi fue su nombre, que derivo en la palabra «algoritmo», que es una palabra complicada para designar recetas de cocina.

    califica como excelente.

  4. Instruments Flags

    Breakpoints are awesome. I really love them, and i really love how easy is to work with them on Xcode. But sometimes, they are not really a good solution. If you want to inspect the behaviour of your app in a multithreaded environment, halting the operation will change so many things you are not longer inspecting the real app anymore.

    I also love Instruments. Instruments gives you a more cohesive view of the interactions of the different pieces of code. Is far better than breakpoints to get the big picture. But sometimes is hard to get into the little details. Well, with the introduction of Instruments 4, it is possible to flag events from the code, and get a more detailed picture in instruments.

    First, you have to link the app with the DTPerfomanceSession framework. Then, import DTSignalFlag.h in the classes you want to inspect.

     #import <DTPerformanceSession/DTSignalFlag.h>
    

    Finally, you can just flag a given event with

    DTSendSignalFlag("net.volonbolon.appName.eventName", DT_POINT_SIGNAL, TRUE);
    

    Or, if you are interested in follow the execution of a oven task, you can set the start and end flag with:

    DTSendSignalFlag("net.volonbolon.appName.eventName.start", DT_START_SIGNAL, TRUE);
    

    and

    DTSendSignalFlag("net.volonbolon.appName.eventName.end", DT_END_SIGNAL, TRUE);
    

    Now, in instruments, find the flags table (Window > ManageFlags) and choose Signal Flags from the Displayed Flags menu.

    Run the app in instruments, and you are the events are going to be marked with a flag.

  5. Silos 2 (Calendars on iOS)

    Since the introduction of iOS 4 it is possible to fetch, create, edit and delete events from the user’s calendar database through EKEventStore. The calendar kit store is also protected by the iOS.

    The event store kit had diverged between iOS and OS X regarding initialisation. For the desktop, -init was deprecated, and replaced with -initWithAccessToEntityTypes:. This new designated initialiser takes as argument the entity type you want to access:

    typedef enum {
        EKEntityTypeEvent,
        EKEntityTypeReminder
    } EKEntityMask;
    

    With OS X, access is automatically granted.

    iOS 6 still have -init as the designated initialiser, but you have to request access to the user’s calendar database with -requestAccessToEntityType:completion:

    EKEventStore *store = [[EKEventStore alloc] init];
    
    [store requestAccessToEntityType:EKEntityTypeEvent
                          completion:^(BOOL granted, NSError *error) {
                              <#code#>
                          }];
    

    The user will be prompted just one to determine if he or she authorize the app to access the store. Any subsequent instantiations of EKEventStore uses existing permissions. When the user is done authorizing (or not) the app, the OS will either run the completion handler (iOS 6), or broadcast an EKEventStoreChangedNotification (iOS 5). If no access is requested or granted, then the database handle to the app will be empty. Thus, upon receiving the notification, you have to send a -reset message to the store in order to populate the database.

    There is also a class method, +authorizationStatusForEntityType: to query the store about the authorization status of the app for a given entity type. This will return:

    typedef enum {
       EKAuthorizationStatusNotDetermined = 0,
       EKAuthorizationStatusRestricted,
       EKAuthorizationStatusDenied,
       EKAuthorizationStatusAuthorized
    } EKAuthorizationStatus;  
    

    EKAuthorizationStatusNotDetermined means that the app had never requested authorization, EKAuthorizationStatusRestricted means that the app is not authorized to access the store, and neither the user to change that.

  6. Silos

    Last February, something happens. A very popular iOS application was found phoning home the whole address book of users. Granted, it was not the only one. Many where capturing all sort of data to phone home. Apple was not to blame here, after all, the contract forbids to gather user information without prior consent. But the policy was not really enforced. Apple took some heat after the Address Book-Gate and decided to change things in iOS 6. From now on, third party applications access to contacts, calendars, reminders and photos is mediated by the OS, and authorised by the user.

    Address Book

    In Address Book, the protected store is the address book ref, if you call ABAddressBookCreate, the os will perform the authorisation.

    CABAddressBookRef addressBook = ABAddressBookCreate();
    

    If the app was not previously authorised, and if the user is enabled to authorise the app, an alert view is showed with a brief explanation of what is happening.

    The OS check is transparent to the application, ABAddressBookCreate is the same API used in iOS 5, and even without changing a single line of code, in iOS 6 the address book reference is protected. But even if you don’t really have to change anything, some changes are going to be greatly beneficial.

    For instance, the protected APIs are going to block the thread until the user either grants or reject the authorisation. In other words, wraps all your calls in a dispatch block to allow the rest of the app to keep running.

    Another thing to check is the returning value. In the past, the likelihood to get back a nil object was small. Now, if the user does not grant access to the siloed store, the function will return nil1.

    Also, check whether the API you are using has been deprecated. ABAddressBookCreate for instance has been deprecated and apple recommends to replace it with ABAddressBookCreateWithOptions that takes a pointer to a CFErrorRef that will be populated with more information, if needed (oddly enough, the first argument, options is a reserved CFDictionaryRef, for now, we have to pass NULL)

    CFErrorRef error = NULL;
    ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
    

    The error can be either raised because an store problem was found (kABOperationNotPermittedByStoreError) or because the user had denied access to the database (kABOperationNotPermittedByUserError).

    The first time the function is ran, it will returns, immediately, an empty read-only database. At this point you should register with ABAddressBookRegisterExternalChangeCallBack

    if ( addressBook == NULL ) {
        NSLog(@"%@", error);
    } else {
        ABAddressBookRegisterExternalChangeCallback(addressBook, addressBookChanged, (__bridge void *)(self));
    }
    

    And in your callback, update the address book reference with

    void addressBookChanged(ABAddressBookRef addressBook, CFDictionaryRef dicRef, void *context) {
        ABAddressBookRevert(addressBook);
    
        CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople( addressBook );
        CFIndex nPeople = ABAddressBookGetPersonCount( addressBook );  
        for ( int i = 0; i < nPeople; i++ ) { 
            ABRecordRef ref = CFArrayGetValueAtIndex( allPeople, i );
            NSLog(@"%@", ref);
        }
    }
    

    If you want, you can also check the app access status with the function ABAddressBookGetAuthorizationStatus that returns:

    typedef CF_ENUM(CFIndex, ABAuthorizationStatus) {
       kABAuthorizationStatusNotDetermined = 0,
       kABAuthorizationStatusRestricted,
       kABAuthorizationStatusDenied,
       kABAuthorizationStatusAuthorized
    }; 
    

    kABAuthorizationStatusDenied and kABAuthorizationStatusAuthorized are self explanatory. kABAuthorizationStatusNotDetermined means that the app had never tries to gain access to the store, thus the OS does not really knows what to say. kABAuthorizationStatusRestricted is issued when the user is not allowed himself to grant access to the store (parental control might be enabled). As far as the app is concerned, kABAuthorizationStatusRestricted should be consider a no.

    Testing

    It is very important to note that data isolation is NOT supported on simulator. Unfortunately, only the device is supported. And since authorisation UI is only showed once, but any test have to check all the possible results, you will have to reset settings. Is going to be tiresome, but needed. And please, fail gracefully. Try as hard as possible to keep going even if the user does not grant access to some store.


    1. Well, in fact, some APIs were returning nil even prior to iOS 6, in order to prevent blocks. In that cases you had to handle change notifications. 

  7. UDID replacements

    We all know what UDID is. We all also knows that it has been deprecated in iOS 5. Apple told us to use CFUUIDCreate function and save the resulting string to NSUserDefaults. But that’s not even half of the UDID story. Luckily, iOS 6 introduces a few new APIs to replace the deprecated UDID. None of the three different replacements are hot wired to the hardware, so they are safer than the UDID. The big difference between these three new APIs is, basically, the scope within you need the token to be valid.

    Application Identifier

    iOS introduces a whole new class, NSUUID. UUID are identifiers standardised by the Open Source Foundation. They are composed by a 16-octet (128-bit) number. Its canonical representation is a 32 hex string, displayed in five groups separated by hyphens:

    98d2374a-332c-11e2-9183-d49a20e7cca4
    

    The new class expose two different methods to create and returns a new random UUID (you can also initialise a UUID with bytes or a hex string, perhaps obtained from a cloud service).

    + UUID
    – init
    – initWithUUIDBytes:
    – initWithUUIDString:
    

    Once you have the UUID object, you can get the raw bytes, or the ASCII representation with:

    – getUUIDBytes:
    – UUIDString
    

    Once the UUID is saved to the defaults, it is part of the application data, meaning that it will be persisted for as long as the application is installed on the device. But because it is backed-up with the standard synchronisation process, if the user accidentally deletes the app, nothing is lost when he or she reinstall it from the backed version. The same is also true if the user restore the app to a new device.

    From the functional perspective, is little more than a wrapper to CFUUIDCreate. You need something more? Perhaps you would like something to share amongst a few apps of your own? well, there is a new API for that.

    Identifier for Vendor

    UIDevice class now includes a new API to get an ID that is associated with a team, -identifierForVendor. The idea here is quite simple. If you call this API you are going to get always the same identifier. Even if you call it from two different apps as long as they are signed with the same Team ID. The vendor ID is manage by the OS itself and, in terms of life time, it will be persisted for as long as there is at least one app of your team on the device.

    This ID is not a hash of the team ID, it is associated with the Team, but it is not composed with it. For instance, let’s say you install AppA signed with your team ID, and you call identifierForVendor on it. The OS will promptly create a new ID for your team, and returns it to AppA. Now, you install a second app, AppB also signed with your team ID, and calls identifierForVendor. The OS will returns exactly the same identifier produced for AppA. Now, you remove both of them, and the OS forgets the identifier. And then you install either a third App, AppC, or re-install from new AppB or AppC. The OS is going to produce a new identifier for your team.

    The synchronisation process will backup the identifier, but you cannot push it to a new device, as in the case of the NSUUID. In that respect, is like the UDID.

    But this second identifier is only shareable between your own apps. Perhaps you need something more open, perhaps something to support advertising.

    Aaron Cedercrantz notes that if the OS was updated to iOS 6 Over the Air, -identifierForVendor might return 00000000-0000-0000-0000-000000000000 (Radar Report) Thanks for the tip.

    Identifier for Advertising

    There is a second new API hanging in UIDevice, -identifierForAdvertising. This is unique for the device, is available for all the applications, and is the recommended API for advertising, in fact, iAd has adopted it in iOS 6. The main advantage in respect to UDID is that this is not hardcoded to the hardware. Is generated by software, and can be easily reset with the Erase All command in settings.

  8. Pro Multithreading and Memory Management for iOS and OS X with ARC, Grand Central Dispatch, and Blocks →

    Listen really careful. If you want to understand multithreading on iOS / Mac, do yourself a favour, buy this book.

  9. Using Method-Swizzling to help with Test Driven Development →

    Years doing stupid things like changing drawRect in navigation bars to customising them, and never realise how useful Method-Swizzling could be for testing apps. OCMock and Method-Swizzling are going to really love each other in my next tests.

  10. (Source: vimeo.com)