Некоторые методы из классов Cocoa принимают необязательный параметр, обозначаемый как void* и нередко называемый contextНа первый взгляд, параметр void*, обозначающий тип универсального указателя, подобен параметру id, обозначающему универсальный тип объекта, поскольку ссылка на объект является указателем.

На самом деле параметр id обозначает универсальный тип объекта, тогда как параметр void* — просто указатель языка С. Это означает, что в среде Cocoa значение типа void* не интерпретируется как объект, и поэтому выделяемая для него память не требует автоматического управления. Таким образом, в ваши обязанности входит обеспечить сохранение этого значения в памяти настолько долго, насколько это будет для вас полезно.

Насколько долго этого будет достаточно? Назначение аргумента context:, передаваемого методу, состоит в том, чтобы быть возвращенным в качестве параметра context: при обратном вызове и помочь распознать что-нибудь или предоставить дополнительные сведения. Так, если предоставить значение параметра context: при вызове метода beginAnimations : context:, то от среды Cocoa можно ожидать вызова реализации метода animationDidStop: finished: context: с тем же самым значением параметра context:. Следовательно, значение параметра context: необходимо сохранить до тех пор, пока не будет сделан обратный вызов метода animationDidStop: finished: context:.

Иногда параметр context: обозначает только идентификатор с намерением лишь сравнить параметр context: в обратном вызове с исходно переданным аргументом context:. Следовательно, он может быть сохранен как внешняя переменная в том классе, где он используется. Ниже приведен обычно рекомендуемый образец такого применения параметра context: в коде.

static void* const MYCONTEXT = (void*)&MYCONTEXT;

В данном случае имя MYCONTEXT имеет значение, указывающее на собственную область памяти, а параметр context: в обратном вызове может быть сравнен с ним непосредственно. Еще одним аргументом context:, часто рекомендуемым в качестве значения идентификатора, служит ссылка на объект self. Очевидно, что такая ссылка будет существовать при условии, что ей может быть отправлено сообщение обратного вызова, а следовательно, она имеет прямую сохраняемость.

С другой стороны, параметр context: может обозначать отдельный полноценный объект. В этом случае его нужно где-то хранить. Для этой цели лучше всего подходит переменная экземпляра, поскольку внешняя переменная действует на уровне класса, а для работы с другими значениями параметра context: могут потребоваться иные экземпляры данного класса.

Если действует механизм ARC, то объект Objective-C нельзя передать вместо ожидаемого значения типа void*, и наоборот, не указав дополнительные сведения для управления памятью. Это еще один случай “пересечения моста” (т.е. стыкования типов), рассматривавшегося в предыдущем разделе. Любое управление памятью уже произведено на стороне объектов

Objective-C, и поэтому достаточно простого приведения к стыковочному типу bridge.

Если же в качестве аргумента context: передается значение, то требуется приведение его типа ( bridge void*), а когда оно возвращается из обратного вызова, — обратное приведение его типа ( bridge id).

Приведенные выше соображения не распространяются на параметры, обозначаемые как объекты. Например, при вызове метода postNotificationName: object: userlnfo: параметр userlnfo: обозначается как объект типа NSDictionary и сохраняется автоматически центром уведомлений, а освобождается после рассылки уведомления. Управление памятью, выделяемой для этого объекта, происходит подспудно и поэтому не является вашей заботой.


 

 

 

Добавить комментарий