2009-12-25 18 views
11

que estoy tratando de resolver un NSNetService (llamado "My_Mac") a una IP en una aplicación de fondo con este código:delegados NSNetService no ser llamado

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

Y en la misma clase, tengo estos delegado los métodos definidos:

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

Aquí es la parte extraña: ni los métodos de delegado consiguen llamados a no ser que corro un NSAlert después de "[resolveWithTimeout servicio: 5];". ¿Algunas ideas?

Respuesta

9

No estoy seguro, pero parece que la solicitud no está realmente programada en un ciclo de ejecución por algún motivo. Tal vez intente algo como this para programarlo?

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

Pregunta estúpida, pero están implementando de manera explícita NSServiceDelegate protocolo o apenas tiene los métodos?

EDIT: tuve otra idea de que esto podría ser algún tipo de condición de carrera (un escenario más probable). Los delegados suelen ser referencias débiles. Si su objeto está cayendo fuera del alcance y se libera automáticamente, el sistema terminaría con un manipulador nulo y dispararía los mensajes a cero. En el caso en que muestre un NSAlert (u otro trabajo), su objeto podría estar colgando el tiempo suficiente para que los mensajes vuelvan a activarse. ¿Podrías confirmar que tu objeto permanece durante los 8 segundos completos?

+0

Gracias por la respuesta slf. Probé el código NSRunLoop que tenías, pero no los dados. Acabo de tener los métodos, ya que estoy apuntando a 10.5, que no tiene definido el protocolo formal NSServiceDelegate. –

+2

slf: tiene razón: apagué el GC para asegurarme de que el objeto aún estaba allí y se llamó a los delegados. Ahora solo tengo que rastrear dónde está siendo lanzado automáticamente, ya que he intentado retenerlo explícitamente, y eso no funcionó. ¡Gracias por señalarme en la dirección correcta! –

+0

la solución a problemas aparentemente complejos suele ser más simple de lo que piensas :) – slf

23

Si está utilizando ARC necesita retener el objeto de servicio en alguna parte. En su ejemplo, el objeto de servicio probablemente se salga del alcance y no se mencione en ningún otro lugar en su código, por lo que el compilador intentará liberarlo inmediatamente después de la llamada de resolución.

Añadir una propiedad:

@property (nonatomic, strong) NSMutableArray *services; 

En su delegado, o donde se utiliza 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]; 
} 

No se olvide de parar y liberar esos servicios una vez que haya terminado o deshacerse de el delegado:

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

esto funcionó para mí! – joshblour

+0

reteniéndolo funciona. ¿Pero el parámetro NSNetService en las firmas de método NSNetServiceDelegate no retiene el objeto? p.ej. ** remitente ** en '- (void) netServiceDidResolveAddress: (NSNetService *) remitente' – snowbound

Cuestiones relacionadas