objective-c - iTunesFinder 示例中的警告(Apress - 学习 Obj-C)

标签 objective-c cocoa

当我编译下面的代码时,我收到以下警告:发送“ITunesFinder *”预期“id”的类型不兼容?我才刚刚开始,说实话,我对这个例子有点困惑。我有兴趣知道是否有一种方法可以在不使用委托(delegate)类的情况下编写此示例?

我对类的实现也有点困惑,这本书没有描述它是基于什么,也没有描述类别、协议(protocol)或委托(delegate)的作用,也没有描述它们是如何工作的。

这是代码...

// 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;
}

任何指示/智慧将不胜感激。

加里

最佳答案

当我尝试在 10.6 下使用 gcc 4.2.1 编译此文件时,它编译时出现以下警告:

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

我怀疑这与您描述的问题相同,但来自编译器的更具描述性的诊断(可能比您的版本更新?)。您可以通过将协议(protocol)添加到 header 中的接口(interface)声明来解决此警告:

@interface ITunesFinder : NSObject<NSNetServiceBrowserDelegate>

发出警告的原因是 setDelegate: 方法具有以下签名:

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

这仅仅意味着它可以采用任何实现正式 NSNetServiceBrowserDelegate 协议(protocol)的对象。由于您的类接口(interface)没有显式声明这一点,因此编译器会警告您这一事实。只要在实际发送委托(delegate)消息时提供实际方法,它应该仍然可以在运行时工作。

is it possible to write this example without using the delegate class?

不,委托(delegate)类是您接收事件通知的方式。

I am also a little confused by the class implementation, the book does not describe what this is based on, or for that matter what Categories, Protocols or Delegates do, nor how they work.

NSNetServiceBrowserDelegate 协议(protocol)定义了您的类需要实现的一组方法。您可以将其视为 Java 中的接口(interface)或 C++ 中的虚拟基类。 Objective-C(不支持多重继承)的区别在于,您不从您尝试实现的接口(interface)继承,您只需声明您的特定类根据协议(protocol)实现这些方法。

现在协议(protocol)被用于各种各样的事情,Cocoa 中一个非常常见的模式是将它们用于回调。因此,在这里,您的 ITunesFinder 正在以某种方式实现浏览器协议(protocol),以便 NSNetServiceBrowser 知道如何调用您的类(它以前从未见过!),以便提供浏览器通知。

这些委托(delegate)通常用于将行为从框架类委托(delegate)给您的某个类,以便您可以轻松地自定义事物而无需进行大量子类化,并接收事件通知(通常是在某些有趣的事情之前和之后)。这是一个非常优雅的模型。

Apple 文档在这个主题上非常好:

关于objective-c - iTunesFinder 示例中的警告(Apress - 学习 Obj-C),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1537084/

相关文章:

ios - Objective-C 中 FOR 循环的奇怪行为

ios - 在类中添加 NavigationController 而不是在 appdelegate 中

objective-c - 以毫秒为单位获取当前时间 Cocos2d

cocoa - 如何更改UIKit UIImage :drawInRect method to AppKIt NSImage:drawInRect Method

iphone - 内存管理——什么时候释放?

ios - 我如何实现 `prepareForReuse` ?

xcode - 如何在不包含 Mac OS X 10.6 SDK 的 Xcode 版本中构建它

objective-c - 根据 AppleScript,Cocoa 应用程序不包含菜单栏

objective-c - 运行具有提升权限的进程 OS X 10.7 & 10.8

objective-c - NSPredicateEditor & NSExpression - 显示可以不同于谓词的值吗?