【问题标题】:NSNetService delegates not being calledNSNetService 委托未被调用
【发布时间】:2010-12-29 22:38:56
【问题描述】:

我正在尝试使用以下代码将 NSNetService(名为“My_Mac”)解析为后台应用程序中的 IP:

NSNetService *service = [[NSNetService alloc] initWithDomain:@"local." type:@"_daap._tcp" name:@"My_Mac"];
[service setDelegate:self];
[service resolveWithTimeout:5];

在同一个类中,我定义了这些委托方法:

- (void)netServiceDidResolveAddress:(NSNetService *)sender
- (void)netService:(NSNetService *)sender didNotResolve:(NSDictionary *)errorDict

这是奇怪的部分:除非我在“[service resolveWithTimeout:5];”之后运行 NSAlert,否则不会调用委托方法。有什么想法吗?

【问题讨论】:

    标签: objective-c cocoa bonjour


    【解决方案1】:

    我不确定,但由于某种原因,请求实际上并未安排在运行循环中。也许尝试像this 来安排它?

    NSNetService *service = [[[NSNetService alloc] initWithDomain:@"local." type:@"_daap._tcp." name:@"My_Mac"] autorelease];
    [service setDelegate:self];
    [service scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:@"PrivateMyMacServiceMode"];
    [service resolveWithTimeout:8.0];
    

    愚蠢的问题,但你是明确实现NSServiceDelegate 协议还是只有方法?

    编辑:我有另一个想法,这可能是某种竞争条件(更可能的情况)。委托通常是弱引用。如果您的对象退出范围并被自动释放,系统将最终得到一个 nil 句柄并将消息触发为 nil。在您显示 NSAlert(或执行其他工作)的情况下,您的对象可能会停留足够长的时间以使其能够将消息返回给它。你能确认你的物体停留了整整 8 秒吗?

    【讨论】:

    • 感谢 slf 的回复。我尝试了您拥有的 NSRunLoop 代码,但没有骰子。我只有这些方法,因为我的目标是 10.5,它没有定义正式的 NSServiceDelegate 协议。
    • slf:你说得对——我关闭了 GC 以确保对象仍然存在,并且调用了委托。现在我只需要追踪它被自动发布的位置,因为我已经明确尝试保留它,但没有奏效。感谢您为我指明正确的方向!
    • 看似复杂的问题的解决方案通常比您最初想象的要简单:)
    • resolveWithTimeout 之后对NSNetService 对象的显式保留也为我解决了同样的问题。我是 iPhone 开发的新手,但该死的!像这样的东西很烦人。我想 Mac/iPhone 编程的座右铭应该是“它就是行不通”。
    • 我只是在 ViewDidLoad 中创建 serviceBrowser 对象,而没有在控制器中将其作为属性引用!所以这导致对象在方法范围之后被丢弃并释放。
    【解决方案2】:

    如果您使用 ARC,则需要在某处保留服务对象。 在您的示例中,服务对象很可能超出范围并且没有在代码中的其他任何地方引用,因此编译器将尝试在解析调用后立即释放它。

    添加属性:

    @property (nonatomic, strong) NSMutableArray *services;
    

    在你的委托中,或者你使用 NSNetService 的任何地方

    - (void)netServiceBrowser:(NSNetServiceBrowser *)browser
               didFindService:(NSNetService *)aNetService
                   moreComing:(BOOL)moreComing
    {
        if (!self.services) {
            self.services = [[NSMutableArray alloc] init];
        }
        [self.services addObject:aNetService];
        [aNetService setDelegate:self];
        [aNetService resolveWithTimeout:3.0];
    }
    

    完成或摆脱委托后,不要忘记停止并释放这些服务:

    for (NSNetService* service in self.services) {
        [service stop];
    }
    [self.services removeAllObjects];
    

    【讨论】:

    • 保持有效。但是 NSNetServiceDelegate 方法签名中的 NSNetService 参数不是保留对象吗?例如发件人- (void)netServiceDidResolveAddress:(NSNetService *)sender
    【解决方案3】:

    我刚刚遇到了这个问题,我已经保留了NSNetService 对象,所以这不是原因。

    原来是因为我定义的委托方法的访问级别与class 的访问级别不匹配(classpublic,而委托方法是internal)。而且因为所有的委托方法都是可选的,编译器只是给出了一个无声的警告。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-09
      • 1970-01-01
      相关资源
      最近更新 更多