Getting Use of Undeclared Identifier error with imported method - objective-c

I'm trying to use the userVisibleDateTimeStringForRFC3339DateTimeString method that Apple documents here.
So first I created a separate class called jhsDateFormatter and first modified it from
- (NSString *)userVisibleDateTimeStringForRFC3339DateTimeString:(NSString *)rfc3339DateTimeString;
to
- (NSMutableString *)userVisibleDateTimeStringForRFC3339DateTimeString:(NSMutableString *)rfc3339DateTimeString :(NSString *)rfc3339DateTimeFormatString;
so I could pass in a second parameter, which would be the desired date format string.
I then imported this new class into my view controller.m:
#import "jhsDateFormatter.h"
and called the method this way:
predicateMutableString = [userVisibleDateTimeStringForRFC3339DateTimeString:dateHolderMutableString :#"yyyy'-'MM'-'dd'"];
predicateMutableString is defined in the viewController.h and synthesized in the .m.
I got a build error: use of undeclared identifier 'userVisibleDateTimeSTringForRFC3339DateTimeString
So I commented out my modified version and used the original code and method signature in my class file:
- (NSString *)userVisibleDateTimeStringForRFC3339DateTimeString:(NSString *)rfc3339DateTimeString;
and called it this way:
I'm not sure why the method call isn't being accepted. I think I've matched up the data types.
Please let me know your ideas of what is awry.
Thanks

You probably want to declare your method like this:
+ (NSMutableString *)userVisibleDateTimeStringForRFC3339DateTimeString:(NSMutableString *)rfc3339DateTimeString formatString:(NSString *)rfc3339DateTimeFormatString;
(Note the + at the start, and the fact that the second argument is now named - it was blank in your code, which is valid but weird.)
Then you'd call it like this:
predicateMutableString = [jhsDateFormatter userVisibleDateTimeStringForRFC3339DateTimeString:dateHolderMutableString formatString:#"yyyy'-'MM'-'dd'"];
Where jhsDateFormatter the new class you've made.
In your example code, you're not calling the method on any object, which is why the compiler is complaining.

Related

how do i write the name of a method with multiple parameters in the .h file

I am new to iOS. I have defined the following method in a .m file and need to add its name to the .h file.
-(Boolean) addBookFromArrayOne:(Book*)bookOne bookTwo:(Book*)bookTwo mergeByThisField:(NSString*)field sortDescending:(Boolean)
This post Method Syntax in Objective C was very helpful in learning the Objective C method syntax. The answer
in Objective-C, the name of a method is composed of all of the
portions of the declaration that are not arguments and types. This
method's name would therefore be: pickerView:numberOfRowsInComponent:
was particularly helpful.
But it does not show how to generalize to multiple parameters.
I took a guess at the syntax in the header file but am clearly getting it wrong:
#property Boolean addBookFromArrayOne:bookTwo:mergeByThisField:sortDescending;
Can somebody show me how to define this method name in the header file?
Just copy method declaration from implemetation to header
-(Boolean) addBookFromArrayOne:(Book*)bookOne bookTwo:(Book*)bookTwo mergeByThisField:(NSString*)field sortDescending:(Boolean)desc;
Don't use a property to declare a method; to declare a method in your header file just write:
-(Boolean) addBookFromArrayOne:(Book*)bookOne bookTwo:(Book*)bookTwo mergeByThisField:(NSString*)field sortDescending:(Boolean)descending;

Empty method name, what does this actually do?

I'm currently learning myself objective-c and iOS programming and found myself stuck with non-working code due to this subtle error for an hour.
Consider the following code:
#property (strong, nonatomic) NSString *name;
- (NSString *):name { return #"Some name"; }
At first glance (and for anyone new) this looks like an overridden getter for the name property. But theres a very subtle : that shouldn't be there. You get no warning/error from the compiler/parser/runtime here, so my question is what does this actually end up as?
I tried to figure a way of calling this method once I saw the error, but didn't succeed in my few attempts.
The method signature - (NSString *):name breaks down to the following:
- It is an instance method (versus a class method with a +).
(NSString *) It returns a string.
: If you were to speak the name of this method, it would simply be called "colon". : tells the compiler that your method accepts one parameter as well.
name There is a parameter called name.
When you don't specify a type, the compiler assumes you meant id, so this method actually fleshes out to be - (NSString *):(id)hello
A valid call to this method would be: [self :#"hello"].
You can do really weird things because : is a valid name for a method, and the compiler assumes id. You could, if you really wanted to, have a method called - :::. The compiler would assume you meant - (id):(id):(id):(id), a method that returns an object of type id and takes three parameters of type id. You'd call it like so: [self :#"hello" :anObject :myObject];
A method declare like the one you posted is rare (and poor style, imo). Objective-C is supposed to be verbose. Methods break down like this:
First character: Either - or +. - means it is an instance method, + means it is a class method.
Value in parentheses: The return type of the method. In your example, the method returns an (NSString *).
The rest (before the curly braces) is the method name along with any parameters they take. You could have a name with no parameters, in which case the method name would not have a : in it. Such as - (void) reload; This would be a method that doesn't return a value and takes no parameters.
If your method takes parameters, they will be mixed into the method name and usually will declare the type (unlike your example). Such as - (NSString *) reverseString:(NSString *) stringToReverse; In this example your method name would be reverseString: it takes one parameter, an NSString* that will be called stringToReverse in the method definition.
Usually, if you see a : with no type it will be a case like - (float) addThreeValues::: This method returns a float and takes 3 parameters. This would be an appropriate definition because the three values don't matter what order they are provided because we are just adding them.

Newbie question -multiple parameters

I am trying to implement a private method which takes an NSMutableDictionary and a Player object as its parameters. As it is a private method, the only place that it exists is in the ".m" file.
It is declared as
-(void) incrementScore: (NSMutableDictionary*) scoreboard forPlayer: ( Player* ) player {
and I call it as follows :
[ self incrementScore:deuceScore forPlayer:p];
However,it won't compile - I get
may not response to message -incrementScore:forplayer
I'm not sure where my error lies - do I need to declare the method in the ".h" file, or elsewhere in the ".m" file, or have I just got the syntax completely wrong?
The compiler needs to find a declaration for your method somewhere before you use it. This be done in three way:
Declare the method in the (public) #interface for the class in its .h file .
Declare the method in a class extension (a semi-private #interface, usually at the top of the .m files).
Define the method somewhere in the #implementation before your first use of it.
This is only a warning not a compile error... (if you changed preferences to treat all warnings like error it'll be a compile error).
Probably the line calling the method is above (in the .m file) the declaration method. Move the method just below #implementation directive, or above the method with the calling line. The warning/error should disapper.

"warning: '<CLASS>'may not respond to '<[-|+]FUNCTION>'" Objective C/Xcode Compiler Warnings

I figured this one out, yet thought it worthy of its own question answer pair.
I'm new to Xcode and Objective C, and getting to know its varied eccentricities. For instance, the compiler warning "warning: ''may not respond to '<[-|+]FUNCTION>'" appears when I try to compile the following code, which all appears in my implementation file since I desire to create a private static utility function for this class:
// Here's the function declaration in the implementation file (I don't want it in the header)
+(void)authenticationRedirectTo:(NSURL *)url WithRelayState:(NSString *)relayState AndSAMLResponse:(NSString *)samlResponse {
...
}
...
// Later on, here's a call to that same function:
[CnaCalendarController authenticationredirectTo:formActionURL WithRelayState:relayState AndSAMLResponse:SAMLResponse];
...
When compiled, this produces the warning above. Next, I'll post my resolution. Feel free to contribute your ideas as well!
If what you really want is a private method, that is, you don't want the method to be in the header file, then I like to use a Category to accomplish this. I just define the category above my implementation.
// Enforce private methods by putting them in a category.
#interface YourClass (PrivateMethods)
+(void)authenticationRedirectTo:(NSURL *)url WithRelayState:(NSString *)relayState AndSAMLResponse:(NSString *)samlResponse;
#end
#implementation YourClass
+(void)authenticationRedirectTo:(NSURL *)url WithRelayState:(NSString *)relayState AndSAMLResponse:(NSString *)samlResponse {
...
}
#end
Now, it doesn't matter what the order of your methods in your implementation is which is nice so you can properly "#pragma mark"
The problem is with your method call:
[CnaCalendarController authenticationredirectTo:formActionURL WithRelayState:relayState AndSAMLResponse:SAMLResponse];
Note that the first 'r' in "authenticationredirectTo:..." is lower case, but you've declared it as "authenticationRedirectTo:...", with a capital 'R'. Given that, it's no surprise that the compiler complains that it can't find a declaration for the method you're calling. The code will likely crash on that line, too, since the method with the lower-case 'r' isn't defined.
What i think the problem is, you are declaring the function after the call to this function. And while compiling it just could not find it.
OK, here's my solution as promised:
Problem 1: Xcode will generate erroneous warnings when a function declaration or implementation appears after the call in processed source code. In my case, they are in the same file so I was able to move to function implementation above the call.
Also check the order of your imports to ensure such a function is imported before an import that calls it. I didn't see this but saw other posts where this was the case.
Problem 2: It seems Xcode has some limitations on the LENGTH of function names. Shortening my function name as shown in the snip below resolved the issue. I'll obviously pick something more meaningful.
// Here is the warning function commented out and a *shorter* name in place.
//+(void)authenticationRedirectTo:(NSURL *)url WithRelayState:(NSString *)relayState AndSAMLResponse:(NSString *)samlResponse {
+(void)X:(NSURL *)url Y:(NSString *)relayState Z:(NSString *)samlResponse {
Hope this helps you with your troubles. Don't forget to vote this answer if it is useful.

Elementary Obj-C Question bout Methods

take example:
-(void)setName:(NSString *)name age:(int)age;
How would you call this method (in other words, the method's name is setName but what is the "age" parameter doing in there) and what do the types in parentheses mean? Is it just a way to tell the compiler what types are being returned?
[ myObject setName: #"Adam" age:18 ];
The age parameter is the second parameter in the method signature.
The types in parentheses are the expected types for the argument. e.g. name is expecting only an NSString and age is expecting only an int.
The - means that the method is an instance method, not a class method, which is denoted using a + instead.
The type in parentheses right after the - is the return type.
This is a great site for learning the basics of Objective-C: CocoaDevCentral
To answer, one would need a bit more information, but I'll be guessing this is from some sort of class named aClass, and you have an instance of aClass, named instance.
-(void)setName:(NSString *)name age:(int)age;
means you have a method, named setName:age:, that needs two arguments, one NSString, one int, and it returns a void. As it has a - as it's first character, it is an instance method.
[instance setName:#"James Hargrove" age:21];
Would call setName:age: on the instance.
(The instance should be created using, say,
aClass *instance = [[aClass alloc] init];
which would create an instance of aClass named instance, and initialize it.
This is the standard Objective-C method syntax. This could be read as:
A method with no return value (void) that
sets the name of the object (an NSString * parameter)
and the age (and integer
parameter).
Dissecting the method:
"-" The hyphen states that this is an instance method.
(void) The return type is void - or
no return type expected
setName:(NSString *) The first
parameter to be passed is the "name"
and is an NSString *.
age:(int)age The second parameter
to be passed is the "age" and is
an int.
In reality, the method syntax is actually quite self-documenting once understood (and quite foreign if you're used to more tradition C/C++ or Java syntax).
The actual example of the call of this method would be:
[someObject setName:#"Rich" age:101];
The method name is actually this:
setName:age:
You call it like this:
[someObject setName:#"Alice" age:20];
setName:age: is also the unique signature of that method, and with that signature you can call that method on any object you wish. For example:
NSArray* objects = ...
SEL mySelector = #selector(setName:age:);
for (id object in objects)
{
if ([object respondsToSelector:mySelector])
{
[object setName:#"Alice" age:20];
}
}
what do the types in parentheses mean? Is it just a way to tell the compiler what types are being returned?
Yes, those are "C casts". If everything was an object you wouldn't need those, but because you can pass and return plain old C types to and from your methods, the compiler needs to know the types of your parameters and return values.
You'd call this method like so:
[classInstance setName:#"name" age:123];
The first instance of "age:" indicates that the method receives another parameter, called "age" when used in the implementation of the method.
The types in parentheses indicate the types of data that are expected for each parameter, with the exception of the first one, "void", which means that this method returns nothing.
So, you would call this method as follows.
Say it is a method of an object named foo (of class Foo). Then you would call:
[foo setName:someName age:someAge].
If it were a static method, it would be preceded by a + instead of a minus as follows:
+(void)setName:(NSString *)name age:(int)age;
Then you would call
[Foo setName:someName age:someAge] //use the classname instead of the object name
The types are indeed there for type-checking by the compiler. You'll get warnings if you pass the wrong sort of data, and you will get warnings if your header doesn't match your implementation.
You can actually write Obj-C functions in a couple of different styles though, omitting some of this stuff. You can even write straight up C-style.