Must Objective-C messages have split up names to have different arguments? - objective-c

That's an example
- (NSArray *)shipsAtPoint:(CGPoint)bombLocation withDamage:(BOOL)damaged;
May we delete withDamage part here? What's the difference if that's available?

You actually can, and then you would call the method like this:
[obj shipsAtPoint:point :YES];
But it's considered bad style and virtually no one does this.

Related

Why do objective-c array parameters not use colon notation?

Im currently learning some objective-c from the big ranch guide book. My understanding is that methods with multiple parameters use colons to separate each parameter, but when reading about creating arrays, i found this snippet of code:
NSArray *dateList = [NSArray arrayWithObjects:now, tomorrow, yesterday, nil];
This has left me confused as i thought objective-c method parameters must each be preceded by a portion of the method name along with a colon. Can anybody explain this to me?
This is an exception to the rule; this is commonly called a variadic method. If you look at the definition in NSArray.h:
+ (instancetype)arrayWithObjects:(id)firstObj, ... NS_REQUIRES_NIL_TERMINATION;
you see that you can specify an arbitrary number of parameters, as long as the last one is nil (this is called the sentinel).
This saves the developers from creating a large number of different methods having roughly the same functionality, each of which accept a different number of parameters. They did so in NSObject, where you have
- (id)performSelector:(SEL)aSelector withObject:(id)object1;
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;
(but no further methods).
The method only has one parameter, a variable parameter list.
Here is the Objective-C declaration from the Apple Developer website:
+ (instancetype nonnull)arrayWithObjects:(ObjectType nonnull)firstObj, ...;
There's no need for colon separation, because the object list is treated as one parameter, even thought it looks like many parameters!

Method with multiple input parameters

