Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSNetService delegates not being called

I'm trying to resolve a NSNetService (named "My_Mac") to an IP in a background app with this code:

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

And in the same class, I have these delegate methods defined:

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

Here's the strange part: neither delegate methods get called unless I run a NSAlert after "[service resolveWithTimeout:5];". Any ideas?

like image 844
K_T Avatar asked Dec 25 '09 03:12

K_T


2 Answers

If you are using ARC you need to retain the service object somewhere. In your example, the service object most likely goes out of scope and is not referenced anywhere else in your code, so the compiler will try to release it immediately after the resolve call.

Add a property:

@property (nonatomic, strong) NSMutableArray *services;

In your delegate, or wherever you use 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];
}

Don't forget to stop and release those services once you're finished or getting rid of the delegate:

for (NSNetService* service in self.services) {
    [service stop];
}
[self.services removeAllObjects];
like image 112
utopalex Avatar answered Sep 20 '22 18:09

utopalex


I'm not sure, but it looks like the request is not actually scheduled in a run loop for some reason. Maybe try something like this to schedule it?

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];

Stupid question, but are you explicitly implementing NSServiceDelegate protocol or just have the methods?

EDIT: I had another thought that this might be some kind of race condition (a more likely scenario). Delegates are usually weak references. If your object is dropping out of scope and being autoreleased, the system would end up with a nil handle and be firing the messages to nil. In the case where you show an NSAlert (or do other work) your object might be hanging around just long enough for it to get the messages fired back to it. Could you confirm your object sticks around for the full 8 seconds?

like image 30
slf Avatar answered Sep 18 '22 18:09

slf