Reputation: 625
I got the above error when migrate to ARC. Here is the code:
static NSString *cashBalanceKeyPath = @"test";
...
[xxx forKeyPath:cashBalanceKeyPath options:NSKeyValueObservingOptionNew context:&cashBalanceKeyPath];
...
-(void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
if (&cashBalanceKeyPath == context) < error here
{
...
}
When I used bridge:
if (&cashBalanceKeyPath == (__bridge NSString *)context)
I got the error: Comparison of distinct pointer types (NSString *__strong* and NSString *)
How can I make the conversion? Thanks in advance.
Upvotes: 6
Views: 6943
Reputation: 52548
The whole problem can probably be avoided by writing
static int cashBalanceKeyPathContext = 0;
and using &cashBalanceKeyPathContext as the context.
Upvotes: 0
Reputation: 2241
ARC generally doesn't like __strong when it comes to string and Apple recommend that you use copy.
Upvotes: -1
Reputation: 12782
If you want to compare strings you should be using the method isEqualToString:
Upvotes: -1
Reputation: 70753
If you strip out the __strong
in the error message, it's clearer what's going on:
Comparison of distinct pointer types (NSString ** and NSString *)
&cashBalanceKeyPath
is a pointer to an NSString object, or a NSString**
, while context is being cast to an NSString*
, or a plain NSString object (which it isn't).
So to fix the problem, change the cast to be (NSString * const *)
, the const is apparently required to appease ARC.
Upvotes: 1
Reputation: 4406
as cashBalanceKeyPath
is a pointer and context
is a pointer the correct way to compare this two is:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if (context == (__bridge void *)(cashBalanceKeyPath)) {
}
}
and the call should be:
[xxx addObserver:self forKeyPath:cashBalanceKeyPath options:0 context:(__bridge void *)(cashBalanceKeyPath)];
I wonder how your code could work with MRC.
Upvotes: 0
Reputation: 53000
You appear to be using the address of a variable as a unique tag, so there are no memory management/ownership issues here. To do the address comparison cast the address of the variable to void:
if ((void *)&cashBalanceKeyPath == context)
That seems to give the compiler all it needs without any bridge cast.
Upvotes: 2
Reputation: 2552
The reason you're getting the error is because you're comparing a string and a pointer to a string, when you really just want to compare two strings. When you're comparing two strings, you should use isEqualToString
. So your code might look like this:
NSString *contextString = (__bridge NSString *)context;
if ([contextString isEqualToString:cashBalanceKeyPath])
{
//Do something
}
...
Hope this helps!
Upvotes: -1
Reputation: 539815
I can't tell you exactly why, but you don't get a warning or error if you swap the order of the comparison:
if (context == &cashBalanceKeyPath) {
// ...
}
Upvotes: 2