I'm having one error and one warning concerning the usage of the 'GetTiming()' function. My colde is as follows:
[values addObject:[NSNumber numberWithFloat:25.0]];
[timings addObject:GetTiming(kCAMediaTimingFunctionEaseIn)];
[keytimes addObject:[NSNumber numberWithFloat:0.0]];
I am importing the following:
#import <QuartzCore/CAAnimation.h>
#import <QuartzCore/CAMediaTimingFunction.h>
The error I suppose is due to the fact that I'm using ARC, and says:
implicit conversion of 'int' to 'id' is disallowed with ARC.
I tried to disable ARC in the concerning file but the error persists.
About the warning, it says:
implicit declaration of function 'GetTiming' is invalid in C99
Any one have any ideas on how can I fix these issues?
Thanks a lot!
First make sure that the GetTiming function exists (include the right header). Now if GetTiming returns an int the problem is you can not add a primitive value to an array. You need to wrap the value returned in an NSNumber.
[timings addObject:
[NSNumber numberWithInt:GetTiming(kCAMediaTimingFunctionEaseIn)]];
Edit:
You are missing the function that was declared in JackController.m.
CAMediaTimingFunction* GetTiming(NSString* name) {
return [CAMediaTimingFunction functionWithName:name];
}
For simplicity do not use that function, just create it directly.
[timings addObject:
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]];
Related
I have the following code:
SEL moveAlongBoth = #selector(moveAlongX:andY:);
if ([p1 respondsToSelector:moveAlongBoth]) {
[p1 performSelector: moveAlongBoth
withObject: [NSNumber numberWithInt:1]
withObject: [NSNumber numberWithInt:1]];
}
I am getting a "performSelector may cause leak" warning.
But
[p1 moveAlongX:1 andY:1];
Works just fine.
I understand that I am getting the error because the values are set to (int) in the implementation and I am using NSNumber. Without changing the implementation, how would I go about declaring a number value to int (if possible)?
Why can't you just do this:
if ([p1 respondsToSelector:#selector(moveAlongX:andY:)]) {
[(id)p1 moveAlongX:1 andY:1];
}
By the way, the Cocoa naming convention would have you call this method moveAlongX:y:.
With regard to the second part. If you are in charge of the classes that may be the type of p1, then you could define a protocol with moveAlongBoth:: and instead of checking with performSelector check wit conformsToProtocol. Let's say the protocol's name is CanMoveAlong then you can cast it to
id <CanMoveAlong> canDo = (id<CanMoveAlong>)p1;
after you checked conformity and directly invoke the method
[canDo moveAlongX:1 andY:1];
Doing so you achieve both, you get rid of the warning and you can pass int directly without using NSNumber.
I had a function that was supposed to return an NSURL, but I accidentally had it return an NSString. Xcode did not issue any warnings. Any idea why this is or how I can enable warnings for this. (It lead to a crash later in the app). Incidentally, if I change the function to return an NSMutableDictionary, I do get a compiler warning about incompatible return types. I am using Xcode 4.5.1.
-(NSURL *) urlForThing:(Thing *)thing
{
//This is clearly a string at compile time and I would expect a warning
//If I change this to [NSMutableDictionary alloc] I do get a warning
return [NSString stringWithFormat:#"thing://url/%#", thing];
}
Well, I suppose the short answer is that stringWithFormat: returns an id, not an NSString. This doesn't make much sense to me, but it explains the lack of warning.
I have an array of views, and I need to hide them all, so I use:
BOOL shouldHideViews = YES;
[allViews makeObjectPerformSelector:#selector(setHidden:) withObject:(void *)shouldHideViews]
When I convert the code to ARC, it tells me I need some bridged cast, then I changed:
(void *)shouldHideViews
to
(__bridge BOOL)shouldHideViews
it says incompatible types casting 'int' to 'BOOL' with a __bridge cast
So how do I do it? I know I can just iterate all the views in the array, but this is not the point, I want to know in general what I should do to make this ARC compatible.
Thanks!
The other answers indicating that you can't pass YES this way are correct. There are easier solutions however:
[allViews setValue:[NSNumber numberWithBool: shouldHideViews] forKey:#"hidden"];
This works because NSArray overrides its setValue:forKey: for exactly this use.
You can also now use blocks:
[allViews enumerateObjectsUsingBlock:
^(id obj, NSUInteger idx, BOOL *stop){ [obj setHidden:shouldHideViews];}];
Or the tried and true for() loop (see #rob mayoff's answer.)
Of them, I generally just use a for loop.
you can't pass primitive types as a void pointer. You should keep the boolean variable as an instance variable and reference it in the setHidden. That way you can just do this:
shouldHideViews = YES; //declare BOOL shouldHideViews; in your .h file
[allViews makeObjectPerformSelector:#selector(setHidden) withObject:nil];
These will be rather helpful to you
How to use performSelector:withObject:afterDelay: with primitive types in Cocoa?.
Using performSelector:withObject:afterDelay: with non-object parameters
SEL performSelector and arguments
Either you should make a wrapper using NSNumber or use NSInvocation.
The object argument to makeObjectsPerformSelector:withObject: is of type id. That means it needs to point to an Objective-C object. Casting a non-object to an id is a bad idea, because the system (particularly under ARC) is allowed to do things like send the retain and release messages to an id, and that will crash if you cast YES to id.
I suggest just using fast enumeration:
for (UIView *view in allViews) {
view.hidden = shouldHideViews;
}
This code gives me EXC_BAD_ACCESS, why?
NSMutableDictionary *d = [[NSMutableDictionary alloc] init];
IMP imp= [d methodForSelector:#selector(setObject:forKey:) ];
imp(d, #selector( setObject:forKey:), #"obj", #"key");
I'm just starting using IMP, firs try.. no luck. Not sure why I get the error, also.. in the past, when I got EXC_BAD_ACCESS, the message was printed at the console, this time the error line is highlighted.
Some notes:
ARC is enabled, XCode 4.3.2, the project uses Objective-C++ as de default language/compiler,this code is at the very beginning of the project
thanks guys
You need to cast the function pointer properly or ARC doesn't know what it's supposed to be doing. IMP is a generic function pointer that takes an id, a selector and a variable number of other, undefined arguments and returns an id. The method implementation you're trying to call takes an id, a selector followed by exactly two id parameters and has a void return type. You can fix it by changing to the following code:
NSMutableDictionary* dict = [[NSMutableDictionary alloc] init];
void (*imp)(id, SEL, id, id) = (void(*)(id,SEL,id,id))[dict methodForSelector:#selector(setObject:forKey:)];
if( imp ) imp(dict, #selector(setObject:forKey:), #"obj", #"key");
You should always check that you actually got a function pointer back before you dereference it, as that would also crash. The code above will work even in an ARC environment. Also, even when you're not using ARC, you should always cast your function pointers to the actual prototype rather than IMP. You should never use IMP. Other places that would cause major issues are if the method returns a struct or if the method takes floating point parameters, etc.
Good habit: always cast your function pointers or make typedefs for them if you find the function pointer syntax jarring.
The problem is that IMP has a return type of "id" which ARC will attempt to manage. You need to cast your function pointer to have a return type of void (consistent with the method you are calling):
NSMutableDictionary *d = [[NSMutableDictionary alloc] init];
IMP imp= [d methodForSelector: #selector(setObject:forKey:)];
void (*func)(__strong id,SEL,...) = (void (*)(__strong id, SEL, ...))imp;
func( d, #selector(setObject:forKey:), #"obj", #"key" );
I am trying to return a subset of my NSMutableArray (MessageArray) with the following code. MessageArray contains an NSDictionary, one of the keys being FriendStatus. I get a strange error which I know is a DUH syntax issue. "error. void value not ignored as it ought to be".
-(NSMutableArray*)FriendMessageArray {
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"FriendStatus == 1"];
NSMutableArray *filtered = [MessageArray filterUsingPredicate:predicate];
return filtered;
}
"void value not ignored as it ought to be" means that a method with a signature that starts with (void) is being used to assign a value or object to a variable. What's the signature for filterUsingPredicate? does it start with (void) ?
I'm assuming "MessageArray" is an instance variable (never name instance variables this way; you should have a property called -messages and access it with self.messages). I'l further assume that it is an NSMutableArray or else you'd be getting warnings from the compiler.
NSMutableArray -filterUsingPredicate: modifies the array itself, returning void. The method you want is -filteredArrayUsingPredicate: which returns an array. The fact that the former is a verb and the latter is a noun indicates this fact even without reading the docs. Cocoa naming is extremely consistent, which is why I mention it in the first paragraph. Pay attention to the names and you will have far fewer bugs.