The last two are identical; "atomic" is the default behavior (note that it is not actually a keyword; it is specified only by the absence of nonatomic
-- atomic
was added as a keyword in recent versions of llvm/clang).
Assuming that you are @synthesizing the method implementations, atomic vs. non-atomic changes the generated code. If you are writing your own setter/getters, atomic/nonatomic/retain/assign/copy are merely advisory. (Note: @synthesize is now the default behavior in recent versions of LLVM. There is also no need to declare instance variables; they will be synthesized automatically, too, and will have an _
prepended to their name to prevent accidental direct access).
With "atomic", the synthesized setter/getter will ensure that a whole value is always returned from the getter or set by the setter, regardless of setter activity on any other thread. That is, if thread A is in the middle of the getter while thread B calls the setter, an actual viable value -- an autoreleased object, most likely -- will be returned to the caller in A.
In nonatomic
, no such guarantees are made. Thus, nonatomic
is considerably faster than "atomic".
What "atomic" does not do is make any guarantees about thread safety. If thread A is calling the getter simultaneously with thread B and C calling the setter with different values, thread A may get any one of the three values returned -- the one prior to any setters being called or either of the values passed into the setters in B and C. Likewise, the object may end up with the value from B or C, no way to tell.
Ensuring data integrity -- one of the primary challenges of multi-threaded programming -- is achieved by other means.
Adding to this:
atomicity
of a single property also cannot guarantee thread safety when multiple dependent properties are in play.
Consider:
@property(atomic, copy) NSString *firstName;
@property(atomic, copy) NSString *lastName;
@property(readonly, atomic, copy) NSString *fullName;
In this case, thread A could be renaming the object by calling setFirstName:
and then calling setLastName:
. In the meantime, thread B may call fullName
in between thread A's two calls and will receive the new first name coupled with the old last name.
To address this, you need a transactional model. I.e. some other kind of synchronization and/or exclusion that allows one to exclude access to fullName
while the dependent properties are being updated.
I'm using an asynchronous connection with MGTwitterEngine and it sets the authorization in the NSMutableURLRequest
(theRequest
) like so:
NSString *authStr = [NSString stringWithFormat:@"%@:%@", [self username], [self password]];
NSData *authData = [authStr dataUsingEncoding:NSASCIIStringEncoding];
NSString *authValue = [NSString stringWithFormat:@"Basic %@", [authData base64EncodingWithLineLength:80]];
[theRequest setValue:authValue forHTTPHeaderField:@"Authorization"];
I don't believe this method requires going through the challenge loop but I could be wrong
Best Answer
Your link is comparing an very old version of ASIHTTPRequest - http://allseeing-i.com/ASIHTTPRequest-1.5 has more recent stats.
I'm finding it difficult to say much without repeating much of what I already said on ASIHTTPRequest vs NSURLConnection.
I've seen bugs in both NSURLConnection and ASIHTTPRequest; the advantage of ASIHTTPRequest was that I could fix the bugs in it! (Ben is good at merging in fixes to the mainline, and also very good at fixing bugs reported to him - though I have yet to take advantage of the latter :-) ).
Depending on your app, you may also have to write a lot of code on top of NSURLConnection if you decide to use it (eg. if you need caching), going through the full design/code/test/debug cycle - or you can use ASIHTTPRequest, which has a built in caching layer that's already been tested & debugged.
I think I'd look at the question a different way: If you use ASIHTTPRequest, you have an awful lot of flexibility and power available to you - is there any good reason to build an app using NSURLConnection?