Я погружаюсь в разработку iOS при попытке схватить Objective C, и я нахожусь все еще в той фазе, где, когда-либо где я смотрю, я вижу вещи, которые не имеют никакого смысла программисту ветерана C как я. В этом примере Game Kit на dev сайте Apple один из заголовочных файлов объявляет интерфейс класса, три различных раза...
@interface SessionManager : NSObject {
NSString *sessionID;
GKSession *myGKSession;
NSString *currentConfPeerID;
NSMutableArray *peerList;
id lobbyDelegate;
id gameDelegate;
ConnectionState sessionState;
}
@property (nonatomic, readonly) NSString *currentConfPeerID;
@property (nonatomic, readonly) NSMutableArray *peerList;
@property (nonatomic, assign) id lobbyDelegate;
@property (nonatomic, assign) id gameDelegate;
- (void) setupSession;
- (void) connect:(NSString *)peerID;
- (BOOL) didAcceptInvitation;
- (void) didDeclineInvitation;
- (void) sendPacket:(NSData*)data ofType:(PacketType)type;
- (void) disconnectCurrentCall;
- (NSString *) displayNameForPeer:(NSString *)peerID;
@end
// Class extension for private methods.
@interface SessionManager ()
- (BOOL) comparePeerID:(NSString*)peerID;
- (BOOL) isReadyToStart;
- (void) voiceChatDidStart;
- (void) destroySession;
- (void) willTerminate:(NSNotification *)notification;
- (void) willResume:(NSNotification *)notification;
@end
@interface SessionManager (VoiceManager)
- (void) setupVoice;
@end
Я вижу, что каждый интерфейс отличается, но укажите то же имя класса.
Большое спасибо заранее для Вашей мудрости!
Они называются Категории , и вы можете увидеть их в скобках после имени класса.
Они используются для группировки методов в куски вместо того, чтобы объединять их все в одну большую группу. Их также можно разместить отдельно от объявления основного класса. Это особенно полезно в файлах .m, где вам может потребоваться создать служебные методы для вашего класса, но вы не хотите, чтобы они были видимы для других объектов по какой-либо причине (поэтому вы не помещаете их в .h, который является импортированы другими классами). Другое распространенное использование - группирование методов, которые соответствуют определенной логической категории , неформальному протоколу или тому, что у вас есть. Категории могут быть названы ( @interface MyClass (MyCategory)
) или анонимными ( @interface MyClass ()
). Последний обычно используется для общих частных методов в вашем заголовке.
(Причина, по которой вам нужны категории для объявления частных методов в вашем .m, состоит в том, чтобы компилятор знал о методах - в противном случае вы получите предупреждение, когда попытаетесь вызвать такой метод.)
Кроме того, вы могут использовать категории для добавления методов к существующим классам. Например, UIKit содержит категорию на NSString под названием NSString (UIStringDrawing). Или, если вы хотите создать свою собственную:
@interface NSString (MyFoo)
+ (NSString *)fooString;
@end
//... somewhere else...
@implementation NSString (MyFoo)
+ (NSString *)fooString { return @"foo!"; }
@end
Обратите внимание, что вы не можете добавлять переменные экземпляра с категорией.
По порядку:
Первое объявление интерфейса - это фактическое объявление интерфейса, которое объявляет класс как подкласс NSObject и реализует протокол GKSessionDelegate. Он также объявляет переменные экземпляра и набор методов.
Второе объявление интерфейса - это расширение класса. Это можно рассматривать как своего рода анонимную категорию. Так что мы пока пропустим его и вернемся к нему.
Третий интерфейс - это объявление категории. Категории позволяют делать две вещи. Они позволяют разделить реализацию класса на несколько исходных файлов. В приведенном выше примере у вас будет
@implementation SessionManager
// methods declared in the first @interface
@end
@implementation SessionManager(VoiceManager)
// methods declared in the third @interface
@end
. Две реализации @ не обязательно должны находиться в одном исходном файле.
Еще одна вещь, которую может сделать категория, - это позволить вам расширять уже существующие классы. @interface NSString (MyStringMethods) ...
Возвращаясь к расширению класса, это немного похоже на анонимную категорию. Реализации объявленных в нем методов должны находиться в основном блоке @implementation
. Цель расширения класса - позволить вам объявить частный API отдельно от файла заголовка класса. Я обычно помещаю один в файл.m вверху, если у меня есть методы, которые следует использовать только из класса. Однако учтите, что это всего лишь ограничение по времени компиляции. Нет ничего, что могло бы помешать кому-либо послать сообщение о расширении класса во время выполнения.
Это не определение интерфейса 3 раза - интерфейс только один.
то, что вы видите, - это категории, которые добавляют методы к классу
Существует базовый интерфейс, который определяет атрибуты и некоторые методы - есть только один из них, и он определяет, как объект хранится в памяти и является только один, который нужен.
Objective C ищет методы во время выполнения. Эти методы не нужно находить во время компиляции и, следовательно, не нужно объявлять в заголовках / интерфейсах и т. Д. Если они не объявлены и вы вызываете их код, вы получите предупреждения во время компиляции.
В этом случае одна категория с пустым именем используется для частных функций. Я обычно помещаю этот интерфейс только в файл .m класса, поэтому он не отображается для другого кода, как не в заголовке.
Вторая категория - это добавление методов, обеспечивающих соответствие SessionManager протоколу GKVoiceChatClient. Обычно это делается для того, чтобы сгруппировать код, охватывающий определенное поведение.
Другой причиной использования категорий является добавление методов к существующему классу, например NSString - вы можете создать свою собственную категорию, добавляя методы без подкласса класса, как вы должны делать во многих других объектно-ориентированных языках, включая Java и C ++
Это сделано для поддержания кода, я верю ...легче просматривать различные помеченные интерфейсы, например (VoiceManager), который предназначен для настройки голосового менеджера и методов, связанных с этим, и у вас есть один интерфейс, имеющий дело с методами делегата GK и любым взаимодействием с gamekit, которое будет ... вместо того, чтобы смотреть на один огромный файл интерфейса и выбирать то, что вы ищете ... Они также могут разделять реализации таким образом, чтобы было легче просматривать и перемещаться.