2015-10-05 3 views
5

Так у меня есть MainController,
внутри заголовка У меня есть этот void* заявил:Соблюдая изменения объекта ш /, кажется, не будет работать с ничтожной * КВО, контекст указатель, но работает с NSString *

static void *kStrokeColorWellChangedContext = &kStrokeColorWellChangedContext; 

Внутри реализации я обработка наблюдений:

-(void)observeValueForKeyPath:(NSString *)keyPath 
        ofObject:(id)object 
         change:(NSDictionary *)change 
         context:(void*)context 
{ 
    if([keyPath isEqualToString:@"color"]) 
    { 
     if(context == kStrokeColorWellChangedContext) 
     { 
     [self setValue:[change objectForKey:@"new"] forKey:@"strokeColor"]; 
     } 
    } 

Тогда у меня есть ViewController, который имеет эту линию, которая добавляет MainController в качестве наблюдателя на вид

[self.strokeColorWell addObserver:self.toolController forKeyPath:@"color" options:NSKeyValueObservingOptionNew context:kStrokeColorWellChangedContext]; 

Поэтому, когда цвет меняет взгляд, он уведомляет MainController и входит в -observeValueForKey: рутины, ж/ключ @"color"

Но он не может войти во внутренний блок if, где я проверяю context.

Если бы я был заменен на void* с NSString*, он работает так, как я ожидал.

Как могло случиться, что в нем есть два разных адреса: void*?

EDIT: Возможно значения void* может помочь

Результат po kStrokeColorWellChangedContext:

0x00000001005553e8

результат po context в -observeValueForKey::

0x0000000100555ea0

objc [17775]: Метод кэша поврежден. Это может быть сообщение для недопустимого объекта или ошибка памяти в другом месте.
ObjC [17775]: приемник 0x100555ea0, SEL 0x7fff899c8246, иш 0x100555ea0, кэш> 0x100555eb0, ведро 0x100566160, маска 0x0, оккупировал 0x0
ObjC [17775]: приемник 0 байты, ковши 0 байты
ObjC [17775]: селектор «respondsToSelector:»

исключения бросают может быть намек, но я действительно не понимаю ничего из этого

EDIT2: выход p вместо po

(lldb) p context 
(void *) $5 = 0x0000000100555ea0 
(lldb) p kStrokeColorWellChangedContext 
(void *) $6 = 0x00000001005553e8 

Обратите внимание, что я очень уверен, что отлаживаю правильное уведомление.
Две причины: keyPath уникален, и я вижу, что это значение правильно. Также, если я использую NSString* в качестве контекста, он работает

+0

У вас, похоже, есть опечатка в вашей строке 'static void'. Обе стороны '=' ссылаются на одно и то же имя переменной. Это, вероятно, не то, что вы хотите сделать. – rmaddy

+0

Я знаю, что это выглядит странно, но это похоже на The Way, как описано в NSHipster - хотя код addObserver не показан в этом случае, но с или без него он должен быть таким же. –

+0

Вы не можете использовать 'po' с аргументом 'context', потому что' context' не является объектом. Вот почему вы видите сообщение об ошибке «Это может быть сообщение недействительному объекту ...» – jlehr

ответ

5

Проблема заключается в том, что вы определяете kStrokeColorWellChangedContext как переменную static в заголовке. Каждая единица перевода (исходный файл, в основном), которая импортирует этот заголовок, создаст отдельную переменную этим именем, поскольку объявлено static, и это то, что это означает для переменных в области файлов.

Итак, каждая переменная будет иметь отдельный адрес и, поскольку значение переменной является ее собственным адресом, каждое будет иметь другое значение.

Вы можете объявить переменную в заголовке и определить ее в реализации так, что есть только одна такая переменная. Заявление в заголовке будет выглядеть следующим образом:

extern void * const kStrokeColorWellChangedContext; 

определение в одном из файлов реализация будет выглядеть следующим образом:

void * const kStrokeColorWellChangedContext = (void*)&kStrokeColorWellChangedContext; 

Обратите внимание, что я сделал переменный а const указателя к мочеиспусканию. Это запрещает что-либо от присвоения ему нового значения, поскольку оно должно быть константой.

+0

Правильный ответ - я пропустил часть «header». Хороший. –

+0

Удивительный, спасибо, что сломал его и объяснил - включая ключевое слово 'const'. Один быстрый вопрос, если у вас есть время: вы упомянули, что каждая единица перевода, которая импортирует заголовок, создаст отдельную переменную. Но я помню, что «# import» гарантирует, что файл когда-либо включается только один раз ». Знаете ли вы, как это работает, если я всегда использую '# import'? –

+0

Каждая единица перевода импортировала ваш заголовок. Как вы говорите, он импортирует его только один раз. Таким образом, каждая единица перевода имела определение 'static void * kStrokeColorWellChangedContext = ...' в области файлов. Поэтому каждая единица перевода имела свою собственную переменную 'kStrokeColorWellChangedContext', независимую от одноименной переменной в любой другой единицы перевода, которая также импортировала тот же заголовок. Нет необходимости, чтобы заголовок был импортирован * несколько раз ** для данной единицы перевода ***, чтобы вызвать проблемы. –

1

Это работает для меня - kStrokeColorWellChangedContext «имеет» два адреса: его положение в памяти и его значение, и они одинаковы! Поэтому kStrokeColorWellChangedContext и & kStrokeColorWellChangedContext должны быть взаимозаменяемыми в вашей программе.

Вы пробовали переходить через ваш ответный вызов KVO и просматривали/регистрировали значения context и kStrokeColorWellChangedContext? И keyPath?

+0

Степень моего тестирования заключалась в проверке значения 'context', переданного в' -observeValue'. Затем в 'lldb' я набрал' po kStrokeColorWellChangedContext'. Эти два значения были не одинаковыми, и я могу подтвердить, что представление отправляет уведомление в MainController, потому что, если я заменю контекст, который я перехожу в '-addObserver' со строкой, я вижу, что значение' context' является string –

+0

Никаких других наблюдателей не добавляется? –

+0

Да на самом деле. У меня точно такая же настройка с другим представлением, при этом все будет тем же, кроме контекста, называется kFillColorWellChangedContext. Но это значение контекста также не совпадает с «контекстом», переданным в 'observValue' Также я могу удалить его, и та же проблема все еще существует. Очень запутанно, потому что мы используем этот шаблон в другом месте в рабочей области, и он отлично работает –

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

  • Нет связанных вопросов^_^