12

我正在尝试使用以下代码将 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,否则不会调用委托方法。有任何想法吗?

4

3 回答 3

31

如果您使用 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];
于 2013-04-21T11:15:18.513 回答
10

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

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 秒吗?

于 2009-12-25T05:21:41.910 回答
0

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

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

于 2018-10-14T10:25:51.130 回答