Использование Objective C Подсчет ссылок , что означает каждый Объект, имеет подсчет ссылок. Когда объект создается, он имеет подсчет ссылок "1". Просто разговор, когда объект упомянут (т.е., сохраненный где-нибудь), он "сохраняется", что означает, что его подсчет ссылок увеличен одним. Когда объект больше не необходим, он "выпущен", что означает, что его подсчет ссылок уменьшен одним.
, Когда подсчет ссылок объекта 0, объект освобожден. Это - основной подсчет ссылок.
Для некоторых языков, ссылки автоматически увеличены и уменьшены, но цель-c не является одним из тех языков. Таким образом программист ответственен за сохранение и выпуск.
А типичный способ записать метод:
id myVar = [someObject someMessage];
.... do something ....;
[myVar release];
return someValue;
проблема необходимости не забыть высвобождать любые полученные средства в коде и утомительна и подвержена ошибкам. Objective C представляет другое понятие, нацеленное на создание этого намного легче: Пулы автовыпуска. Пулы автовыпуска являются специальными объектами, которые установлены на каждом потоке. Они - довольно простой класс, если Вы ищете NSAutoreleasePool.
, Когда объект отправит сообщение "автовыпуска" в него, объект будет искать любые пулы автовыпуска, находящиеся на стеке для этого текущего потока. Это добавит объект к списку как объект отправить сообщение "выпуска" в в какой-то момент в будущем, которое является обычно, когда сам пул выпущен.
Взятие кода выше, можно переписать его, чтобы быть короче и легче читать путем высказывания:
id myVar = [[someObject someMessage] autorelease];
... do something ...;
return someValue;
, поскольку объект автовыпущен, мы больше не должны явно называть "выпуск" на нем. Это вызвано тем, что мы знаем, что некоторый пул автовыпуска сделает это для нас позже.
, Надо надеяться, это помогает. Статья Wikipedia довольно хороша о подсчете ссылок. Больше информации приблизительно пулы автовыпуска может быть найдено здесь . Также обратите внимание, что, если Вы создаете для Mac OS X 10.5 и позже, можно сказать, что XCode для создания с включенной сборкой "мусора", позволяя Вам полностью проигнорировать сохраняет/выпускает/автовыпускает.
В своей первой попытке решить эту проблему я удалил Class B наследование MarshalByRefObject
и вместо этого пометил его как сериализуемый. В результате объект был упорядочен по значению, и я только что получил копию Class C , которая выполняется в главном домене приложений. Это не то, что я хотел.
Реальное решение, которое я обнаружил, заключалось в том, что класс B ( DangerousProgram
в примере) также должен наследовать от MarshalByRefObject
так что обратный вызов также использует прокси для перехода потока обратно в домен приложения по умолчанию.
Кстати, вот отличная статья , которую я нашел Эриком Липпертом, которая объясняет маршал by ref vs. marshal by value очень умным способом.
Магия событий .NET скрывает тот факт, что, когда вы подписываетесь на событие в экземпляре B экземпляром A, A отправляется в домен приложения B. Если A не является MarshalByRef, то отправляется копия значения A. Теперь у вас есть два отдельных экземпляра A, поэтому вы столкнулись с неожиданным поведением.
Если кому-то сложно понять, как это происходит, я предлагаю следующий обходной путь, который делает очевидным, почему события ведут себя именно так.
Чтобы вызывать «события» в B (в домене приложения 2) и обрабатывать их в A (в домене приложения 1) без использования реальных событий, нам нужно создать второй объект, который переводит вызовы методов (которые пересекают границы без много шума) к событиям (которые ведут себя не так, как вы могли бы ожидать). Назовем этот класс X, будет создан в домене приложения 1, а его прокси будет отправлен в домен приложения 2. Вот код:
public class X : MarshalByRefObject
{
public event EventHandler MyEvent;
public void FireEvent(){ MyEvent(this, EventArgs.Empty); }
}
Псевдокод будет выглядеть примерно так:
Для B для запускать событие обратно в AD1 , он должен иметь не только метод, но и экземпляр для запуска этого метода. Вот почему мы должны отправить прокси X в AD2 . Это также , почему междоменные события требуют, чтобы обработчик событий был упорядочен через границу домена! Событие - это просто причудливая оболочка для выполнения метода. И для этого вам понадобится не только метод, но и экземпляр, на котором он будет выполняться.