2013-07-02 2 views
6

Я получил вышеуказанную ошибку при переносе в ARC. Вот код:Неявное преобразование типа указателя не Objective-C void * в NSString * __ strong * не разрешено с помощью ARC

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 
    { 
     ... 
    } 

Когда я использовал мост:

if (&cashBalanceKeyPath == (__bridge NSString *)context) 

я получил ошибку: Comparison of distinct pointer types (NSString *__strong* and NSString *)

Как я могу сделать преобразование? Заранее спасибо.

+1

Было ли сравнение даже с MRC? – Sulthan

+0

Да. Сравнение отлично работает с MRC (без ARC). Это может быть неявное преобразование. – user2543991

+1

Исходное сравнение '& cashBalanceKeyPath == context' выглядит нормально даже в ARC. Вы не сравниваете какие-либо объекты, даже не добавляете объекты в простые указатели. Какова исходная ошибка компиляции? – Tricertops

ответ

1

Если вырезать __strong в сообщении об ошибке, это ясно, что происходит:

Comparison of distinct pointer types (NSString ** and NSString *) 

&cashBalanceKeyPath является указателем на объект NSString или NSString**, а контекст быть приведен к NSString*, или простой объект NSString (которого нет).

Итак, чтобы исправить проблему, измените отливку на (NSString * const *), по-видимому, const должен успокоить ARC.

+0

if (& cashBalanceKeyPath == (__bridge NSString **) context) Я получил ошибку: указатель на не-const тип NSString * без явного права собственности – user2543991

+0

Это дает ошибку: указатель на не-const тип NSString * 'без явного владение " –

+0

@ user2543991 Да, ошибся там. Обновлено, чтобы использовать правильный листинг – cobbal

2

Я не могу вам точно сказать, почему, но вы не получите предупреждение или сообщение об ошибке, если поменять порядок сравнения:

if (context == &cashBalanceKeyPath) { 
    // ...  
} 
+0

Это интересно. Кто-нибудь знает, почему ????? – user2543991

+0

Ick! Вы правы, и я не знаю, из-за чего, либо, либо в правилах преобразования ошибок или C (на любом другом языке об этом не подумайте, а в семействе C ...). Я бы не советовал полагаться на это. – CRD

+1

Это то, что я * предполагаю/угадываю *: правая сторона '==' отлита от типа левой стороны. Кастинг 'NSString **' на 'void *' разрешен с помощью ARC, но противоположное направление запрещено. –

-1

Причина вы получаете ошибку, потому что вы «Сравнение строки и указателя на строку, когда вы действительно просто хотите сравнить две строки. Когда вы сравниваете две строки, вы должны использовать isEqualToString. Таким образом, ваш код может выглядеть так:

NSString *contextString = (__bridge NSString *)context; 
if ([contextString isEqualToString:cashBalanceKeyPath]) 
{ 
    //Do something 
} 
... 

Надеюсь, что это поможет!

+0

Если я правильно понял вопрос, он не хочет сравнивать строки. 'context' является адресом переменной' cashBalanceKeyPath' и просто используется как уникальный указатель. –

+1

Извините, непонятый этот конкретный вопрос. У меня была эта проблема до этого и она была решена, но моя ситуация была другой, как вы указали. – architectpianist

2

Вы, кажется, используете адрес переменной как уникальный тег, поэтому здесь нет проблем с управлением памятью/владением. Для сравнения адресов отбрасывать адрес переменных к мочеиспусканию:

if ((void *)&cashBalanceKeyPath == context) 

Это, кажется, дает компилятор всему это нужно без моста гипса.

+0

Справа. На самом деле автор вопроса не сообщал оригинальное сообщение об ошибке/предупреждении, которое приводило к созданию моста. Может быть, это были просто несовместимые указатели? – Tricertops

+0

@iMartin: Я думаю, что исходное сообщение об ошибке находится в заголовке вопроса. –

+0

@MartinR Ах, вы правы. Очень хорошее размещение! – Tricertops

0

в cashBalanceKeyPath является указателем и context указатель правильный способ сравнить два является:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { 
    if (context == (__bridge void *)(cashBalanceKeyPath)) { 

    } 
} 

и вызов должен быть:

[xxx addObserver:self forKeyPath:cashBalanceKeyPath options:0 context:(__bridge void *)(cashBalanceKeyPath)]; 

Интересно, как ваш код может работать с MRC.

+0

'context' ожидает содержать ** адрес объекта, а не сам объект **. Ваше сравнение никогда не пройдет. – Tricertops

+0

После вашего редактирования: Да, если он будет использовать сам объект как «контекст», ваше решение будет правильным. Но он использует адрес объекта (указатель на объект). – Tricertops

+0

Вы правы, но я думаю, что просто смешно использовать указатель таким образом. –

-1

Если вы хотите сравнить строки вы должны использовать метод isEqualToString:

+0

Хм. Было бы неплохо понять голосу за ясность. – uchuugaka

+0

Голосов нет, потому что он не заинтересован в равенстве строк. В watchValueForKeyPath передается контекст, который необходимо идентифицировать. Контекст может быть _anything_. Для простоты он решил передать адрес статической переменной в качестве контекста и пытается проверить, соответствует ли контекст адресу статической переменной. – gnasher729

+0

Справедливо! Спасибо за разъяснения. – uchuugaka

-1

ARC вообще не нравится __strong, когда дело доходит до строки и Apple, рекомендуется использовать копию.

+0

«copy» может использоваться для свойства NSString * *, но это совершенно не связанная тема. Я не вижу объявления собственности в вопросе. –

0

Вся проблема, вероятно, можно избежать написания

static int cashBalanceKeyPathContext = 0; 

и использование & cashBalanceKeyPathContext в зависимости от контекста.

Смежные вопросы

 Смежные вопросы