Different way on initialising NSArray - ios

I am used to the simple way of initialising NSArray.
NSArray *temp = [[NSArray alloc] initWithObjects:#"data1",#"data2",#"data3",nil];
I have now come across code in a non arc app where initialisation is done at many place like
NSArray *temp;
temp = [#[#"data1",#"data2",#"data3"] retain];
Can anyone elaborate the difference between two and if one is better than other.
Thank you

The second is using the new(ish) Objective-C Literal syntax.
This literal syntax allows simplified creation of NSNumber, NSArray and NSDictionary objects as well as providing subscripting support for arrays and dictionaries.

The second one is just a shortcut for:
+ (instancetype)arrayWithObjects:(id)firstObj,...
This
#[#"data1",#"data2",#"data3"];
will be compiled like:
[NSArray arrayWithObjects:#"data1",#"data2",#"data3",nil];
You can't say one is better than the other, they are made for different purposes. The shortcut syntax was invented to create arrays with content faster. You can see the shortcut is less code then the full arrayWithObjects example.
There are other shortcuts as well:
#{key: object}
to create a NSDictionary.
#YES #NO #value /* like #35 */ #(x + y)
to create a NSNumber

The first statement instantiates an NSArray object. In practice, you rarely see this code because NSArray objects are immutable and it's useless to have an array object with no elements that you can't change. It's more common to have
NSMutableArray *temp = [[NSMutableArray alloc] init];
or something similar and then add objects to the array later.
The second case declares a new variable of type NSArray and assigns it to an array of three NSStrings and then retains this NSArray object. This new array is immutable, like before, so it can't be changed. By sending the retain message, the retain count of that object will be incremented and the object will not be deallocated until it is sent a release. Without the retain, the object is owned by something else, probably an autorelease pool, in which case it will be deallocated when the method returns.

Related

Assigning autoreleased object to a strong object

Lets say I have a class A with a member variable "myDictionary".
Now if I do this:
myDictionary = [NSDictionary dictionary];
I know that by default members of a class are of strong type. So myDictionary will be available during the lifetime of class A object. Thats what my understanding is about ARC.
But I am getting an EXE_BAC_ACCESS on myDictionary which really confuses me. Do I need to do anything extra in order to avoid EXE_BAD_EXCESS on myDictionary? Because above method returns an autoreleased object.
Thanks in Advance.
If you're not using ARC, then you should use +dictionary any time you
need an autoreleased dictionary, and +alloc/init any time you need a
dictionary that you're going to hold on to (e.g. by placing it in an
ivar), or alternatively if you simply want to avoid autorelease and
-release it manually.
So try to implement like this:
myDictionary = [[NSDictionary alloc] init];
The most likely error here is accessing myDictionary from multiple threads. Ensuring that you always access ivar correctly is one of the several reasons you should always refer to your properties as self.myDictionary rather than directly referring to the _myDictionary ivar. When you need to make this thread-safe, that will ensure there is only one place you need to fix the code.
There are other possible ways to get this error, such as incorrect handling of CFBridging... functions, but the most common is multi-threaded access.

setString on nil object with categories

It looks to me like sending setString: to a NSMutableString that hasn't had init called on it yet does not call init on it's own. For example:
NSMutableString *string; // Declare, but do not init yet
[string setString:#"foo"];
NSLog (#"%#",string); // Prints "(null)"
I'd like to overwrite this behavior, so that essentially
- (void) setString:(NSString *)aString
{
if (!self)
{
self = [self initWithString:aString];
}
else
{
[super setString:aString];
}
}
I could do so with a subclass, but I would have to go through my project and replace all my NSMutableStrings with my subclass, which is a pain. I was looking at the Apple Docs and it looks like what I want to do is create a Category for NSMutableString. I haven't used categories before, so I got a couple questions:
First, it looks like categories only allow me to add new methods, it doesn't allow me to overwrite existing methods. I suppose it is easy enough to just create a setStringWithInit: method that does what I want, so this first issue isn't really an issue after all (although I still have to do a find-replace through my project for setString, but oh well).
Second, and more importantly, how do I check if the sender of my new method is nil? If setString: returned something other than void, I think I could get it to work, but that's not the case here. How do I get the if (!self) check from my code above to work with a category?
Or are categories not the way to go for this kind of thing, and I'd just be better off sub-classing after all?
EDIT:
So the strings I'm using this on will actually be #propertys of a custom NSObject subclass. In my code, I'll actually be calling [myObject.someProperty setString:#"foo"];, and the debugger is showing me that someProperty is nil when I try to do this. Also, in other parts of my app I'm checking if (!myObject.someProperty) to see if that property has been used yet, so I don't want to just automatically self.someProperty = [[NSMutableString alloc] init]; in the init method of myObject's class.
Although now that I think about it, I think I can get away with replacing if (!myObject.someProperty) with if ([myObject.someProperty length] == 0), which would allow me to go through and alloc-init things right away. But if I'm initializing everything right away, that will create some memory space for it, correct? It's probably negligible though. Hm, perhaps this is what I should be doing instead.
The proper code would simply be:
NSMutableString *string = [NSMutableString string];
[string setString:#"foo"];
NSLog (#"%#",string);
Why would you not initialize the variable? There is no need to override setString: or any other method. Don't try to treat NSMutableString any differently than any other class.
Besides, overriding setString: still won't solve anything. As long as the pointer is nil you can't call a method on it.
You are marching down a path to madness. Abandon hope, all ye who enter here!
Do not try to change the language semantics so that sending a message to a nil object somehow magically creates an instance of the object. That is not how the language works.
What you are trying to do is likely impossible, and if you were able to succeed, you would create programs that are fundamentally incompatible with standard Objective-C. You might as well found a new language, Objective-D
It is legal to send a message to a nil object in Objective C. The result is that the message gets silently dropped, and nothing happens. In many other object-oriented other languages, sending a message to a nil object/zero pointer causes a crash.
The semantics of of Objective C object creation are:
First allocate memory for the object using the class method alloc:
NSMutableString* aString = [NSMutableString alloc];
Then send the newly created object an init method to set it to its initial state:
aString = [aString init];
These 2 steps are just about always combined into a single line:
NSMutableString* aString = [[NSMutableString alloc] init];
Classes sometimes include shortcut "convenience" methods that do the 2 step alloc/init for you, and return an object in one call, e.g.:
NSMutableString *aString = [NSMutableString stringWithCapacity: 50];
Do not try to fight this convention. Learn to follow it. If you cannot tolerate this convention, program in a different language. Really.
You can reimplement a method without subclassing by using method swizzling. Here's a tutorial. There are 2 reasons not to do it here though.
it would be against the good Objective-C practices, since your
setter will also be an init method. Not good.
As #rmaddy correctly points out, calling setString: on a nil object will do
nothing. Even if you do override the method.
So I recommend creating a category on NSMutableString, and implementing [NSMutableString initWithString:] there. It is a much cleaner solution.
You cannot really do that - you have a method which can be called only on instance of this object, so you will have to create it first anyways to use it.
In your code it will be "nil" anyways - it won't create itself.
Why are you doing it instead of just:
NSMutableString *string = #foo";
I cannot imagine a reason to avoid allocating an object
macros FTW!
#define setString(X,Y) if(!X){X=[[NSMutableString alloc] initWithString:Y];}else{[X setString:Y];}
When I try to assign a value with this:
It will always be initialized first
It won't be initialized until I try to give it a value
It doesn't clutter up my code
It still gives a warning if X isn't an NSMutableString, or if Y isn't an NSString or NSMutableString
I haven't tested for if Y is nil, but I expect it will cause a crash, which is what I want.
Drawbacks:
I still have to remember to always use my setString() instead of the stock setString:
I'll have to do something similar for any other setters I call (the only one that I'm worried about off hand is setValue:forKey:, which I use extensively - one step at a time I guess) - a one size fits all solution would have been nice - maybe a topic for another question.
Whatever I pass in has to be a NSString before I pass it, I cannot convert it to a string in line - but at least I get a build error if I try to do so, so it isn't up to me to remember to do so (still adds clutter though)
NSMutableString *X;
int y = 0;
setString(X, [NSString stringWithFormat:#"%d",y]) // <--- Doesn't work
NSString *Y = [NSStirng stringWithFormat:#"%d",y];
setString(X,Y) // <--- Does work

Accessing obj as property vs method param (style preferences)

When it comes to accessing objects from different methods in the same class, from what I understand, these are two ways to do it. Given that I DO want to hold a property pointer to this object, which is the better way to go about this? I've been thinking about this for a while, and wondered if there is a preference consensus.
#1:
NSArray *array = ... // Get array from somewhere
self.myArray = array;
[self doSomethingToMyArray];
This method takes no parameter and accesses the array via its own property via self
- (void)doSomethingToMyArray
{
// Do stuff with/to the array via self.myArray
[self.myArray ...];
}
Vs #2:
NSArray *array = ... // Get array from somewhere
self.myArray = array;
[self doSomething:array];
This method takes an array and accesses the array via its own method parameter
- (void)doSomething:(NSArray *)array
{
// Do stuff with/to the array via method parameter "array"
[array ...];
}
I think it's primarily going to depend on what doSomethingToMyArray does and who calls it.
Fairly obvious comments:
if you want to do that to more than one array, you need to take an argument;
if what you're doing is actually logically more to do with the array than with your class (e.g. you've implemented randomisation of the order of the array) then it'd be better as a category on NSArray rather than being anywhere in that class at all;
if there's any possibility of subclasses wanting to redefine the manner in which the array is obtained then you'll want to invoke the getter somewhere;
similar concerns apply if a subclass or an external actor should be able to intercede anywhere else in the process.
Beyond those concerns there are a bunch of us that just prefer this stuff to be functional anyway — noting that you're doing something to the array, not with the array, in which case you'd tend more towards self.myArray = [self processedFormOf:array] (or self.myArray = [array arrayByDoingSomething]; if the category tip makes sense).
So, ummm, I don't think there's a clear-cut answer.
That depends on what you want to do, just by reading it:
doSomething:array
I would assume the above method takes ANY array and performs an action, whereas:
doSomethingToMyArray
with this method you are describing the intention of doing something to your instance's array. Inside this method (given that you followed Apple good coding practices and you synthesized your property to _myArray) , you could either go with:
[self.myArray message]
or preferably
[_myArray message]
Your second option is sort of silly. If you're storing a pointer in an instance, then it's so that you can use it later (within that instance) without needing to pass it around whenever you call a method.
This is also dependent on whether you're using ARC or not (use ARC if this is a new project). In a non-ARC project, self.myArray = foo; will do a very different thing than myArray = foo; (the self. syntax calls a property, which in many cases will correctly retain the thing you've assigned). In an ARC project, they'll generally have the same behavior, and there's less room for error.
Personally, in my ARC projects, I do not use the self. syntax from within a class, since it's just extra typing for the same effect. This ties in nicely with the new usage of #property, where you're no longer required to write a #synthesize block, and Objective-C will automatically generate an ivar for you, with the name of your property prefixed by an underscore, i.e. _myPropertyName. That makes it very clear visually when you're accessing code from outside the class (crossing the encapsulation boundary), where things will look like foo.bar = baz; versus inside the class, where it's just _bar = baz;.
IMHO, clearly, a function call would incur an extra overhead.
you would have to allocate an object pointer (though minimal) over the stack (extra memory)
Have to pass it (extra processing)
Property is actually a small function call unless you have made customizations to the getter. I also assume that compiler may have its own optimizations put in place for such accessors so that you can access them with minimal overhead, though I do not have any source to cite this.

Are all objects in objective-c basically pointers?

I know there are differences between C/C++ and Objective-C, but what is the case when it comes to the pointer-mark *? Is this not used for pointers in Objective-C, or are all objects pointers in this language?
I.E, if I try NSString string = #"Hello";, XCode tells me to use NSString *string instead. Does this still mean it is a pointer?
Let's say I have this standard method(as in, this is the way most methods look):
-(void)method:(NSString*)s;
then I would send something like this:
NSString *string = #"Hello";
[self method:string];
Would I save data time or allocation or access or whatever by doing everything like this:
-(void)method:(NSString**)s;
//and use it like this:
NSString *string = #"Hello";
[self method:&string];
Or is it a waste? If they are already pointers, I would guess they would be pointing to pointers this way.
?
Objects themselves aren't pointers, they're areas of memory with data in them. The variables you're talking about are pointers to those objects:
NSString *string = #"Hello";
Here, 'string' is a pointer to anNSString literal object. When passing this as a variable you're passing a reference to the object. The contents of the object (if it's a mutable object, which NSString isn't) can be edited, but the reference can't.
By using NSString ** you're adding an extra level of indirection. Now you're passing a pointer to a pointer. The only reason you want to do that is when you want to allow the object (if there is one) to be edited as well as the reference to the object. For example, when calling a method that optionally returns an error:
NSError *error = nil;
[someone doStuff:(NSString *)string error:(NSError **)error];
Now someone can instantiate an NSError and return it to you.
You should not use pointers to pointers unless this is your intention.

Passing multiple parameters into function using array

I have to maintain a code of somebody. The code opens a thread. The thread worker function in iOS (and any other language I know of) accepts only one parameter. In order to overcome this, the code creates an array, adds all the parameters into an array and passes it into the thread. Here is the code.
NSArray* params = [[NSArray alloc] initWithObjects: mainView, actionFlag, nil];
[self performSelectorOnMainThread:#selector(updateWorker:) withObject:params waitUntilDone:NO];
And the function is called this way
-(void)updateWorker:(NSArray*)params
{
UIView* view = [params objectAtIndex:0];
bool actionFlag = ((NSNumber*)[params objectAtIndex:1]).boolValue;
/* do stuff with view and actionFlag */
}
I have a gut feeling that this is very wrong at so many levels but cannot built a valid argument for this case.
What are the drawbacks of passing number of arguments as an array?
Actually what you are doing is technically correct (but I do understand why it feels wrong).
If you want to feel better, what I would do in this case is instantiate (create) a "NSDictionary" object and then set the objects / values to useful keys and in your "updateWorker" method, fetch the objects via "objectForKey:".
Doing it this way will be easier for you (or somebody else) to maintain in the future, as you won't have to poke around to see what goes in array position 1, array position 2, etc.
Most of them are future updates,
Some cases (not so rare) may happen:
Addition of new parameters to the array
changing the order of elements in the array
removing elements in the array
problems when releasing and retaining elements in the array (not ARC)
One point to note here, is that all of these cases will be hard to debug, since you will be moving from one thread to the other

Resources