I understand how to create my own methods that accept input parameters in objective-c but I have never actually created a method with more than one input parameter!
From methods I have used with multiple input parameters each has a name along the lines of
first:second:third:
and look like
- (void)first:(NSString *)fname second:(NSString *)mname third:(NSString *)lname;
my question is when creating your own method with multiple input parameters do you have to create a name like first:second:third or can you just have something like C++ where you have the one name followed by a list of input parameter types followed by the parameter names... if I remember correctly.
fullName:(NSString, NSString, NSString) fname, mname, lname;
No. A method must have the format as you described:
- (void)first:(NSString *)fname second:(NSString *)mname third:(NSString *)lname;
You have to have the parameters interleaved with the method signature. It's ok because xcode has code completion and it can give you nice descriptive names about what your method is doing and what it requires.
e.g.
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
In the example above without even looking at the API for UIViewController you can get a pretty good understanding of how this method works and what it's params are. It is good practice to name your methods well to describe what they do (it can remove the need for most commenting if done well).
You may well of course see a method written like this
- (void)myMethodThatAcceptsARectangle:(float)x :(float)y :(float)w :(float)h;
But this will not be very clear in use as to what the parameters relate to:
[self myMethodThatAcceptsARectangle:1.0f :1.0f :1.0f :1.0f];
So you should avoid this (I added it incase you ever see this and wonder what's happening).
fullName:(NSString, NSString, NSString) fname, mname, lname;
Yes, you can do something like that. It'd look like this instead:
-(void)fullName:(NSString*)fname :(NSString*)mname :(NSString*)lname
and you'd call it like this:
[foo fullName:first :middle :last];
That largely defeats the point of Objective-C's method names, though, and the main reason to do something like that is to register your dislike of the normal Objective-C convention, or perhaps to get yourself kicked off whatever project you're working on.
Another option could be variadic parameters. They're used to provide a variable amount of parameters, even though you wouldn't have a name on each one of them. e.g.
[NSString stringWithFormat:#"My name is %# %#", #"John", #"Doe"];
It would be something like this:
- (void)names:(NSString *)names, ...;
Implementation, additional info
Here's a simple example for Method with parameters.
- (void)methodName:(NSString *)parameterOne methodNameContinues:(NSString *)parameterTwo;
For Example,
-(void)showAlertMsg:(NSString *)message withTitle:(NSString *)title;
Here you can see, we've a prefix "withTitle" for the second parameter. We've to proceed the same for the other parameters too.
I can think of a perfectly good reason to use NSDictionary to pass arguments. I also believe it answers the question.
You can place all of the items in an NSDictionary then unpack them. This maybe useful if you have say a persitanceStore NSObject that you want to send a list of parameters to.

Sorting NSArray igonring Umlauts

I want to sort an array I have so that the Umlauts are treated as normal versions of the characters (ä == a, etc.). I thought localizedCaseInsensitiveCompare: should do the trick. But it doesn't. Anyone?
Best
–f
localizedCaseInsensitiveCompare: compares using the standard rules in the current language chosen by the user, ignoring the case. In your case you want to disregard the diacritics, not the case. This means you need to do something else.
You need to use compare:options: and pass NSDiacriticInsensitiveSearch as an option. see here.
To sort an array using it, you need to either use a block using sortedArrayUsingComparator:, or implement a category method in NSString and pass that selector to sortedArrayUsingSelector:. Don't forget to prefix the name of the category method so that it doesn't overlap with a private method in the framework. So, do something like
#interface NSString (myaddition)
-(NSComparisonResult)mySecretDiacriticsInsensitveCompare:(NSString*)string;
#end

Objective-C method signatures. Are they inconsistent?

I'm new to Objective-C, but please help me out here.
What I'm seeing is that method signatures in Objective-C that take multiple parameters seem inconsistent.
Example:
- (void) sendEmail: (NSString *) toStr
subject:(NSString *) subjectStr
body:(NSString *) bodyStr;
OK, so here we have 3 "parameters" (at least that's what I'm used to calling them), but 2 of them have "external" names (subject, body) but the first one doesn't! Isn't there something wrong with that from a consistency/style point of view?
When we call this method we do it like:
[emailObj sendEmail:#"test#test.com" subject:#"testSub" body:#"this is a test"]
(Hopefully I did that right, remember I'm new to this.)
So the subject and the body are clearly marked in the call, but not the "to" address? It seems really wacked to me. Why is that first parameter getting special treatment?
I guess you thought that in the method declaration
-(void) A:(NSObject*)a B:(NSObject*)b C:(NSObject*)c
A is the method name, B and C are the names of parameters.
In Objective-C, the totality A:B:C: is the method name (more technically, called the selector) and used as a unit when you call a method by name. For example,
if([obj respondsToSelector:#selector(A:B:C:)]){
...
}
checks if obj responds to A:B:C:. But [obj respondsToSelector:#selector(A:)] will be NO in this case.
So, you should really think of the totality of A:B:C: as the method name, and A is the name of the first parameter.
Note also that you can't call A:B:C: as A:C:B:, either.
In most cases, methods like this are normally named so that the lack of a name on the first parameter makes sense. In this case, I would expect something like sendEmailTo.
I would say that if you're confused about what a method does, then it's probably not named as well as it could've been.
Given the selector above, I would expect the 3 parameters to be some sort of email object, a subject, and a body. Since, however, the first parameter is not an "Email" object but rather the recipient of an email, I would probably rename this method to be:
- (void) sendEmailToRecipient:(NSString *)recipient subject:(NSString *)subject body:(NSString *)body;

Using sortUsingSelector on an NSMutableArray

I have used sortUsingSelector to sort an NSMutableArray of custom objects.
Now I'm trying to sort an NSMutableArray containing NSMutableArrays of custom objects.
Can you use sortUsingSelector on an NSMutableArray, or does it only work for custom classes?
If you can use blocks, the most straightforward way using sortUsingComparator:. Otherwise, you'll need to use sortUsingFunction:.
In either case, you are going to need to write a custom block or function that takes two arrays as arguments and returns a sort order based on their contents (I'm not sure what logic you are using to determine if array A or array B is "before" or "after" the other).
You'd do something like:
static NSInteger MySorterFunc(id leftArray, id rightArray, void *context) {
... return ascending/descending/same based on leftArray vs. rightArray ...
}
Then:
[myArrayOfArrays sortUsingFunction: MySorterFunc context: NULL];
It sends the selector to the objects, so you'll need to use one of the other sorters. Probably sortUsingFunction:context:.
Of course you can also use sortUsingSelector:, it really doesn’t matter whats the object in your array as long as it responds to the selector you want to use. But NSMutableArray and NSArray don’t have any comparison methods themselves, so you’d have to extend them using a category to implement your compare method.
So you probably want to use the other sorting methods pointed out in the other answers here. It’s not impossible to use sortUsingSelector: but it is rather inconvenient and most people (including me) would argue that it’s bad style to write a category for that.