Почему делает этот пример кода на dev сайте Apple, объявляют три интерфейса для того же класса?

Я погружаюсь в разработку 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

Я вижу, что каждый интерфейс отличается, но укажите то же имя класса.

  1. Какова причина этого?
  2. Я также заметил это то же поведение в других примерах кода, только вместо того, чтобы объявить несколько интерфейсов в заголовочном файле, Вы будете видеть дополнительный @interface блок, объявленный к вершине.m файла реализации, обычно выше @implementation блока. Почему?

Большое спасибо заранее для Вашей мудрости!

8
задан BeachRunnerFred 28 July 2010 в 15:23
поделиться

4 ответа

Они называются Категории , и вы можете увидеть их в скобках после имени класса.

Они используются для группировки методов в куски вместо того, чтобы объединять их все в одну большую группу. Их также можно разместить отдельно от объявления основного класса. Это особенно полезно в файлах .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

Обратите внимание, что вы не можете добавлять переменные экземпляра с категорией.

9
ответ дан 5 December 2019 в 11:22
поделиться

По порядку:

Первое объявление интерфейса - это фактическое объявление интерфейса, которое объявляет класс как подкласс 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 вверху, если у меня есть методы, которые следует использовать только из класса. Однако учтите, что это всего лишь ограничение по времени компиляции. Нет ничего, что могло бы помешать кому-либо послать сообщение о расширении класса во время выполнения.

1
ответ дан 5 December 2019 в 11:22
поделиться

Это не определение интерфейса 3 раза - интерфейс только один.

то, что вы видите, - это категории, которые добавляют методы к классу

Существует базовый интерфейс, который определяет атрибуты и некоторые методы - есть только один из них, и он определяет, как объект хранится в памяти и является только один, который нужен.

Objective C ищет методы во время выполнения. Эти методы не нужно находить во время компиляции и, следовательно, не нужно объявлять в заголовках / интерфейсах и т. Д. Если они не объявлены и вы вызываете их код, вы получите предупреждения во время компиляции.

В этом случае одна категория с пустым именем используется для частных функций. Я обычно помещаю этот интерфейс только в файл .m класса, поэтому он не отображается для другого кода, как не в заголовке.

Вторая категория - это добавление методов, обеспечивающих соответствие SessionManager протоколу GKVoiceChatClient. Обычно это делается для того, чтобы сгруппировать код, охватывающий определенное поведение.

Другой причиной использования категорий является добавление методов к существующему классу, например NSString - вы можете создать свою собственную категорию, добавляя методы без подкласса класса, как вы должны делать во многих других объектно-ориентированных языках, включая Java и C ++

4
ответ дан 5 December 2019 в 11:22
поделиться

Это сделано для поддержания кода, я верю ...легче просматривать различные помеченные интерфейсы, например (VoiceManager), который предназначен для настройки голосового менеджера и методов, связанных с этим, и у вас есть один интерфейс, имеющий дело с методами делегата GK и любым взаимодействием с gamekit, которое будет ... вместо того, чтобы смотреть на один огромный файл интерфейса и выбирать то, что вы ищете ... Они также могут разделять реализации таким образом, чтобы было легче просматривать и перемещаться.

1
ответ дан 5 December 2019 в 11:22
поделиться