настройка свойств и делегатов - когда использовать self? - PullRequest
0 голосов
/ 01 октября 2011

Я работаю с примером кода NSXMLParser и у меня есть пара вопросов о том, как устанавливаются делегаты и свойства, особенно в AppDelegate.

В интерфейсе объявлено, что AppDelegate следует за NSXMLParserDelegate protocol, но, похоже, не реализует ни один из методов протокола или не устанавливает себя в качестве делегата в любой точке.Кажется, они в классе ParseOperation.Это просто опечатка?

@interface SeismicXMLAppDelegate : NSObject <UIApplicationDelegate, NSXMLParserDelegate> {
    UIWindow *window;
    UINavigationController *navigationController;
    RootViewController *rootViewController;

@private
    // for downloading the xml data
    NSURLConnection *earthquakeFeedConnection;
    NSMutableData *earthquakeData;

    NSOperationQueue *parseQueue;
}

Интерфейс также объявляет некоторые частные свойства.Они снова определены в расширении интерфейса в файле .m.

@interface SeismicXMLAppDelegate ()

@property (nonatomic, retain) NSURLConnection *earthquakeFeedConnection;
@property (nonatomic, retain) NSMutableData *earthquakeData;    // the data returned from the NSURLConnection
@property (nonatomic, retain) NSOperationQueue *parseQueue;     // the queue that manages our NSOperation for parsing earthquake data

- (void)addEarthquakesToList:(NSArray *)earthquakes;
- (void)handleError:(NSError *)error;
@end

ОК, я думаю, я понимаю, что это означает, что другие классы не могут получить доступ к этим свойствам, и это кажется действительно хорошей вещью вэтот случай.Вот загадка - в реализации - applicationDidFinishLaunching: два свойства определены с использованием разных обозначений.

self.earthquakeFeedConnection =
[[[NSURLConnection alloc] initWithRequest:earthquakeURLRequest delegate:self] autorelease];

против

parseQueue = [NSOperationQueue new];

Почему одно из них назначается с помощью self.propertyName = идругой с propertyName =?Я знаю, что как parseQueue, так и earthquakeFeedConnection заканчиваются счетом сохранения 1, с той разницей, что earthquakeFeedConnection является частью autorelease pool и будет выпущен автоматически, тогда как нам придется выпустить parseQueue позже,использования +new и не вызывая autorelease.

Вопросы памяти не объясняют использование себя.Есть ли другая разница?

Ответы [ 2 ]

1 голос
/ 01 октября 2011

alloc и new возвращают объекты, которые сохраняются один раз. init не влияет на управление памятью и autorelease освободит этот объект позже один раз.

если вы пишете self.myProperty = ..., то вызывается установщик synthesized, который ведет себя так, как вы определили в соответствующем свойстве nonatomic, retain. nonatomic означает, что метод получения и установки не являются поточно-безопасными (но быстрыми). retain означает в этом случае, что установщик освободит старый объект и сохранит новый объект. если бы вы написали assign вместо retain, то установщик просто назначил бы указатель и не вызвал бы освобождение или сохранение для затронутых объектов.

Цель вашего примера - создать два объекта, которые сохраняются один раз.
Example1:

self.earthquakeFeedConnection = [[[NSURLConnection alloc] initWithRequest:earthquakeURLRequest delegate:self] autorelease];
  • после alloc: retainCount: 1
  • после автоматического выпуска: retainCount: 1-1 (минус один означает: выпущено позже)
  • после вызова установщика: retainCount: 2-1

Пример 2:

parseQueue = [NSOperationQueue new];

  • после нового: retainCount: 1

Так что в итоге оба случая приводят к одному и тому же. Вы также можете написать

earthquakeFeedConnection = [[NSURLConnection alloc] initWithRequest:earthquakeURLRequest delegate:self];

