Why doesn’t my enum work as a method parameter? - objective-c

I've used typedef enum in the past with method parameters and had no problem, but today I'm having problems...
h file
typedef enum
{ eGetVarious1,
eGetVarious2,
} eGetVarious;
- (double)getVarious:(eGetVarious)eVar:(NSDate*)pDate;
an m file

you're calling a class method, and declaring an instance method:
instance method:
- (double)getVarious:(eGetVarious)eVar:(NSDate*)pDate;
class method (may not use ivars or instance methods):
+ (double)getVarious:(eGetVarious)eVar:(NSDate*)pDate;
say you want this as an instance method, declare it like this:
- (double)getVarious:(eGetVarious)eVar forDate:(NSDate*)pDate;
and if you were in the scope of implementation of an instance method, then this should work:
double result = [self getVarious:eGetVarious1 forDate:[NSDate date]];
note the reason compiler is reporting an error:
if it has not seen a particular objc selector and you use it, it assumes the undeclared selector's arguments take id (anonymous objc object).
also, enum type should not be promoted to a pointer (although 0 is ok). since the compiler saw no way to match what you're calling: [objc_class* getVarious:eGetVarious<enum_type> :NSDate*] it is right, because you should be calling it as:
General * anInstanceOfGeneral = /* something here */;
NSDate * date = /* something here */;
double result = [anInstanceOfGeneral getVarious:eGetVarious1 forDate:date];

Related

Too few arguments to function call, expected at least 2, have 0

I wrote the following code:
#interface TestClass : NSObject
//
-(void)testLog;
//
+(void)testLog;
#end
//===============================
SEL sel = #selector(testLog);
IMP imp = class_getMethodImplementation([TestClass class], sel);
imp();
//===============================
SEL testSel = #selector(testLog);
IMP testImp = class_getMethodImplementation(objc_getMetaClass(class_getName([TestClass class])), testSel);
testImp();
I set the Enable Strict Checking of objc_msgSend Calls to NO but still have this error。
Why is it wrong?
All Methods take a minimum of two arguments: a reference to the object (or class in the case of a class method) the method is being called on, this is the value of self within the method body; and the selector of the method. This is what is missing in your calls.
You can see this in definition of IMP given in the documentation is:
id (*IMP)(id, SEL, ...)
With the explanation:
This data type is a pointer to the start of the function that implements the method. This function uses standard C calling conventions as implemented for the current CPU architecture. The first argument is a pointer to self (that is, the memory for the particular instance of this class, or, for a class method, a pointer to the metaclass). The second argument is the method selector. The method arguments follow.
HTH

id pointer in Objective-C

