Я прав о том, что я сказал в своем комментарии к ответу обратного пути.
Переменные - это контейнеры. Переменная отлична от значения, которое находится в ней. Как правило, когда вы используете имя переменной в своем коде, вы на самом деле ссылаетесь на значение; когда вы говорите foo(bar)
, вы не передаете переменную bar
на функцию foo
, вы передаете значение, которое находится в переменной bar
.
Локальные переменные не инициализируются ничем, если вы не инициализируете их. Итак, не никогда ссылается на локальную переменную, не присваивая ей или не инициализируя ее ранее. Случайные плохие вещи будут случайным образом случаться.
Переменные экземпляра, с другой стороны, инициализируются до nil
и будут содержать nil
, пока вы не разместите в них что-то еще. Это важно, потому что все через init
вы ничего не поместили в переменную экземпляра testWindow
, поэтому она содержит nil
.
Затем, указав addObserver:… selector:… name:… object:testWindow
, вы передаете это значение по умолчанию, nil
, в качестве объекта, для которого вы хотите наблюдать за уведомлениями. Это означает наблюдение за этим уведомлением для любого объекта.
Это не то, что вы имели в виду, но то, что вы имели в виду, не то, что вы написали. Вы хотели добавить себя в качестве наблюдателя для тестового окна. Но вы еще не создали тестовое окно, и вы не указали его указатель на переменную testWindow
, так что вы написали, чтобы добавить себя в качестве наблюдателя для любого объекта.
Только после того, как уведомление происходит, вы создаете окно (неправильно, при этом) и назначаете его переменной. Это слишком поздно для того, чтобы это повлияло на ваше наблюдение; присваивание не ретроактивно изменяет то, как вы наблюдаете, потому что вы могли передавать только то, что было в переменной в это время (что было nil
); вы не могли и не могли передавать переменную или любые возможные будущие значения переменной.
Итак, вам нужно создать окно и назначить переменную в init
, , затем добавить себя в качестве наблюдателя для уведомления.
Существует два правильных способа создания окна в коде. This - один из них, а this - другой. Не используйте простой init
, чтобы создать окно, потому что оно не будет иметь прямоугольник рамки.
Или, еще лучше, вместо того, чтобы делать все это в коде, просто используйте IB, чтобы сделать окно. Вы должны сделать выход testWindow
и начать наблюдение в awakeFromNib
.
В любом случае у вас есть проблема и на другом конце, потому что вы release
(и тем самым уничтожаете или, по крайней мере, пытаетесь уничтожить) окно в методе уведомления. Не ожидайте продолжения получения уведомлений об объекте после его уничтожения. Вам нужно переместить это сообщение release
и nil
в другое место вашего кода, в место, где вы действительно закончили с окном, а не просто скрывать его временно.
В итоге:
- Создать окно и назначить его указатель на переменную
testWindow
в init
, перед тем вы посылаете, что addObserver:selector:name:object:
сообщение.
- Для окна, которое пользователь может отображать и скрывать, сохраняйте время жизни окна отдельно от отображаемого/скрытого состояния. Все в порядке, если у вас заказанный оконный объект; вам не нужно уничтожать его, как только вы его закажете. Во всяком случае, память не так уж и скучна, а не на Mac. Отпустите окно, только когда вы действительно закончите с ним, возможно, только в
dealloc
.
(О, и стиль/maintanability дело: Не посыпаем буквенные строки, как @"TestNotification"
всего кода Определить переменную с этим значением где-то, и использовать эту переменную везде, где вы хотите использовать уведомление Тогда.. , чтобы изменить строку, вы меняете ее ровно в одном месте и переименовываете переменную, вы можете использовать инструмент Refactor Xcode.)
Спасибо за все это. На самом деле я не создаю свое окно таким образом, но я просто не добавил всю часть NSMakeRange(). –
Er, вы имеете в виду 'NSMakeRect'? –