confused about Objective-C syntax [duplicate] - iphone

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Method Syntax in Objective-C
I just started learning Objective-C and I'm a little confused about this statement.
+(NSMutableArray *) array;
This is what I understand:
+ means this is a method that responds to a class (which makes this a static method)
NSMutableArray is an array that can have it's size change
* pointer ( memory location reference)
array is the name of the array that is of type NSMutableArray.
() Why does this method need parentheses around the object pointer '(NSMutableArray *)'
I don't know how to conceptualize what these part mean as a whole. Can you explain this to me?

in C syntax this would be written as:
static NSMutableArray *array();
NSMutableArray * is the return type. array is the name of the method. There are no arguments, but if there were it would be like this:
+ (ReturnType)methodName:(ArgType)argName;
or if there were multiple arguments:
+ (ReturnType)firstPartOfMethodName:(Arg1Type)arg1Name secondPartOfMethodName:(Arg2Type)arg2Name;
This can be a point of confusion for a lot of Obj-C newcomers. The fact that the method name is split between the arguments can be extremely confusing to most programmers coming from other languages.
The reason that it's ordered that way is to give clarity to the arguments. When using methods like:
- (id)initWithBitmapDataPlanes:(unsigned char **)planes
pixelsWide:(NSInteger)width
pixelsHigh:(NSInteger)height
bitsPerSample:(NSInteger)bps
samplesPerPixel:(NSInteger)spp
hasAlpha:(BOOL)alpha
isPlanar:(BOOL)isPlanar
colorSpaceName:(NSString *)colorSpaceName
bitmapFormat:(NSBitmapFormat)bitmapFormat
bytesPerRow:(NSInteger)rowBytes
bitsPerPixel:(NSInteger)pixelBits
(This is a real method from the Cocoa framework, known for being the longest), it's very helpful that you know which argument to place first, second, third, etc.

The 1,2,3 statements are correct. But fourth one is, array is the name of method. The fifth one is, the return type of array method is NSMutableArray *.
Finally array is the class method and it has NSMutableArray * return type and also does not any arguments.
It look like - (void)viewDidLoad. viewDidLoad is the instance method and it has void return type and also does not any arguments.

Related

iOS Obj-C: Variable object that can be assigned as a double or a string?

I'm pretty new to iOS development, and I want to figure out if there's a good way to handle this issue. Basically, I'm making a technical calculator that returns some product specifications based on user input parameters. The product in question has specs for some, but not all user parameters, so I . In a constants file, I have a bunch of ATTEN_SPEC_X variables which are const double or const NSString *. Now, it's perfectly okay to be missing a spec, so my plan was to leverage NSArray's ability to hold different types and use introspection later to handle strings vs doubles before I report the returned specs.
Here's an incomplete example of one method I'm implementing. It's just a big conditional tree that should return a two-element array of the final values of spec and nominal.
- (NSArray *)attenuatorSwitching:(double *)attenuator{
double spec, nominal;
{...}
else if (*attenuator==0){
spec=ATTEN_SPEC_3; //this atten spec is a string!
nominal=ATTEN_NOM_3;
}
{...}
return {array of spec, nominal} //not actual obj-c code
So instead of making spec and nominal doubles, can I make them some other general type? The really important thing here is that I don't want to use any special handling within this method; another coder should be able to go back to the constants file, change ATTEN_NOM_3 to a double, and not have to retool this method at all.
Thanks.
The problem you'll run into is that NSArrays can't directly handle doubles. However, you can get around this if you start using NSNumber instances instead - you can return an NSArray * containing an NSString * and an NSNumber * with no problems. If you need even more general typing, the Objective-C type id can be used for any object instance (though still not with primitives; you can't make a double an id).
Later, when you get an array, you can use the NSObject method -isKindOfClass: to determine the type of object you're pulling out of the array, and deal with the string or number depending on the resultant type. If you need to convert your NSNumber back to a double, just use the NSNumber instance method -doubleValue to unbox your double. (+[NSNumber numberWithDouble:] goes the other way, giving you an NSNumber out of a double.)
If you're using a recent enough version of Xcode, you can even make these things literals, rather than having to litter calls to +numberWithDouble: all over the place:
return #[ #3, #"number of things" ]

struggling with correct way to name this method

Long time c#/java/c++ programmer, brand spankin new to objectivce C. Read the guidelines, looked api's, but not quite there yet on the naming convention.
Example: assume I have a Cars class that has an array of every car, and you wanted methods to return a subset of the array.
I see NSArray has a method: getObjects, but in most cases I don't see the "get". So
what do you prefer?
All inputs appreciated! Spent way too much time thinking about this.
Option A) -(NSArray *) getCarsWithColor:(NSString *)color;
Option B) -(NSArray *) getCars:(NSString *)withColor;
Optoin C) -(NSArray *) carsWithColor:(NSString *)color;
OPtion D) -(NSArray *) cars:(NSString *)withColor;
Option E) none of the above, name it xxxxxxxxxxxx....
Thanks.
Objective-C methods are seldom named with get. The getObjects: method has get in it only because the result is placed in a buffer in an input argument.
-(void)getObjects:(id*)aBuffer;
^^^^ ^^^^^^^
whereas your method is not filling a buffer, but return an array. Option (A) and (B) are out.
Also, the kind of argument is usually part of the selector name (stuff before :), e.g.
-(UIView*)viewWithTag:(NSInteger)tag
^^^^^^^
// not view:(NSInteger)withTag
-(CGPoint)convertPoint:(CGPoint)point fromView:(UIView *)view
// not convert:(CGPoint)point from:(UIView*)view;
so option (D) is discouraged.
A detailed guideline for naming methods can be found in Coding Guidelines for Cocoa: Naming Methods. This guideline also include other conventions which you may be interested.
Option C is the best. Never use "get" unless you're getting pointers into a C array and the arguments should only be named for the method signature that refers to them.
This way, longer methods with multiple arguments are clearer:
-(NSArray *)carsWithColor:(NSColor *)color
wheels:(NSInteger)wheels
seats:(NSInteger)seats
premiumInterior:(BOOL)premiumInterior ...
...which can be shortened to: -carsWithColor:wheels:seats:premiumInterior:... when describing it to others.
"C" is the standard way to do it. get is very rarely used in getters and the more verbose carsWithColor is preferred.
In addition to what everyone else has said, I'd be curious why you're storing an NSArray of objects in the Cars class. It sounds to me like cars is an NS[Mutable]Array ivar somewhere containing instances of the car class. Then, you don't need this method at all. If you're using Core Data, then you'd do a fetch and if you're just handling the NSArray yourself, you could use a predicate to filter the array's objects. I think that is the bit that strikes me as the most un-Cocoa aspect of your question. If you do need this method, then it would be defined on the object containing the NSArray ivar like:
NSArray *cars = [NSArray arrayWithObjects:car1, car2, car3, nil];
(NSArray *)carsWithColor:(NSString *)color{
return [cars filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"color == %#", color]];
}
That code is untested, but it's how I would approach the problem. The method is really a controller type method and shouldn't be part of your model logic. Having the Cars class sounds like muddled MVC to me.
Objective-C method names do not use the get prefix. So option C is closest to being correct, with the caveat that the aWithB construction implies the NSArray * that comes back will be autorelease-d.
Oh, there are so many ways to do what you're trying to do! Usually, the "get..." notation should be avoided unless you're defining a custom getter, to avoid confusion. I vote for option C, "-(NSArray *) carsWithColor:(NSString *)color;".

