how to use pointers in Objective c - objective-c

I have seen some iOS developpers using code like this :
- (void)setupWebView:(UIWebView**)aWebView {
UIWebView *webview = [[UIWebView alloc] init];
.....
if (*aWebView) {
[*aWebView release];
}
*aWebView = webview;
}
Do you know what'is this mean and why we use this ? thanks

- (void)setupWebView:(UIWebView**)aWebView {
That is awful. You should never have a method that returns void, but sets an argument by reference unless:
• there are multiple arguments set
• the method is prefixed with get
That method should simply return the created instance directly. And this just makes it worse -- is flat out wrong:
if (*aWebView) {
[*aWebView release];
}
*aWebView = webview;
it breaks encapsulation; what if the caller passed a reference to an iVar slot. Now you have the callee managing the callers memory which is both horrible practice and quite likely crashy (in the face of concurrency, for example).
it'll crash if aWebView is NULL; crash on the assignment, specifically.
if aWebView refers to an iVar slot, it bypasses any possible property use (a different way of breaking encapsulation).

It is a method to initialize a pointer. The first line allocates the object. The if statement makes sure that the passed in pointer-to-a-pointer is not already allocated, if it is it releases it. then it sets the referenced pointer to the newly allocated object.

The answer by #bbum is probably correct, but leaves out one aspect to the question that I see there. There are many examples in Foundation which use pointer-pointers in the method signature, so you can say it is a common pattern. And those are probably not a beginners mistake.
Most of these examples are similar in that they fall into one category: the API tries to avoid the usages of exceptions, and instead use NSError for failures. But because the return value is used for a BOOL that signals success, an NSError pointer-pointer is used as output parameter. Only in the probably rare error case an NSError object is created, which can contain error code and error descriptions, and localized descriptions and possibly even more information (like an array of multiple errors in the case of bulk operations). So the main success case is efficient, and the error case has some power to communicate what went wrong, without resorting to exceptions. That is the justification behind these signatures as I understand it.
You can find examples of this usage in both NSFileManager and NSManagedObjectContext.
One might be tempted to use pointer-pointers in other cases where you want multiple return values and an array does not make sense (e.g. because the values are not of same type), but as #bbum said, it is likely better to look hard for alternatives.

Related

NSUUID as Unique ID as replacement to NSManagedObjectID

I've run into some problems using NSManagedObjectID and it changing depending on it's saved state.
As such I've decided to use my own UniqeIDs as recommended in the docs and by others. I've seen many examples here on Stack Overflow and on other places where it's a simple matter of storing a NSUUID string value in a core data field.
However, this isn't quite enough for what I want. One of the useful things about NSManagedObjectID is that it is always the same object and can be compared by pointer, so you can post notifications around using the NSManagedObjectID as their object, anything that requires information about the entity can register for notification based on the NSManagedObjectID without writing additional code to check if the notification is indeed the one we're looking for.
However, would that be still be true if an NSString is passed around instead of the NSManagedObjectID? We're always supposed to use isEqualTo for NSString comparison, even if it might be the same object. I feel like using an NSString as an object for a notification is a bit of a no no.
In my case, it's pretty much guaranteed be the same object, unless objective c messes around with NSString behind the scenes. the uniqueID is generated once on insertion of an object, and would be passed around unaltered as required, and I simply want to replace all calls where I use NSManagedObjectID with something I can drop in with minimal changes.
A CFUUID would seem ideal, as they can be guaranteed to share pointer values, however CFUuidRef is not an objective-c object, so can't be used for notifications among other things. An NSUUID seems next to best apart from the caveat in the documentation that says they aren't guaranteed to be the same object. But if my NSUUID is created, stored and retrieved on a single object, could we guarantee the passed around NSUUID to be the same object throughout the application? If so, couldn't we say the same thing about an NSString? Even if we could, I'd be happier just going with NSUUID.
I can't pass around the Entity directly, as I'm using the notification to post information between separate threads. Even though I only ever modify the entities on the main thread, and entities can be accessed for readonly across threads, I've had many problems in the past, that all went away once I implemented a system based on using just the NSManagedObjectID.
Maybe I got you wrong, but why not passing around instances of NSUUID (if you do not want to use instances of NSString) and comparing them on equality?
#interface NSUUID(Equality)
- (BOOL)isEqualToUUID:(NSUUID*)other;
#end
#implementation NSUUID(Equality)
- (BOOL)isEqualToUUID:(NSUUID*)other
{
return [self.UUIDString isEqualToString:other.UUIDString];
}
// Only for completness
- (BOOL)isEqual:(id)other
{
if( [other isKindOfClass:[NSUUID class]] )
{
return [self isEqualToUUID:other];
}
return NO;
}
#end
BTW: The same reasons that make you feel badly using instances of NSString as notification object does not apply to instances of NSUUID?
BTW 2: Handling CF-objects in ARC code is not that difficult.

Why is assigned a nil to singleton's static variable

What is the advantage of using this:
+ (CardPainter*) sharedPainter {
static CardPainter* sp = nil;
if (nil == sp) {
sp = [[CardPainter alloc] init];
}
return sp;
}
instead of this:
+ (CardPainter*) sharedPainter {
static CardPainter* sp = [[CardPainter alloc] init];
return sp;
}
The static variable initialization is performed only once, so I see no advantage of the former.
Well, at a compiler level there's several overlapping reasons… the simplest to think about is that static variables are stored in a dedicated data section of your compiled application, which is just mapped into memory as-is. So the compiler has to know precisely what that is at compile time. The result of any Objective-C method call is unpredictable at compile time by definition and in practice - you never know for sure that something "interesting" won't happen at runtime to change the behaviour of that method call, so you don't know for sure what will be returned.
This is all a bit different from e.g. C++, for various reasons (a key one being that C++ has constructors, whereas Objective-C does not). But even in C++ it's still frowned upon for several reasons:
Constructor order is unpredictable, but it's easy and common to have constructors depend on each other, meaning your program can have undefined behaviour at runtime (including data corruption or crashing).
Initialisation of lots of non-trivial objects can be expensive. Doing it all together at launch time might be efficient, but it makes your app slow to launch, which is far worse.
The latter point applies equally to Objective-C. The more you can avoid doing at launch time, and instead do just-in-time, on-demand, the better the user experience generally is.
[ Note that there is one noteable exception to the "no static object instances" rule, and that's strings, of the #"foo" form. Those are actually encoded in your app's data section as real instances (of a special NSString subclass) that just get mapped in at launch and magically work as-is. But that's very carefully architected and the compiler & runtime are tightly coupled on that aspect, to make sure it all works smoothly. It doesn't and cannot apply generally. ]
Because if you dont ask, you gonna initiatlite "*sp" any time you call the "sharedPainter", losing any data.
So, if you ask if sp is nil and the answer is FALSE means "sp" is already initialized and it return the instance. If the answer is true, that means that sp is not initialized and just in that case you call the init function.

objective c "Did you forget to nest alloc and init?"

I am just starting climbing the Objective C learning curve (using Nerd Ranch iOS programming book).
Based on what I have know from other languages about "nesting" multiple executions within one line I assumed that I can alter:
NSString* descriptionString = [[NSString alloc] initWithFormat:#"%#", possesionName]
with a two line version:
NSString* descriptionString = [NSString alloc];
[descriptionString initWithFormat:#"%#", possesionName]
but it seems that the second attempt raises an exception
2012-01-22 18:25:09.753 RandomPossessions[4183:707] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -length only defined for abstract class. Define -[NSPlaceholderString length]!'
Could someone help me understand what exactly I am doing wrong here? Thanks a lot in advance.
PS. If this is a way Objective C messages work and you have to make alloc and init in one line just let me know - I assumed this is just a set of functions that either can be executed two in one go or one after another.
An important difference between both versions (they are not exactly equal) is that in the first version you use the result of initWithFormat for the variable descriptionString, while you use the result of alloc in the second. If you change your code to
NSString* descriptionString = [NSString alloc];
descriptionString = [descriptionString initWithFormat:#"%#", possesionName]
all should be well again. It is specified that an object returned by alloc shall not be seen as initialized and functional until some init Method has been called and init might return something else.
The alloc method will allocate memory for a new object. But the init method might throw away that memory and return a completely different object. Or it might return nil. This is why you must always do self = [super init] when you override an init method.
NSString is one class that does this kind of thing all the time.
I'm not exactly sure why the exception is happening, but I believe it could be ARC injecting code in between your two lines of code or something similar. Whatever it is, something is trying to act on the allocated object that has never been initialised, and this is a huge problem that can lead to all kinds of issues. Consider yourself lucky it threw an exception, sometimes it wont.
The NSString class might not actually be a real class. It may contain almost no methods and almost no variables. All it has is a bunch of factory methods to create "real" string objects of some other class, and this is done using methods like initWithFormat:. So, by long standing convention alloc/init must always be done in a single statement and there are a handful of places where, usually for performance reasons, something will rely on this convention being used.
Basically, objective-c is a language where you don't need to know exactly what is going on inside an object. You just need to know what messages can be sent to an object, and how it will respond. Anything else is undefined behaviour and even if you learn how it works, it is subject to change without notice. Sometimes the behaviour will change depending on circumstances that are completely illogical, for example you might expect the "copy" method to give you a copy of the object you send it to, and while this is the default behaviour, there are many cases where it will actually just return the same object with slightly different memory management flags. This is because the internal logic of the class knows that returning the same object is much faster and effectively identical to returning an actual copy.
My understanding is copy sent to NSString may return a new object, or it may return itself. It depends on which NSString subclass is actually being used, and there isn't even any documentation for what subclasses exist, let alone how they're implemented. All you need to know, is that copy will return a pointer to an object that is perfectly safe to treat as if it was a copy even though it might not be.
In a "proper" object oriented language like Objective-C, objects are "black boxes" which can intelligently change their internal behaviour at any time for any reason, but their external behaviour always remains the same.
With regard to avoiding nesting... The coding style for Objective-C often does require extensive nesting, or else you'll be writing 10 lines of code when only 1 is really needed. The square brace syntax is particularly suited to nesting without making your code messy.
As a rule of thumb, I turn on Xcode's "Page Guide at column" feature, and set it to 120 characters. If the line of code exceeds that width then I'll think about breaking it into multiple lines. But often it's cleaner to have a really long line than three short lines.
Be pragmatic about it. :)
From Apple's library reference, initWithFormat:
Returns an NSString object initialized by converting given data into Unicode characters using a given encoding.
So you can use these two lines of code:
NSString* descriptionString = [NSString alloc];
descriptionString = [descriptionString initWithFormat:#"%#", possesionName];
For more info please go to:
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/Reference/NSString.html#//apple_ref/occ/instm/NSString/initWithFormat:

What is preferable in objective-c: id or explicit type?

What is better and why ?
What is better in such situations as the class init method and usual variables in a code ?
What is better and why ?
Explicit typing information is always better unless you just can't use it for some reason (see below).
It allows the compiler to much more stringently validate the code and will catch many errors at compile time that would otherwise cause your app to crash at runtime.
A long, long, time ago, everything in the APIs used id. This proved to be a complete pain in the butt; fragile and led to many crashes that would have been caught with specific types.
So, it was changed. (This was ~1994).
What is better in such situations as
the class init method and usual
variables in a code ?
For init, you have no choice but to use the generic (id) return type. Objective-C does not support either co-variant or contra-variant declarations, nor is there a mechanism for generalizing the declaration of init while also providing support for specific type checking.
Same goes for retain, objectAtIndex:, addObject: and many other methods that take or return one of many kinds of objects (or take 'em as arguments).
And, no, there is absolutely no performance difference whatsoever between id and, say, NSView*.
can you give an example when explicit
typing will cause a problem please?
If you wrote:
- (MyClass *) init;
And in a subclass:
- (MySubclass *) init;
You'd get compiler warnings out the wazoo most likely or you'd have to typecast out the wazoo.
On recent versions of clang (in Lion) you should actually not return id, and instead return instancetype. This is a keyword that is used in return types to specify that the type it returns is an instance of the class receiving the message. It is now the preferred return type for init methods on OS X Lion.
Explicit typing provides build-time protection, informing you of likely problems if you do things such as casting or performing operations on something that probably won't work.
Explicit typing also helps prevent non-obvious transfer of mistyped objects, something traveling through a path in your code you hadn't considered that turns out to be of an unexpected type. This kind of bug often doesn't become clear until the program has been tested a lot, more commonly after its release.
It's also helpful for future programmers (including your future self) trying to work with your code, making to more likely that they'll be able to tell at glance what an object is supposed to be. It makes code more "self-documenting" as a result.
Some things cannot have a meaningful type because no type actually applies. Other times you need to use id because you need to be able to accept any type of object. Cocoa Touch uses it, for example, when referring to the sender of a message because anything could have sent it; specifying an explicit type simply wouldn't work.
The vast majority of the time, though, an explicit type is to your advantage.
Use a type as specific as you can but not more so. Consider how you are using any particular variable, argument, or return type and set its type appropriately.
For example a UITableView's dataSource property is declared as id<UITableViewDataSource> because the table view only cares that its data source is some object which conforms to the UITableViewDataSource protocol. This allows the data source to be flexible enough for use with any specific class which implements the protocol but still allows the compiler to warn you if you attempt to assign an object which does not implement that protocol as the data source.
If you are too specific then your code becomes inflexible, accepting only specific implementations which are not strictly necessary (ie demanding a NSMutableString when you could really work with any NSString).
If you are too vague (typing everything as id for example) then you lose the ability to identify when you are sending unrecognized selectors to a particular instance and the compiler cannot identify any number of invalid statements.
For init methods follow the advice in The Objective-C Programming Language
The return type of an initializer method should be id.
The reason for this is that id gives an indication that the class is purposefully not considered—that the class is unspecified and subject to change, depending on context of invocation. For example, NSString provides a method initWithFormat:. When sent to an instance of NSMutableString (a subclass of NSString), however, the message returns an instance of NSMutableString, not NSString. (See also, though, the singleton example given in “Combining Allocation and Initialization.”)
I don't think there is a performance difference between both.
You can let id return type for init because you can cast the result of your init.
For exemple :
Toto *foo = [[Toto alloc] init];
id foo2 = [[Toto alloc] init];
Both work but you'll have to cast foo2 variable like that (Toto *)foo in order to access property or methods of your instance without creating a compiler warning. Even if it works fine...
I think some developers let id because they just pass there variable trough instance and don't use it. That kind of use allow to not import the .h
Regards,
KL94

Why does a passed-by-value struct parameter get corrupted?

This isn’t the original code (I stripped things back in trying to simplify for debugging), but it does display the problem. On the face of it, looks simple enough:
- (void) testMethod: (TouchData) toi {
TouchData newToi = toi;
NSString *test = #"test string";
NSLog(#"string: %#", test);
// in ‘real’ code I pass the struct back
// It’s void here for the simplest possible
// case
}
TouchData is a struct, declared thus:
typedef struct {
Entity *owner;
CGPoint startPos;
CGPoint latestPos;
CGPoint startOfStraightSwipePos;
NSTimeInterval startTime;
NSTimeInterval latestTime;
NSTimeInterval startOfStraightSwipeTime;
CGFloat latestSpeed;
NSMutableArray *gestures;
BOOL isOfInterest;
} TouchData;
When I step through testMethod in the debugger (watching toi) on hitting NSLog (which doesn't even involve toi), all toi member values suddenly zero out. This doesn’t happen to the copy (newToi). It doesn’t happen if I pass the struct in by reference. It doesn’t happen if replace the testMethod invocation directly with the method body (ie. if I run these lines in situ rather than calling into a method). It doesn’t happen if I change the toi parameter type to a dummy struct with a couple of int members, created just before the call.
It might worth pointing out that testMethod is only called from within its own
class, and that the caller has just extracted the struct from an NSMutableDictionary (via unboxing an NSValue). But given that (a) the struct is
passed into the method here by value, and (b) that on entry its members as shown
by the debugger are all as expected, I don’t see that this can be causing a problem. There is also the thorny issue of the two object pointers in the struct, but in other contexts they’re working out OK, and they check out in the debugger on entry to the method, so I don’t think I’ve missed essential retains.
I presume I’m running into some kind of heap or stack corruption, but I’ve no idea how or why. I’m new to Objective-C, and have previously worked in
garbage collected environments, so my memory management experience is limited. It’s entirely possible that I’ve missed something painfully obvious.
I expect someone will tell me to make TouchData an object type instead, and indeed I may well go that way. I also have a couple of tested workarounds, ie. to either work on a copy, or pass the struct in by ref. But I’d really like to know what’s going on here.
If toi is not used after the line TouchData newToi=toi, the compiler can do whatever it wants to do in the stack memory where toi originally was placed after that line. For example, it might reuse the stack memory when calling another function, in this case NSLog.
So, watching toi by a debugger might show something strange. The compiler does often do these things, in particular if the optimization is turned on. Even with no optimization there's no guarantee that the stack location of toi is left intact after it's last used.
By the way, you said having object pointers inside toi didn't cause problems, but it's a tricky situation and I recommend strongly against that practice. Follow the standard retain/release rules; otherwise, another programmer who takes a look at your code (who might be yourself two years from now) would be totally confused. Also, the static analyzer (which can be accessed by doing Build & Analyze in XCode) might be confused and might give false positives. So, don't do that.