Предупреждение в примере ITunesFinder (Apress - Learning Obj-C) - PullRequest
0 голосов
/ 08 октября 2009

Когда я компилирую код ниже, я получаю следующее предупреждение: Несовместимый тип отправляет "ITunesFinder *" ожидаемый "id"? Я только начинаю и, честно говоря, немного смущен этим примером. Мне было бы интересно узнать, есть ли способ написать этот пример без использования класса делегата?

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

вот код ...

// INTERFACE
#import <Cocoa/Cocoa.h>
@interface ITunesFinder : NSObject
@end

.

// IMPLEMENTATION
#import "ITunesFinder.h"
@implementation ITunesFinder
-(void) netServiceBrowser: (NSNetServiceBrowser *) b
           didFindService: (NSNetService *) service
               moreComing: (BOOL) moreComing {

    [service resolveWithTimeout:10];
    NSLog(@"Service Found: %@", [service name]);
}

-(void) netServiceBrowser: (NSNetServiceBrowser *) b
         didRemoveService: (NSNetService *) service
               moreComing: (BOOL) moreComing {
    [service resolveWithTimeout:10];
    NSLog(@"Service Lost!: %@", [service name]);
}
@end

.

// MAIN
#import <Foundation/Foundation.h>
#import "ITunesFinder.h"

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    NSNetServiceBrowser *browser = [[NSNetServiceBrowser alloc] init];
    ITunesFinder *finder = [[ITunesFinder alloc] init];

    NSLog(@"iTunesFinder ... Start");
    [browser setDelegate: finder]; // <<< Warning here !!!!
    [browser searchForServicesOfType: @"_daap._tcp" inDomain:@"local."];
    NSLog(@"Browsing ...");

    [[NSRunLoop currentRunLoop] run];

    // Clean up
    [browser release];
    [finder release];
    [pool drain];
    return 0;
}

Любые указатели / мудрость будут высоко оценены.

* 1016 Гэри *

1 Ответ

4 голосов
/ 08 октября 2009

Когда я попытался скомпилировать это под 10.6 с помощью gcc 4.2.1, он скомпилировал следующее предупреждение:

main.m:12: warning: class 'ITunesFinder' does not implement the 'NSNetServiceBrowserDelegate' protocol

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

@interface ITunesFinder : NSObject<NSNetServiceBrowserDelegate>

Причина, по которой было выдано предупреждение, заключается в том, что метод setDelegate: имеет следующую подпись:

- (void)setDelegate:(id <NSNetServiceBrowserDelegate>)delegate;

, что просто означает, что он может принимать любой объект, реализующий формальный протокол NSNetServiceBrowserDelegate. Так как ваш интерфейс класса явно не объявил это, компилятор предупреждает вас об этом. Он все еще должен работать во время выполнения, при условии, что фактические методы предоставляются, когда сообщения делегата действительно отправляются.

возможно ли написать этот пример без использования класса делегата?

Нет, класс делегатов - это способ получения уведомлений о событиях.

Я также немного смущен реализацией класса, книга не описывает, на чем это основано, или, в этом отношении, что делают Категории, Протоколы или Делегаты, и как они работают.

Протокол NSNetServiceBrowserDelegate определяет набор методов, которые должен реализовать ваш класс. Вы можете думать об этом как об интерфейсе в Java или виртуальном базовом классе в C ++. Разница в Objective-C (который не поддерживает множественное наследование) состоит в том, что вы не наследуете от интерфейса, который пытаетесь реализовать, вы просто объявляете тот факт, что ваш конкретный класс реализует эти методы в соответствии с протоколом.

Теперь протоколы используются для разных целей, и в Какао очень распространенным является использование их для обратных вызовов. Итак, ваш ITunesFinder реализует протокол браузера таким образом, что NSNetServiceBrowser знает, как вызывать ваш класс (которого он никогда раньше не видел!), Чтобы предоставлять уведомления браузера.

Эти делегаты часто используются для делегирования поведения от базового класса одному из ваших классов, чтобы позволить вам легко настраивать вещи без большого количества подклассов, и получать уведомления о событиях (обычно до и после чего-то интересного). Это очень элегантная модель.

Документация Apple на эту тему очень хороша:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...