Сеттер-решение выглядит сложнее, но есть некоторые побочные эффекты. Если позже вы заметите, что вам нужно специальное поведение либо внутри метода получения, либо для установки (например: запуск некоторых других методов или проверка некоторого значения: NSString, который должен содержать только адреса электронной почты), то вам нужно только перезаписать метод получения или установки. Если вы не используете self.myProp = ..., вам придется искать использование и также изменять этот фрагмент кода.

Делегат: да, вы правы: обычно вы должны (или должны) перечислить все реализованные протоколы в определении интерфейса, но NSURLConnectionDelegate является исключением. Я не знаю почему (я не нахожу точку реализации в NSObject -class-reference), но каждый NSObject уже реализует этот делегат. Поэтому вам не нужно упоминать, что ваш класс реализует этот делегат.

0 голосов
/ 04 октября 2011

Резюме: Ответ Томаса подтверждает тайну протокола делегата.Декларация, как я и предполагал, просто опечатка.Так что я не скучаю по лодке, что приятно, поэтому я принимаю его ответ.

Ответ об использовании -alloc, -init vs + new менее удовлетворителен.Фраза «просто стиль кодирования», кажется, отбрасывает что-то важное, поэтому я придумал свой собственный анализ.По сути, я думаю, что это защитный элемент авторского стиля: этот подход не делает никаких предположений об инициализированном объекте.

verbose = N Объединение + new и пользовательского установщика может привести к проблемам,Если пользовательская реализация установщика предполагает, что инициализированный объект имеет определенное состояние (например, что-то, что могло быть сделано в методе custom -init), это может привести к плохим последствиям.Избегайте любых конфликтов, не делая никаких предположений об объекте.Убедитесь, что пользовательский установщик не вызывается, если настройка явно не выполнена.Таким образом, безопасно вызывайте [self setPropCustom] = [[PropClass alloc] initWithCustomization] и избегайте вызова [self setPropCustom] для [[PropClass alloc] init].Поскольку -init часто переопределяется, получайте минимальный объект с помощью + new вместо -alloc, -init.

vervose = Y Я своего рода нуби.У меня есть опыт в достижении цели, но очень мало в том, чтобы делать это элегантно или в стиле CS.Поэтому я заинтересован в стилях кодирования.Почему автор может «любить» делать это особым образом?Это она пережила, я действительно сомневаюсь, что это просто «настроение».

Существует множество дискуссий о стиле кодирования на блог Уилла Шипли , особенно серия «Прокачай мой код», которая является своего рода жемчужиной.Он включает в себя довольно подробное обсуждение + new vs -alloc, -init.Я процитирую один из комментариев :

Корвин сказал ...

[отредактировано] Код - это ремесло.Это неточно.Написание кода, который следует стилю всех остальных, похоже на написание поэзии в том же метре и стиле, что и у всех остальных.Подумайте немного, поймите, что каждый небольшой изюминка, которую ваш код передает, является маленькой частью вас, и перестаньте делать его «идеальным».Читайте чужой кодекс, как если бы вы писали стихи - черпайте вдохновение из него, учитесь у него, иногда подражайте ему, но никогда не воспринимайте его как личное оскорбление.

В конце дня вы должны спросить себя: сделал ли код, который я пишу, искусство?Это облегчит жизнь пользователя?Это заставило меня чувствовать себя хорошо?Если вы можете ответить на эти вопросы, да, вы в порядке.Все остальное недействительно.
25 августа 2005 г. 12:08 *

Итак, что я могу узнать из этого стиля кодирования в NSXMLParser?Какое вдохновение я могу получить от этого?Что ж…

Смысл стиля кодирования состоит в том, чтобы дать себе дополнительную информацию о том, как вы решаете что-то делать, и использовать согласованные шаблоны, чтобы избежать известных ловушек.Есть, как правило, несколько способов достижения желаемого результата.Выделение памяти - это то, что программисты делают постоянно.Его так много называют, что помогает быть последовательным в том, как вы это делаете.Ну и дела, если бы я был последовательн в том, куда я положил обувь ребенка, мне не пришлось бы охотиться в течение 10 минут каждое утро.Согласованность - это быстрый путь, а стиль кодирования обеспечивает согласованность кода.

