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.
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.
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.
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.
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.
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.
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.
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. ↩
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.
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.
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.
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.
Listen really careful. If you want to understand multithreading on iOS / Mac, do yourself a favour, buy this book.
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.
Organization is, I’m pretty sure of that, the cornerstone of the telecommuter. As a telecommuter, you don’t have the benefit of discreet boundaries, in space or in time, so you have to be strict on how you manage your time. Otherwise, you will spent the whole day tweeting. And unless your name is Justin Halpern, tweet is not going to pay the rent.
Interruptions For the past 15 years, I have tried every Getting Things Done system I knew about. They all seems pretty impressive, and they are all filled with big promises. I failed miserably with all of them, well, almost all of them.
The thing is, I’m a programmer, I like to write code, I don’t like to dance around folders, and post-its, and have dozens of different rules to organize my day. I don’t want to learn rules just to keep my todo list trim.
Then I found the Pomodoro Technique. It also is overflown with dozens of marketing superlatives, and fancy words. But at then is just as simple as concentrate on the task for a few minutes, then rest a few more minutes, and start all over again with the task. You have to try to forget about the world, and for 25 minutes immerse yourself in the job. Is dead simple. And is actually how I was working ever since college. I’m a big procrastinator, so, specially when the job at hand is boring, I treat myself with 5 or 10 minutes of absurd laziness after half an hour of work. Give or take a few minutes, and you have Pomodoro.
There two really important aspects that Pomodoro tries to cope. First, it is easy to procrastinate when the job is boring, or the task is overwhelming. With Pomodoro, you act like a recovered alcoholic, one pomodoro at a time. You just have to worry for the next 25 minutes.
The other one is unplanned interruptions. Interruptions are expensive. Imagine yourself thinking really hard about a bug in your code. Ten minutes into the debugging session a colleague storm into your office to chat about the last episode of The Big Bang Theory. Five minutes later, he’s gone. But you don’t even remember what’s the bug you were working on. Don’t take me wrong, I love Sheldon Cooper like any other geek, but kills my mood to waste so much time. The interruption cost is not only the 5 minutes spent talking about some TV show, but the 10 minutes before that (because you are no longer able to remember what you’ve been working back then), and the 10 minutes after that (trying to remember what you were thinking).
Obviously, some times interruptions are needed. For instance, the server is down, and you had to take a look at what’s happening because thousands of users are getting angry. But for the most part, they has to be avoided. That’s pretty much my summation of Pomodoro, as far as I am concerned, set a timer and forget about the world until the timer fires. No interruptions for 25 minutes. No email, no twitter, no web (only to browse documentation), no nothing. You and your code.
But wait a minute, how’s the timer firing up is any different of an email, or your colleague talking about The Big Bang Theory? Well, for once, you have allocated more time, so the chances of actually getting something done before the timer is fired are much greater. And if you have done something useful, then the chances of get into “procrastination mode” are smaller. Is like a game (actually, I play a game with my self, trying to beat my pomodori record each day). You also know when the timer is about to get off, so you can project in advance. If you know you have just one minute left in your Pomodoro, you can create a dump note with all your ideas about what you were doing. Then, as soon as the rest is done, you can start right at the same point (you don’t have to think about what you were thinking, you have your notes there to help).
So there it is, I hate interruptions. Does that means I code in a cave, from where occasionally I emerge to deliver my product? No. I know guys that are able to rewrite Unix in a couple of weeks by themselves. I’m not one of them. You have to be a genius for that, and I am not a genius. I love to engage with smart people, love to have ideas flowing all over the place, waking up in the middle of the night with something that I have to share with the guys because this is really awesome. We really have to implement it.
Because of that, I need human interaction. At least once a day, a brief phone (or Skype) call to let everyone else knows what I’m running after, and what the rest is working on is the needed. And twice or thrice a week, a longer call is also useful to understand where the team is headed.
The daily call is just a five minutes chat to get everyone in the loop. “Hi there, what are you working on?” Excellent, then I will start with X, hopefully tomorrow X is going to be done, and you can start with Z”. That’s all. Really
The longer calls should never be longer than half an hour, and if possible, the agenda should be available to all participants before the call. If the agenda is public to everyone, then each member of the team can think about ideas to share at the call. And more importantly, everyone in the call can play Miss Sweetie Poo. The more time a coder spent talking, the less time he or she has to actually code. Managers all around the world, remember that.
The calls has to be scheduled, so everyone can organize to take the calls avoiding interruptions.
Mail is really useful to communicate between two persons, but it is not that good to handle anything else. Don’t use email to alert about a bug. Why? Because everyone receives dozens of messages per day, and is really easy to spend long minutes just looking for the message that reports some bug to get the details. A good Issue Tracking System is as important as a Version Control System 1. There are services with all the whistles. But being a simple guy, all I need is just a plain old board to record bug reports, and features requirements. The one included in Github is excellent. Pivotal Tracker and Lighthouse are terrific as well. And if you are a little paranoid, you can run your own instance of Redmine.
And talking about features requirements, the ideas behind them has to be nurtured. Yes, phone calls or email messages are great to ignite the spark, but wikis are even better to make them grow. But soon enough threads became a mess. Wikis, on the other hand, are great to consolidate ideas, and incubate them. It is just one piece of text, collectively composed, but just one piece. Once again, Github offers a good enough solution to implement Wikis.
Private email groups are perfect to share problems and ideas between more than two members of the team. Why they are better than plain vanilla email? Because you are broadcasting to the whole team. So, let’s say you have a problem, the solution is elusive. Why don’t tell the rest of the team about it? Most of the time, the simple exercise to think carefully about the problem in order to write it down and share it with the rest, will help you to find a new perspective to fix it. And if that’s not the case, actually shooting the message will give everyone the chance to help. The same is also true to enhance ideas for features. Wikis are great to have a uniform repository for new born ideas, emails are great to discuss details that will be added to the wiki description.
When files has to be shared, nothing like Dropbox. Really. Even a free account will give the team a lot of space to share files. Again, for the paranoids (and yes, I am a little paranoid myself), a simple FTP or sFTP box is enough. At least for geeky teams, if commercial fellas has to be able to share files, you better set a dropbox account.
There are plenty of technology that helps telecommuters team to get things done. Let’s take a brief look to some of them.
Repeat after me, you will never code more than 2 lines of code without GIT, HG, or anything else (yes, including CVS is you are masochist. Not my cup of tea). ↩
Apple has introduced new APIs to Lion and iOS that allows developers to edit Core Data managed objects concurrently much more easy.
Until iOS 5 or Lion, the contexts (instances of NSManagedObjectContext), were confined to threads. Context were associated with a given thread, the only safe way to communicate between contexts was to use ObjectIDs, immutable references to objects that each context used to set its own stack.
The setup was easy to understand, and quite efficient to handle operations. But because the developer had to track which context goes with which thread, it was prone to bugs.
With iOS 5 and Lion, two new concurrency types where introduced, to use them, a new initializer was added to NSManagedObjectContext:
- (id)initWithConcurrencyType:(NSManagedObjectContextConcurrencyType)ct
The ct parameter indicate how the context should behave when accessed concurrently.
| Constant | Description |
|---|---|
NSConfinementConcurrencyType |
Default Value. The system is confined to a thread. Objects cannot be accessed outside the thread |
NSPrivateQueueConcurrencyType |
The context is associated with a private queue. |
NSMainQueueConcurrencyType |
The context is associated with the main queue. Because of that, this is really useful to populate UI Widgets. |
If the context is initialized with -init, it is configured as NSConfinementConcurrencyType.
Context configured with either NSPrivateQueueConcurrencyType os NSMainQueueConcurrencyType are associated with a queue (either a private one, or the main one), and they can only be accessed through that queue. Once the context is created, you can talk to it through -performBlock: 1. The block is then safely performed in the queue associated with the context. Inside the block, Managed Object Context API should be used normally.
NSMainQueueConcurrencyType is very similar to NSPrivateQueueConcurrencyType, the only difference is that her the queue is not private, but the main queue. The same used by UIKit for the UI widgets. Because of that, any object living in the main queue can message the context directly. If we want to access it from a different context, then we can use -performBlock: (or the usual dispatch_async / dispatch_get_main_queue tango).
NSPrivateQueueConcurrencyType queues are really private. Apple does not expose them, and dispatch_get_current_queue should not be used to get a reference to it. The easiest way to coordinate more than one context is through a dispatch_group.
The new APIs to message context distinguishes themselves on how they are run. -performBlock is asynchronous, it is considered a user event, and thus is wrapped in an event loop. Calls to -performBlock: inside a block are added to the end of the queue, so we should not consider them as re-entry points.
On the other hand, as you might expect given the name, -performBlockAndWait: runs asynchronously. It is not considered a separate event, thus is not wrapped inside an autorelease pool. Calls to this API inside the block are run instantaneously, and can be used as re-entry points.
In both these methods, it is illegal to throw exceptions out of the block.
Core Data events are triggered automatically, as the main event loop (actually, usually they are coupled together). At the end of each event, core data automatically performs:
NSNotifications dispatchThe queues prevent a lot of bugs basically by assuring users a space where it is safe to talk to context. But Apple also provided means to share objects between different context, even unsaved objects. The trick is to nest contexts.
To nest contexts a new API was introduced in iOS 5 and OS X Lion, -setParentContext:. Once a context is configured as a child of another context, and the former is saved, the changes are pushed up to the parent. Because there is no actual IO between these two contexts, the parent can call asynchronously -save: to write down the changes without hogging the caller thread.
NSManagedObjectContext *child = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
NSManagedObjectContext *parent = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[child setParentContext:parent];
// A lot of juicy stuff here
NSError *childError = nil;
[child save:&childError];
[parent performBlock:^{
NSError *parentError = nil;
[parent save:&parentError];
}];
Because any context can have more than one children, you can save changes in one child, and pull the changes from the parent to other children as needed.
Child changes are only pushed up one level. From child to parent, not from child to grandparent. But fetching in an ancestor will pull to all descendants. Calling -objectWithID: pulls as few levels as necessary. A parent can fetch all the required data in the background, and then its children can call -objectWithID only on the objects that it wants, reducing the resources needed to perform the operation.
NSManagedObjectContext *mainMOC = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
NSManagedObjectContext *backgroundMOC = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[mainMOC setParentContext:backgroundMOC];
[backgroundMOC performBlock:^{
NSError *error = nil;
// Define some request
NSArray *results = [backgroundMOC executeFetchRequest:request error:&error];
if ( [results count] > 0 ) {
NSManagedObjectID *objectID = [[results objectAtIndex:0] objectID];
[mainMOC performBlock:^{
NSManagedObject *storedObject = [mainMOC objectWithID:objectID];
[[self textView] setText:[storedObject valueForKey:@"txt"]];
}];
}
}];
And since parents have to be able to produce a safe space to talk to children, you have to choose a queue type for any context that is going to be used as parent. I would argue that perhaps the best pattern is to deploy a private queue based parent, and then assign main queue based children to deal with UI widgets, but that’s up to another discussion.
Well, actually two new APIs with performBlockAndWait:. ↩
Don’t take me wrong, I strongly believe that anyone writing a compiler deserves my respect. Is not a task for the feeblest. Yet, my relationship with GCC was not always a good one. How not to hate the cryptic messages spilled by the parser from time to time? Well, let’s praise Stallman irreducibility, Apple condemn GCC and replace it with LLVM1. Regardless of the actual reasons, the change brings a better compiler to the table. One that can parse and understand code even better than my cocker spaniel, which is much more of what GCC gives us. And because the compiler is able to understand the code, well, to understand it a little better than GCC, then Apple decided that LLVM can take care of the memory-management tasks. In Apple own words:
“The compiler has a complete understanding of your objects, and releases each object the instant it is no longer used, so apps run as fast as ever, with predictable, smooth performance.”
And yes, the best part is that this is not GC. It is just let the compiler insert the release when needed. ARC works on top of the familiar reference counting.
Basically, ARC requires Apple LLVM compiler 3.0 (or later, as the time of writing, the default compiler is Apple LLVM 3.1), and the compiler flag -fobjc-arc set. Both of these requirements are set by default by Xcode 4.2 and later.
As you must remember, the only secret of reference counting is to keep an eye on ownership.
+alloc, +allocWithZone: or +new. -copy, -mutableCopy or -retain)-release. To ease the task, ARC introduced a few qualifiers to instruct the compiler how the objects ownership would be handle.
__strongDefault qualifier.
Semantically,
NSString __strong * someString = [[NSString alloc] initWithString:@"some string"];
Is the same of
NSString * someString = [[NSString alloc] initWithString:@"some string"];
The ownership is relinquish at the end of the present scope. This means that the release message is send automatically when the control flow leaves the scope where the strong variable was obtained.
By the way, any variable qualified with __strong, __weak and __autoreleasing are initialized to nil.
id __strong someStringVar;
id __weak someWeakVar;
id __autoreleasing someAutoreleasingVar;
Is semantically the same of
id __strong someStringVar = nil;
id __weak someWeakVar = nil;
id __autoreleasing someAutoreleasingVar = nil;
This seems small, but add o the security of the code (we are no longer dealing with undefined states).
The strong reference will generate ownership even for objects that are not created.
NSSet __strong *set = [NSSet set];
Here set is owned for the whole life of the scope.
Members variables can be qualified as __strong as well. In fact, because the compiler can insert automatically the members variable, all we need to do is to define the property.
@property (strong) CLLocation *latestKnownLocation;
And obviously, synthesize it.
@synthesize latestKnownLocation;
As long as the class instance is alive, there is going to be a strong reference to latestKnownLocation.
__weakSo, by default (we don’t even have to type __strong), the compiler will take care of the memory management most of the time. But, what happens, for instance, when two objects refer each other. That’s exactly the kind of relationship that exists between an object and its delegate. We have a tableViewDelegate which is going to serve as a delegate for a UITableView. If the table view delegate property is qualified as strong, and the same happens with the tableView property of the delegate, then, when the delegate reference counter is never going to be zero, because there is always a reference from the table view, and the table view reference counter is also impossible to reduce to zero, because it is referenced from the delegate. This is circular reference.
To avoid these kind of situations, the rule of thumb is not to claim ownership of delegates and other objects that refers to each other (like IBOutlets for instance). Let’s revisit our previous example, because the table view does not claim ownership of the delegate, the delegate can be deallocated with no problem, and because there is no delegate referencing the table view, the the table view can also be deallocated. Even better, when the object that a variable qualified as __weak is discarded, the variable value is set to nil.
The __weak qualifier is only available for iOS 5 (or later) and OSX Lion (or later). For older OSs, __unsafe_unretained qualifier must be used instead.
__unsafe_unretainedThis qualifier exclude the variable from ARC mechanisms. Because no check is perform, and references are not niled, if you set a variable as __unsafe_unretained you hold the responsibility of checking if the object is still there when needed.
__autoreleasingBecause ARC handles the little nuances of memory management, it is very rare to use auto release mechanism explicitly, thou the environment provides the needed tools.
The thing is that when an object is referenced but not created, i.e., none of the methods in the family +alloc, or -copy is called, the object is automatically registered to the auto release pool. When an object is returned from a method, the compiler checks the name of the method. Naming convention is important here because the compiler used the method name to know how to handle the returned object ownership.
Most programmers are going to use __autoreleasing mainly to handle errors via indirect pointers. In ARC indirect pointers are by default qualified as __autoreleasing. The method that handle the error will take an __autoreleasing parameter:
- (BOOL)performWithError:(__autoreleasing NSError **)error {
// try something prone to failure
if ( failure ) {
*error = [[NSError alloc] initWithDomain:@"Some Error Domain"
code:101
userInfo:nil];
return NO;
}
return YES
}
And the caller portion would be something like
NSError __autoreleasing *error = nil;
if ( ![self performWithError:&error] ) {
// Deal with the error
NSLog(@"error: %@", error);
}
There are plenty of code that is not ARC ready (yet). That’s not a big deal. Once again, ARC is not GC, and it works on a a copyable unit basis. To add non-ARC units to your app, Select the Target you are working with, then the Build Phases tab, and look for legacy units in Compiled Sources. Add -fno-objc-arc to each one. Recompile. You are done.
You would like to think that they choose compiler over the other because one is better, but that’s not the whole history. The tipping point was the more forgiven nature of LLVM License ↩
Los momentos de mi vida en los que yo he crecido, tienen que ver con los fracasos; los momentos de mi vida en los que yo he empeorado, tienen que ver con el éxito. El éxito es deformante. Relaja, engaña, nos vuelve peores, nos ayuda a enamorarnos excesivamente de nosotros mismos. El fracaso es todo lo contrario: es formativo, nos vuelve más sólidos, nos acerca a las convicciones, nos vuelve coherentes. Si bien competimos para ganar, y yo trabajo siempre para ganar cuando compito, si no distinguiera qué es lo realmente formativo y qué es secundario, me estaría equivocando mucho.
Happy 94th Birthday, Richard Feynman!
Bonus: Here is a video of Dr. Feynman, playing bongos, and really wanting some orange juice.
Time after time good ideas are wasted in poorly designed apps. The problem, usually, is the lack of understanding of the target of the app, and how the app is going to be used in the real world. The world of the app has to be chartered before the first line of code. We have to figure out what we are going to deliver to our customers in advance. We have to be intentional. No real world architect dare to start building without a blueprint, and best architects spend lots of times with their customers in order to know what they want, even before the blueprint.
Most of the time, every single app starts with a ‘great idea’, and a big list of ‘nice to have’ features. The problem is that compiling a list of features is easy, and is also easy to implement them. Not trivial, but easy. The end result? Apps that are no longer solutions but containers where we shoehorn features. The true genius, we already know that, is not to add, but to remove what is not really needed. Ask Leonard Cohen if you don’t believe me.
That big list is not what we need. Our goal is to define a solution. The very best apps on the App Store are those that solve a problem for a customer. The problem doesn’t have to be huge, but the solution has to be useful.
One of the best way to make sure we are accurately defining a solution instead of just creating a container is to distill the most important aspects of the app in one sentence. We first need to define what makes out app different from the rest of gazillion apps in the store. What makes it special for the customer. And yes, it has to be something special, otherwise, why bother? Then we have to think about the best solution for the need, and finally, the audience. The audience definition, the target in marketing parlance, is critical here. It will help us to better understand the problem at hand, and obviously, improve the solution. Feel free to use the next template:
(app differentiator)(proposed solution), for (app audience)
Let’s try to exercise a little this idea. Let’s pretend we realize there is no good enough medical imaging apps in the store. Sure, there are plenty of excellent of excellent imaging apps out there, but they all lack tools to help doctors measure anatomical features. Our proposed solution, then, is to create an app that contains these measurement tools.
So, we already know the audience of the app is going to be composed by doctors. That’s not enough. Remember, the better we know our target, the best solution we can deliver. For instance, the prototypical customer of the app is going to use it in his or her office? When on the go? Or perhaps when performing a surgery? Three different scenarios that ask for three different solutions. And we might be talking about the same person, just changing the context. When in her office, the doctor has plenty of time to focus on details. We can add more items to the toolset, and let the doctor experience drive the flow. The UI might be monochromatic, clean, scalable and productivity oriented. When on the go, the doctor has no time to read the image and he can use the help of some Artificial Intelligence to focus on features that are particularly interesting. The toolset might be limited, but connectivity tools should be add to let the doctor report back to the hospital, if needed. When in the OR, the doctor does not need a lot of tools, and certainly she is not going to email anything. Buttons should be big, easy to tap, and colors should be shocking. Knowing a little bit more about the target pays, a lot.
With that in hand we can think on:
Easy to use Medical Imaging app to review and report for doctors on the go.
or
Comprehensive Medical Imaging app to analyze, edit, organize and share for doctors at the office.
or
*Really easy to use Medical Imaging tool to help visualize key anatomical features for doctors at the OR. *
The product definition statement then is going to be the cornerstone of the whole design process. Now you can start compiling the list of desired features, you have a tool that will help you to decided if the feature at hand worth the list. You can ask yourself if the new feature is critical or not to fulfill the product definition.
The relevance of each feature is really important. The smaller the feature set, the better. That’s not equals a cripple app. It make no sense to deliver with fewer features than the needed to accomplish the goal of the app. If the product definition ask for 50 features, then go for it.
The rule of thumb is to include the most frequently used features by the majority of the users. Because the app is simple, doesn’t mean it won’t be valuable to your customers.
But not features are critical. The ones that are, obviously, should be there since day one, but perhaps there are others that can be added later. A road map is a helpful tool to know what has to be there in each version. Version 1.0 is for the most critical features. If you are not embarrassed by version 1.0 feature set, then you waited too long. You have to build a road map, you have to know that feature x, as important as it is, might not be critical, if that’s the case, feature x is going to be introduced in version 1.1 or 2.0. Software development, specially nowadays, is not a hit or loose. At least not regarding the feature set (quality is a different issue, is hard to convince a user to give another try to a crappy app). We are not burning disk anymore to deploy software. Users are going to be happy if they discover a new version of the tiny app that does one thing, but does it really well, specially if this new version add more features. And the App Store is your friend here, it is going to pop your new version as soon as it is available to all the users. Software distribution is cheap, version 1.1 could be deployed a week later than 1.0. No problem.
Road Maps are key. You have to be able to allocate resources for the whole map. Version 1.0 is just one step, perhaps the most important (if it is crappy, then you have no second try). Please, read the article of Matt Mullenweg I’m linking above. The first version of the iPod was quite limited, but the people behind it was really careful when choosing the critical features that were needed to implement, and the implementation itself. The second generation packed more features, and the people love them.
But why wait till the whole feature set is complete. Because then you can be pretty sure your market is lost. And also because you are going to learn a lot from real users in the real world.
That being said, it is really, really important to remember that nothing is carved in stone. You have to be flexible, and hear what the audience is asking. Real world can be cruel, but if we are not working for our audience, then it doesn’t matter what we are doing. The application definition statement might be perfect, the feature set might be comprehensive, the road map might be smart. But as soon as version 1.0 hit the store a user will point the elephant in the room, and you might need to rethink the whole feature set and road map. That’s the beauty of this industry, is pretty much alive.
And because you need to be flexible, you have to learn the design patterns that will help you. We have talked about patterns in the past, and I promise I will be back to them. The important thing is to try to devise an architecture where the different modules are not tightly coupled, and you can easily change how they interact. For instance the delegate pattern is better than subclassing (or retain the responsibility of a task in a single class).
Perhaps one of the less known, and yet more useful commands in the git interactive add is patch. Let’s say you start working on a file to fix a bug (yes, I know, your code does not have bugs, but let’s pretend for a moment), Once in the file, you found a line that needs some refactoring, and just because you are a really nice person, you add some comment to a method that has nothing to do with the line you’ve refactored, or the bug you fixed. Three different things in the same file. Sounds familiar? Sure you can issue something like:
git commit -a -m "Cleaning Code"
And you are not lying. But, for the sake of being a good citizen, wouldn’t be better to split the whole stuff in three discreet commits, one for the line you’ve refactored, one for the bug you’ve fixed, and one for the comment you’ve added? This is exactly what path can do.
Instead of adding everything in just one stage, let’s enter the interactive session:
$ git add -i
staged unstaged path
1: unchanged +14/-14 algorithms.py
*** Commands ***
1: status 2: update 3: revert 4: add untracked
5: patch 6: diff 7: quit 8: help
What now> p
Type p in the prompt, and git will list all files in the working directory:
staged unstaged path
1: unchanged +16/-15 algorithms.py
Patch update>> 1
Then you just need to select the number of the file (or files, because you can add many files at one if you need) you want to path. In this case 1. Git is going to print out a lot of things once you’ve done selecting files. It might be a little overwhelming, so let’s take a look at it.
First, GIT will tell us what is taken into account, In this case the version a and the version b of the content of the file algorithms.py:
diff --git a/algorithms.py b/algorithms.py
index 5a835ea..f9d0cdb 100644
Then, it says that the content from file a (the HEAD), is identified with - and the content from b is identified with +
--- a/algorithms.py
+++ b/algorithms.py
And then the content of the file itself.
@@ -10,24 +10,25 @@ Copyright (c) 2012 __MyCompanyName__. All rights reserved.
import sys
import os
-from random import randrange
-
+from collections import defaultdict
def main():
- seq = [randrange(10**10) for i in range(100)]
- seq.sort()
- dd = float('inf')
- xx = 0
- yy = 0
- for x in seq:
- for y in seq:
- if x == y:
- continue
- d = abs(x-y)
- if d < dd:
- xx, yy, dd = x, y, d
- print '%d %d' % (xx, yy)
+ pass
+def max_perm(M, A=None):
+ """docstring for max_perm"""
+ if A is None:
+ A = set(range(len(M)))
+ if len(A) == 1:
+ return A
+ B = set(M[i] for i in A)
+ C = A - B
+ if C:
+ A.remove(C.pop())
+ return max_perm(M,A)
+ return A
if __name__ == '__main__':
- main()
+ main()
+
\ No newline at end of file
And finally, git ask what we want to do.
Stage this hunk [y,n,q,a,d,/,s,e,?]?
I know, I know, a bit intimidating the list of letters. And Linus seems to know that because, the default value is no other than ? which is going to print a help message:
y - stage this hunk
n - do not stage this hunk
q - quit; do not stage this hunk nor any of the remaining ones
a - stage this hunk and all later hunks in the file
d - do not stage this hunk nor any of the later hunks in the file
g - select a hunk to go to
/ - search for a hunk matching the given regex
j - leave this hunk undecided, see next undecided hunk
J - leave this hunk undecided, see next hunk
k - leave this hunk undecided, see previous undecided hunk
K - leave this hunk undecided, see previous hunk
s - split the current hunk into smaller hunks
e - manually edit the current hunk
? - print help
The option we are looking for is s.
Stage this hunk [y,n,q,a,d,/,s,e,?]? s
Split into 5 hunks.
@@ -10,6 +10,6 @@
import sys
import os
from random import randrange
-
+from collections import defaultdict
def main():
Stage this hunk [y,n,q,a,d,/,j,J,g,e,?]?
Then we can simply choose the hunks that we want to add for each commit. Once we are done selecting the hunk, we can update the content:
*** Commands ***
1: status 2: update 3: revert 4: add untracked
5: patch 6: diff 7: quit 8: help
What now> u
staged unstaged path
1: +1/-1 +15/-14 algorithms.py
Update>> 1
And commit with an appropriate message:
git commit -m "Importing defaultdict from collections"
If you don’t want to mess with the interactive session (truth be told, I rather not), then thee is also a shortcut to get right into patching mode.
git add -p
Perhaps, one of the most secure flows in the OAuth specs, because the access token is never exposed. The authorization is accomplished using an authorization code that then is traded for the actual access token in a server-to-server exchange. The client has no access to the access token. The flow starts when the resource owner is redirected to the API provider. In iOS we can simply start the process inside a UIWebView asking for the appropriate API endpoint, and passing the needed parameters
| Parameter name | Required | Description |
|---|---|---|
response_type |
Yes | A token describing what kind of response we are looking for. code if we are asking for an authorization code |
client_id |
No | string or number issued by the API provider |
redirect_uri |
No | URI where the resource owner is going to be redirected after authentication and authorization |
scope |
No | A list specifying the resources we are asking to access. Most API providers use space-delimited lists, Facebook use comma separated strings |
state |
No, but recommended | String with a unique value to validate the callback. Usually a hash |
To these parameters list, API providers can add their own values, for instance, in Foursquare you can specify if the device is touch based with display=touch.
Here the authorization call performed with Cocoa:
NSString *urlString = [[NSString alloc] initWithFormat:@"https://foursquare.com/oauth2/authenticate?display=touch&client_id=%@&response_type=code&redirect_uri=%@", kFourSquareOauthKey, kFourSquareRedirectURL];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlString]];
[urlString release];
[self.webView loadRequest:request];
[self.webView setDelegate:self];
[self.view addSubview:self.webView];
If the authorization is granted, the resource owner is then redirected to the redirect_uri with the following parameters added by the authorization server.
| Parameter name | Required | Description |
|---|---|---|
code |
Yes | This is the code generated by the server to be traded by the access token. Should not be used more than once. If used more than once, the server must deny the request and should revoke all tokens issued based on that authorization token |
client_id |
Yes when present in the request | The value send by the client. Should be used to validate the callback and prevent CSRF attacks. |
On the other hand, if the authorization is not granted, then the user is also redirected to the redirect_uri but this time with a parameter named error with a code identifying what wen wrong. The API provider can also add an error_description with a human readable string explaining the problem, and an error_uri with the location of a Web resource with more information about the problem.
The allowed codes for the error parameter are:
| Error Code | Description |
|---|---|
invalid_request |
The request is missing some required parameter or is otherwise malformed |
unauthorized_client |
The client is not authorized to use this method to request an authorization |
access_denied |
Either the resource owner or the authorization server have denied the request |
unsupported_response_type |
The request is not supported by the authorization server |
invalid_scope |
The requested scope is invalid, unknown, or malformed |
server_error |
The authorization server was unable to process the request |
temporarily_unavailable |
The* authorization server* is currently unable to handle the request due to a temporary overloading or maintenance of the server |
Once the client gets the authorization code, it can be traded for an access token performing a HTTP POST request composed with:
| Parameter name | Required | Description |
|---|---|---|
grant_type |
Yes | What type of gran access is required? authorization_code for a new authorization access code, refresh_token to renew the token, password when we have the resource owner password to trade for the access token, client_credentials when we have resource owner login credentials |
code |
Yes | The code obtained in step 1 |
redirect_uri |
Yes if the value was included in the authorization request | If redirect_uri was included in the authorization request, should be also included in this call. The UIR must be the same |
refresh_token |
Yes to renew the token | The refresh_token produced by this endpoint the first time it is called |
The client_id and the client_secret also has to be included in this call. They can be send as a HTTP Basic Authorization header (with client_id as the login, and the client_secret as the password). Some API providers allow users to send the two tokens as simple parameters for the request as well.
If the access token request is valid, and authorized, the authorization server issues an access token and sometimes a refresh_token as a JSON formatted payload:
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token":"2YotnFZFEjr1zCsicMWpAA",
"token_type":"example",
"expires_in":3600,
"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
"example_parameter":"example_value"
}
The access token and, if available, the refresh token should be kept secret. Many providers issue a short-lived access token. If that’s the case, you will find expires_in and refresh_token as parameters in the JSON response. The expires_in parameter indicates the remaining lifetime of the access_token in seconds. When the access token expires, the refresh token can be used to obtain a new one. To refresh the access token we need to perform a HTTP request to the token endpoint, specifying refresh_token for the grant_type parameter, and adding the refresh_token.
The access token is then used in all the API calls, without the need to crypto sign them anymore. Sometimes, we can add the token as a simple parameter in the request, thou, most of the API providers, prefer the token to be dispatched as a HTTP header.
OAuth defines four different grant types to obtain authorization:
client_id and the client_secret. Note included in the core specification, but also very popular, we can add two more flows: