Home > OS >  NSNetService delegates not being called
NSNetService delegates not being called

Time:08-12

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?

CodePudding user response:

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

CodePudding user response:

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?

CodePudding user response:

I've just run into this problem and I was already retaining the NSNetService object so that wasn't the reason.

Turns it out it was because the access levels of the delegate methods I defined wasn't matching the access level of the class (the class was public while the delegate methods were internal). And because all of the delegate methods are optional, the compiler was just giving a silent warning.

  • Related