Поэзия о нескольких значениях.Речь идет не просто о том, чтобы вызвать слово, но о том, чтобы вызвать эмоцию или ощущение одновременно.... так сочно и так мило.

Поэтому разработка стиля кодирования - это разработка кратких и последовательных способов общения с другим программистом или с самим собой в будущем.Вам не нужно спрашивать «что я здесь делал».Это должно быть частью вашего стиля кодирования.

Итак, вернемся к NSXMLParser. По словам Томаса, этот автор 'любит использовать new без вызова установщика, за исключением того, что он хочет использовать initWith... -метод: тогда он также использует установщик.' (Томас, 4 октября). То, что я хочу знать, это , почему автор выбрал это соглашение как часть своего стиля кодирования? Какой в ​​этом смысл?

Конечно, я бы не стал это писать, кроме того, что, я думаю, я понимаю.

Когда вы пишете класс, вы можете переопределить -init, но вы не переопределите + new. Когда вы пишете класс, вы можете переопределить синтезированные сеттеры и геттеры -setProperty и -property.

Путем последовательного присвоения свойства непосредственно при использовании + new автор использует синтаксис, чтобы подчеркнуть, что это «обнаженный» объект. Пустой. Самый низкий минимум. Затем он обязательно назначит его, не вызывая сеттера. Это кажется хорошей идеей. В конце концов, объединение + new и пользовательский установщик может привести к проблемам, если пользовательская реализация установщика предполагает что-либо о состоянии инициализированного объекта (например, что-то, что могло быть сделано в методе custom -init). Лучше избежать проблемы. Ах. Вот оно Ответ, который я искал.

Так что же я могу, в своем рваном состоянии нуби, взять из этого «стиля кодирования». Хммм ... что придется тушить некоторое время. Возьмите номер 1:

  1. Вызов +new и отказ от любых пользовательских сеттеров являются защитным кодированием.
  2. Настройка -init и установки по умолчанию должны быть выполнены с волновало.
  3. Если требуется пользовательский метод -init, может быть лучше переименовать это -initWithDefaults или что-то. С другой стороны, если вы последовательно используйте +new с назначением без вызова self, тогда вы возможно, сойдет с рук больше настроек, но вам придется быть последовательным.

Я достаточно взрослый, чтобы знать, что я непоследователен. Охота на ботинок происходит, по крайней мере, один раз в неделю, несмотря на некоторые усилия с моей стороны. Поэтому мне нужен стиль кодирования, который является защитным. Для этого я должен сделать оба: 1) развить любовь к + с прямым присваиванием, когда нужен голый объект, и 2) попытаться избежать переопределения стандартных реализаций init, а также синтезированных сеттеров и геттеров.

Как говорит Томас:

'есть некоторые побочные эффекты. Если позже вы заметите, что вам нужно специальное поведение внутри либо получателя, либо установщика (например: вызывая другие методы или проверяя значения: NSString который только должен содержать адреса электронной почты), то вам нужно только переписать геттер или сеттер. Если вы не используете self.myProp = ... тогда Вы должны искать использование и изменить этот фрагмент кода как хорошо ".

Достаточно справедливо. Если я не буду настраивать сеттеры и геттеры, мне придется убедиться, что мое дополнительное поведение происходит где-то еще. Но, на самом деле, я уже склонен делать это путем реализации таких вещей, как -changeLocationTo: (CLLocation *) aPlace inTimeZone: (NSTimeZone *) timeZone '. Там идет проверка, и совершенно очевидно, что она делает с именами, и ее существование напоминает мне, что когда я меняю aPlace, я также хочу убедиться, что я проверяю его timeZone. Я звоню по умолчанию self.setTimeZone и self.setAPlace оттуда и делаю любую очистку. Начало стиля. Но у этого, вероятно, есть некоторые недостатки ...

...