What's the difference between void* and id? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
objective c difference between id and void *
For example, an UIView animation delegate callback method has this argument:
context:(void*)context
Why not simply id? I always pass nil if I don't care about an context. But when I want one, I pass the object. What's the difference? Why did they prefer void* over id?
id is a pointer to a struct which has isa pointer (which denotes to ObjectiveC runtime that this "thing" is object). void* is simply a pointer to possibly anything (probably another id).
It's to allow you to pass a pointer to anything you like. Can be an obj-c object, a pointer to some array, a struct, whatever. The void * type is just the most general, "anything goes" type.
If you're just passing nil, don't worry about it. You could pass NULL instead if it makes you feel better.
I think you're asking something more than what the difference between id and void* is. It seems you are asking why is it void* in this case.
This is void* because this is your pointer. No one but you will use this. This pointer will not be retained or otherwise used. When the animation calls your callback method it will return this pointer to you untouched. What you do with it depends on what you put in the context: in the first place.
Being a void* lets you do a lot of things. You could pass in a standard objective-c object. You could pass a simple C style data structure. You could pass in a function pointer. You could pass nil and do nothing.

Sorting an array with instances of a custom class

I have an array filled with instances of a custom class which contains two String properties, firstname and lastname. Both have a getter method which is equal to the name of the property itself. There is also a method for retrieving the Full name of a person called "getFullName". Consider the example below.
CustomClass *person = [[CustomClass alloc] ...];
person.firstname // Returns "Thomas"
person.lastname // Returns "Meier"
[person getFullName] // Returns "Thomas Meier"
Now I would like to sort this Array by Fullname in a descending Order. I have been looking at some array sorting methods but was not quite able to figure out how to go about this. I guess that I have to create some kind of comparison function which compares two elements, yet how do I tell the SDK which values to pass to this method and where should I place it (in the custom class or in the class where the sorting happens?). Maybe there is another/better way of going about this? Admittedly I have close to none experience with sorting arrays.
Thanks a lot for your help!
Ps. The code should run on iOS 3.2
There are a couple ways to do this. One is to put a comparison method on the custom class. Call it -compare: or something like that. That method should take another object of the same custom type as its input. It should return NSOrderedAscending, NSOrderedDescending, or NSOrderedSame, depending on the result of the comparison. (Inside this compare function is where you look at your own fullName versus the passed-in object's fullName.)
Then you can use NSMutableArray's -sortUsingSelector: method, like this:
[myArray sortUsingSelector:#selector(compare:)];
This works on all versions of iOS. There are block comparison methods available in 4.0+.

initializer not constant?

Quick question if I may: I am just curious about the following (see below) Xcode says "initializer element is not constant" why this does not work, I guess its the NSArray ...
static NSArray *stuffyNames = [NSArray arrayWithObjects:#"Ted",#"Dog",#"Snosa",nil];
and this does ...
static NSString *stuffyNames[3] = {#"Ted",#"Dog",#"Snosa"};
gary
Its because you are called a method (+ arrayWithObjects) that returns data - although the result is immutable, its actually dynamically generated data.
Static local variables are initialized at compile time so their initializer must also be known at compile time, which is obviously not true in you 1st example.
Static variables may be initialized in
their declarations; however, the
initializers must be constant
expressions, and initialization is
done only once at compile time when
memory is allocated for the static
variable.
and more on static variables.
Yes, it's the NSArray. Think about what happens at compile time.
In the second case it has all the information it needs. It has three NSString constants and a C-style array to put them in.
On your first line you have a call to a class method with four parameters, all of which happen to be constants. As far as the compiler is concerned, NSArray is no different from, say, UIApplication. It's a class with paramters. You and I know that it's an array but the implementation of that is in the Foundation library and not a core part of the language.