I am new to Objective-C. I am coming from a Java background. I am trying to create a generic function in objective-c as follows:
- (id<BaseEntity>*)retreive:(NSString *)idValue unpackedWith:(id<ITransferObject>*) transferObject{
NSString * url = [[[self baseUurl] stringByAppendingString: [self getPath]]stringByAppendingString: #"/retreive/"];
url = [url stringByAppendingString:idValue];
NSMutableURLRequest *request = [self createGET:url];
NSString *responseString = [self processRequest:request];
BaseEntity* responseEntity = [transferObject unpack:responseString];
return responseEntity;
}
What I am trying to accomplish is create a function that can take a pointer to any object that implements the ITransferObject protocol. Use a function on this object as defined in the ITransferObject protocol. Then return a pointer to an object that implements the BaseEntity protocol. I feel like I took a Java generics approach to this and it is not working.
I get the following error:
Bad receiver type `__autoreleasing id<ITransferObject> *'
from this line:
BaseEntity* responseEntity = [transferObject unpack:responseString];
And I get the error:
Implicit conversion of an Objective-C pointer to `__autoreleasing id<BaseEntity> *' is disallowed with ARC
from this line:
return responseEntity;
Any ideas?
id is a pointer type in itself—you don’t need to append a * to it to represent a pointer as you do with a class.
- (id<BaseEntity>)retrieve:(NSString *)idValue unpackedWith:(id<ITransferObject>)transferObject
id is a special type - it is a by-reference type that does not require an asterisk: it is already a pointer. Here is an example that illustrates this point:
-(void)someMethod:(id)data; // id does not need an asterisk
...
NSString *str = #"Hello"; // NSString needs an asterisk
[self someMethod:str]; // This works
Adding an asterisk after an id makes the type a pointer to an id - i.e. a double pointer. There are legitimate situations when you need a pointer to an id, but it is not what you need in your situation.
You have two ways of fixing this issue:
You can change id for NSObject (similar to passing Object in Java), or
Remove the asterisk after the id.
The second approach is more common:
- (id<BaseEntity>)retreive:(NSString *)idValue unpackedWith:(id<ITransferObject>) transferObject;
First of all, it looks like BaseEntity is a class, not a protocol, so you can't use it as a protocol.
Second, the id type is inherently a pointer, so you normally don't want to declare a pointer-to-id.
Declare your method like this instead:
- (BaseEntity *)retreive:(NSString *)idValue unpackedWith:(id<ITransferObject>) transferObject{
(Note that I have changed the transferObject type by removing the *.)
Alternatively, use NSObject instead of id and leave the star, this:
- (BaseEntity*)retreive:(NSString *)idValue unpackedWith:(NSObject<ITransferObject>*) transferObject{
Also, the correct spelling is retrieve.

Changing a default returned id to an NSTimeInterval

I have a bit of code that calls a method on an object whose .h file I don't have contained in my project, and cannot have contained (I don't want to get into this).
However, I know that I need to call a specific function that it does have, which returns an NSTimeInterval.
Obviously, the compiler warns me that the method is not defined and might crash. The problem is that the compiler defaults the return value of unknown functions to id, and i cannot cast an id to an non-pointer value. At runtime, however, the value of id is the value I need the NSTimeInterval to contain.
id tempValue = [myObject unknownNumberMethod]; // compiler says: "instance method -unknownNumberMethod not found(return type defaults to 'id'
NSTimeInterval realValue = (NSTimeInterval)tempValue; //this yields a compilation error:/Users/Niv/Projects/Copia/Copia.MAC/RMSDKServicer/RMSDKServicer/Downloader/ActivatorService.m:75:24: Initializing 'NSTimeInterval' (aka 'double') with an expression of incompatible type 'id'
I tried declaring the method like this, just to make the compiler understand it returns an NSTimeInterval and not an id:
#interface MyClass //type of myObject
-(NSTimeInterval)unknownNumberMethod;
#end
however, this makes the unknownNumberMethod return 0 constantly, so I assume it overwrites the real method with a blank one.
I also looked for some way to define an extern method of a class, but couldn't find the right syntax.
what is the correct way to "force" the compiler into realising that even though it doesn't find the method definition, it returns an NSTimeInterval and not an id?
Use an NSInvocation object instead of a performSelector call. See NSInvocation documentation
Have you tried this?
SEL selector = NSSelectorFromString(#"unknownNumberMethod");
if ([someInstance respondsToSelector:selector]) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:
[[myObject class] instanceMethodSignatureForSelector:selector]];
[invocation setSelector:selector];
[invocation setTarget:myObject];
[invocation invoke];
NSTimeInterval realValue;
[invocation getReturnValue:&realValue];
}
Restating my comment, maybe it's a bad idea, but one thing that probably can work is to render the id as a hex NSString using string formatting operation %p, then interpret that as a double...
id tempValue = [myObject unknownNumberMethod]; // compiler says: "instance method -unknownNumberMethod not found(return type defaults to 'id'
NSString *yuck = [NSString stringWithFormat:#"%p", tempValue];
NSTimeInterval result;
NSScanner *scanner = [NSScanner scannerWithString:yuck];
[scanner scanHexDouble:&result];
If you don't have access to the header file, the correct thing to do it provide your own method declaration in an informal protocol:
#interface NSObject(MyAppExtension)
- (NSTimeInterval)unknownNumberMethod;
#end
You then invoke the method as you would any other:
id foo = ...
NSTimeInterval timeInterval = 0.0;
if ([foo respondsToSelector:#selector(unknownNumberMethod)]) {
timeInterval = [foo unknownNumberMethod];
NSLog(#"Got Time Interval: %f", timeInterval);
}
this makes the unknownNumberMethod return 0 constantly, so I assume it overwrites the real method with a blank one.
That is incorrect; nothing is overwritten. Either an object provides an implementation for a given selector, or it doesn't.
If it's not returning the value you expect then the method has been declared with the incorrect return type. Try changing the return type on your method declaration to float or void*. A method that returns void* will have the same calling convention as a method that returns id on both 32-bit and 64-bit systems.
(If you're compiling for 32-bit iOS, that would explain why id works and NSTimeInterval does not. Declare the return type as float instead.)

dot syntax vs method syntax with getter=

I'm not sure how much use this question is but it seems interesting to me...
I thought that using property/synthesize statements was equivalent to me creating the getter/setter. Therefore
// .h
#property (nonatomic) BOOL on;
// .m
#synthesize on = _on;
// In my mind synthesizes the following methods
// - (BOOL)on;
// - (void)setOn:(BOOL)on;
However if I change the declarations to the following:
v
#property (nonatomic, getter=isOn) BOOL on;
#synthesize on = _on;
// In my mind synthesizes the following
// - (BOOL)isOn;
// - (void)setOn:(BOOL)on;
Then given the above I override the getter so I know when it is called:
- (BOOL)isOn;
{
NSLog(#"I was called");
return _on;
}
Now calling the following on an instance (myClass) results in:
NSLog(#"%d", [myClass isOn]);
//=> 2012-02-09 22:18:04.818 Untitled[1569:707] I was called
//=> 2012-02-09 22:18:04.820 Untitled[1569:707] 1
NSLog(#"%d", myClass.isOn);
//=> 2012-02-09 22:18:24.859 Untitled[1599:707] I was called
//=> 2012-02-09 22:18:24.861 Untitled[1599:707] 1
NSLog(#"%d", myClass.on); // This is the one I didn't expect to work
//=> 2012-02-09 22:18:55.568 Untitled[1629:707] I was called
//=> 2012-02-09 22:18:55.570 Untitled[1629:707] 1
I had always assumed that if I was using a property in this sense it was perfectly valid to use the getter/setter with dot syntax in the form
myClass.isOn;
myClass.on = on;
From another question it was suggested that when using dot syntax I should use the property name like this:
myClass.on // Correct
myClass.isOn // Incorrect
Although this works it seem slightly less logical because I know there is no underlying method - (BOOL)on it is instead mapped to - (BOOL)isOn
My questions are (using the latter example)
Is this a bug or should myClass.on really be silently changed to call - (BOOL)isOn
Semantically speaking I am accessing state not invoking behaviour so is my current use of dot syntax correct? (e.g. myClass.isOn)
Update
Although no one has explicitly said it I have reasoned that using .isOn is bad form because regardless of the fact that under the hood the same method is called, semantically isOn is asking a question, which is more behaviour rather than state.
However I am still unclear on where the "magic" wiring goes on that turns calls to myClass.on into [myClass isOn]
Update 2
After looking around the docs some more I found this section on Declared Properties. Using the following code I can inspect a class' properties:
id MyClass = objc_getClass("MyClass");
unsigned int outCount, i;
objc_property_t *properties = class_copyPropertyList(MyClass, &outCount);
for (i = 0; i < outCount; i++) {
objc_property_t property = properties[i];
NSLog(#"Name: %s, attributes: %s\n", property_getName(property), property_getAttributes(property));
}
//=> 2012-02-10 07:10:28.333 Untitled[934:707] Name: on, attributes: Tc,GisOn,V_on
So we have the following attributes:
name = on
type = char (Tc)
getter = isOn (GisOn)
variable = _on (V_on)
With all of this information available at runtime it kind of leaves the question is this lookup done at runtime or compile time like some answers suggest?
However I am still unclear on where the "magic" wiring goes on that turns calls to myClass.on into [myClass isOn]
The logic surely goes as follows, when compiling an obj.name in a getting context:
if(there is an accessible #property for name in scope)
{
if(there is a custom getter specified)
compile "[obj customGetter]"
else
compile "[obj name]"
}
else if (there is an an accessible instance method name in scope)
compile "[obj name]"
else
{
compile "[obj name]"
warn obj may not respond to name
}
There are other ways a language/execution environment can handle custom getter names, but given that Obj-C puts the declaration in the header (which is public) the above is a good guess as to where the custom getter logic is performed - when compiling the call site.
From your experiment we can infer that dot syntax is interpreted as follows:
is there a property with this name? If so, does it have a specified getter / setter name? if so, let's call that method.
otherwise, make up an appropriate method name (direct if we're getting, setXX if we're setting) and throw that at the receiver.
You can, for example, try to use .count against an NSArray instance. Before the abomination police kick in your doors, you may have time to see that it works.
To actually answer your question, in my mind dot notation should only be used to access properties, and in that case you should use the property name as declared in the interface. So .on for a UISwitch. I don't know why the getter name isn't given in the synthesize statement instead of the property declaration, it seems to belong in implementation rather than interface to me.
Well concerning dot notation, let me cite Aaron Hillegass (Cocoa Programming for Mac OSX, 3rd. Ed):
"Overall, I think that this is a rather silly addition to the language since we already had a syntax for sending messages."
When you have a member variable on, and your getter for this variable is called isOn then .on and .isOn are two very different kind of things. By using the getter (and probably a setter, too) you will adhere to the "information hiding" promise, whereas by using direct access to the member variables you won't. Cocoa won't enforce those things as it is relying on conventions. It's up to you to decide which way is right for you. Considering convention, you would have to stick to setters and getters - no matter what names you give them, though.
Property declarations are merely shorthand for regular method declarations. E.g.:
#property int color;
#property (getter=isOn) BOOL on;
becomes these method declarations:
- (int)color;
- (void)setColor:(int)value;
- (BOOL)isOn;
- (void)setOn:(BOOL)on;
You can call these methods just like any other method:
[foo color];
[foo isOn];
Likewise, dot notation is merely informal shorthand for calling plain old methods. For example:
x = #"Hello".length;
x = foo.on;
x = foo.isOn;
becomes
x = [#"Hello" length];
x = [foo isOn];
x = [foo isOn];
Note that #"Hello".length works even though NSString does not actually declare a property named "length". By default, foo.bar always expands to [foo bar] unless bar has been declared a property with a custom getter. If bar happens to be the name of a valid method then it will work without error.
Likewise, in your example foo.isOn works even though you don't actually declare a property named "isOn". Rather "isOn" is the name of a method that just happens to be the getter method for your "on" property.
So, while foo.isOn may work, it's considered bad form because isOn is not actually the name of the property.
What you cannot do is this:
x = [foo on]; // Error
because you never declare an on method.

Objective-c symbols ** & +-

Just when I think I'm getting comfortable with Objective-c the mentioned symbols totally throw me down a rabbit hole...
** a double pointer??
& what sort of things can I do with &reference, is a #property? a full on object? weird pointer razzledazzle?
± I see both a + or a - before method declarations; I've seen Java annotate some datatype declarations by manually typing the + and the magic of compiling in Eclipse would change them to a -
I'm likely asking repetitious questions and/or way outta the ballpark on my guesses; thanks for answers/edits.
You're getting into the C portion that objective-c is built on top of.
** is a pointer to a pointer. Since functions in C take arguments by value, it means you can't change the value of the argument in that function. But, by providing a level of indirection and passing a pointer to the pointer, you can change the value.
& means it's a reference. If an argument takes a ** and you have a * variable, pass a reference to it.
Foo *foo;
[self changeFoo: &foo];
- (BOOL)changeFoo: (Foo **)foo
{
// dereference the double pointer and assign a val = alloc init returns a *
*foo = [[Foo alloc] init];
return YES;
}
A common usage in objective-c / cocoa is NSError. It's essentially an out argument.
NSError *err;
BOOL success = [self doSomething:#"Foo" error:&err];
- (BOOL)doSomething:(NSString*)withData error:(NSError**)error
{
}
As you might know, a pointer points to the address of an object and is the way you reference an object. A double pointer is sometimes used in Objective-C, mainly for returning NSErrors, where you want to get back the address, i.e. a pointer, to an error object (NSError) if an error occurred, thus you pass in a pointer assigned to null and the caller can change that pointer so that it points to the address of another pointer which in turn points to an NSError object.
The ampersand (&) is mostly used by the lower level C APIs, e.g. Core Graphics. They are used to reference things, like the current context. As long as most of your code uses square brackets around its method calls you won't see these very often.
Using a + or a - before a method declarations is used to differentiate between class (+) and instance (-) methods. A class methods is called on the class itself (such as alloc), while a instance method is called on an instance of that object (such as init).
- and + before a method declaration designate an instance method and a static class method. To use an instance method you have to create an object of your class before you can call its method, a static method can be called directly from a class type