2013-01-07 4 views
2

Я подклассифицирую UIToolbar, потому что я буду использовать его во всем приложении. UIToolbar использует протокол делегата:issue with ivar

// 
// UIToolbarCustom.h 
// 

#import <UIKit/UIKit.h> 

@protocol UIToolbarCustomDelegate 

@required 
- (void)tab:(UIBarButtonItem *)sender; 
- (void)ok:(UIBarButtonItem *)sender; 

@end 

@interface UIToolbarCustom : UIToolbar { 

    id <UIToolbarCustomDelegate> delegate; 

} 

@property (strong, nonatomic) id delegate; 

@end 

Standford учитель курс развития IOS рекомендует явно объявить все Ивар префиксом с подчеркиванием, как:

@implementation UIToolbarCustom 

@synthesize delegate = _delegate; 

@end 

Но в этом указать scenarion дает меня ошибка:

error: property 'delegate' attempting to use ivar '_delegate'... 

код работает нормально, если я использую:

@synthesize delegate = __delegate; or 
@synthesize delegate; 

Что здесь происходит? Есть ли переменная частного экземпляра в классе UIToolbar с именем _delegate?

UPDATE

Спасибо все, что вы, ребята, для всех уточнений и protips, я многому учусь. Оказывается, что я новичок в разработке iOS (это моя первая вторая версия приложения, поэтому я пытаюсь сделать это правильно = p). После кончиков я вышел с этим новым файлом заголовок:

// 
// Toolbar.h 
// 

#import <UIKit/UIKit.h> 

@protocol ToolbarDelegate 

@required 
- (void)tab:(UIBarButtonItem *)sender; 
- (void)ok:(UIBarButtonItem *)sender; 

@end 

@interface Toolbar : UIToolbar 

@property (strong, nonatomic) id delegate; 

@end 

Примечание:

  1. Приставка класса была удалена.

  2. Объявление делегата было удалено (я использую код учебника делегата ios, но пример кода использует старую версию xcode, где требуется объявление).

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

PS: Очевидно, что код не работает, так как проблема с ivar. Я собираюсь изменить свои имена, так что мне не нужно, чтобы синтезировать его, не зная о том, что имя для использования в любом случае ...

+0

Совет. Когда вы подклассифицируете класс UIKit, измените префикс от пользовательского интерфейса на любой префикс, который вы используете для своих собственных классов. Это облегчает определение ваших собственных занятий сразу, делает более правдоподобным именование вещей (например, вы можете использовать * LLToolbar * вместо * UIToolbarCustom *), и (что наиболее важно), это позволяет избежать того, что Apple добавит класс с то же имя. Избегание конфликтов имен является основной причиной того, что префиксы используются в первую очередь. – Caleb

+0

Спасибо за отзыв, я сделаю это! – lolol

ответ

5

What is going on here? Is there a private instance variable in the UIToolbar class named _delegate?

Да, это именно проблема. Вам нужно указать другое имя для вашей переменной экземпляра. __delegate будет работать, или вы можете префикс имени с 3-буквенным префиксом (см. Последний абзац).

Обратите внимание, что вы объявили свой ivar как delegate, а затем в заявлении о синтезе сказали компилятору использовать _delegate. Эффективно это означает, что ваш delegate ivar вообще не используется. В любом случае, если вы пишете для iOS (в отличие от 32-разрядного Mac), как и вы, вам не нужно объявление явного объявления экземпляра в разделе @interface вашего подкласса, поскольку компилятор автоматически создаст его для вы.

Наконец, это плохая форма, чтобы называть ваш собственный подкласс тем, что начинается с «UI», поскольку префикс пользовательского интерфейса зарезервирован для классов, которые являются частью UIKit. Вместо этого вы должны использовать свой собственный 3-буквенный префикс или вообще не использовать префикс. Проблема в том, что будущая версия UIKit могла бы включать в себя класс под названием «UIToolbarCustom», и ваш подкласс столкнулся бы с ним.

+0

Это не совсем правильно ... он сталкивается со своим предыдущим объявлением, а не с частным/внутренним Apple ivar (который не будет сталкиваться, потому что они используют другое соглашение ivar). – isaac

+2

Опять же, это неправда. И, если вы не верите, что можете столкнуться с частным/внутренним Apple ivar, попробуйте подклассифицировать UIViewController и создать свойство под названием «popoverController» с его поддерживающим ivar с именем '_popoverController'. Вы получите точную ошибку, которую описывает OP. Как вы можете видеть, глядя на UIToolbar.h, UIToolbar действительно имеет свою собственную переменную экземпляра, называемую '_delegate'. –

+0

Не то, чтобы я не верю, что вы не можете столкнуться, очевидно, это возможно. Мое понимание и то, чему меня учили, состояло в том, что предшествующее соглашение о конце концов было введено для сторонних разработчиков специально, чтобы избежать столкновения с внутренними иварами. Поэтому мое удивление в этом случае ... – isaac

1

С прошлого года, когда вышел Xcode 4.3, вам не нужно синтезировать свои свойства. Это делается для вас компилятором (генерируется ivar, а к его имени добавляется главное подчеркивание). Это означает, что вам также не нужно объявлять ивара. Если вы это сделаете, обязательно назовите его чем-то иным, чем _delegate.

Таким образом, все, что вам действительно нужно это строка:

@property (strong, nonatomic) id<UIToolbarCustomDelegate> delegate; 

UPDATE: смотрите в Andrew Madsen's answer для полного рассказа. Оказывается, UIToolbar имеет свой собственный ivar по имени _delegate. Кто знал!

+0

Это правда, но компилятор будет синтезировать переменную экземпляра, называемую '_delegate', и она будет сталкиваться точно так же. –

+0

Правда. Думаю, вам не нужно объявлять об этом иваре. Я обновил свой ответ, чтобы объяснить это немного лучше. – Macondo2Seattle

+0

В качестве решения это работает, но он не в полной мере объясняет спрошенному, почему его код не работает - причина в том, что он объявлял ivar и свойство с тем же именем. – isaac