How to handle setDelegate: when using multipe streams

I ran into the problem of using a third-party library, and I'm not sure what a common template is to solve it.

I am using the asi-http-request class, which asynchronously retrieves HTTP objects using a stream.

In my objects, the dealloc () method, I do

[request setDelegate:nil];
[request release];

However, the delegate sometimes calls the call after this has happened. (I see when this happens, the delegate field of the request object is nil.) This sometimes fails if the delegate has already been destroyed.

I think this is a race condition. The code from ASIHTTPRequest that calls the delegate looks like this:

// Let the delegate know we are done
if ([self didFinishSelector] && [[self delegate] respondsToSelector:[self didFinishSelector]]) {
    [[self delegate] performSelectorOnMainThread:[self didFinishSelector] withObject:self waitUntilDone:[NSThread isMainThread]];
}

The problem occurs if the calling (but not completed) executor of SelectorOnMainThread is called when the setDelegate call occurs on the main thread.

'didFinishSelector', ( ), - , , .

:

http://groups.google.com/group/asihttprequest/browse_thread/thread/721220b9645f4a42

"" !

0
2

( 'didFinishSelector', , - , ) , apple dev

https://devforums.apple.com/message/255935#255935

, , :

- (void)callSelectorCallback:(SEL *)selectorPtr withTarget:(id *)targetPtr
{
    id target = *targetPtr;
    SEL selector = *selectorPtr;

    if (!selector || !target)
        return;

    if ([target respondsToSelector:selector])
    {
        [target performSelector:selector withObject:self];
    }
}

- (void)callSelector:(SEL *)selector withDelegate:(id *)target
{
    if (!*selector || !*target)
        return;

    SEL callback = @selector(callSelectorCallback:withTarget:);
    NSMethodSignature *signature = [ASIHTTPRequest instanceMethodSignatureForSelector:callback];
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
    [invocation setSelector:callback];
    [invocation setTarget:self];
    [invocation setArgument:&selector atIndex:2];
    [invocation setArgument:&target atIndex:3];

    [invocation performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:[NSThread isMainThread]];
}

, , :

[self callSelector:&didFinishSelector withDelegate:&delegate];

( setDelegate ), 100% . non-main thread setDelegate, callSelectorCallback.

+2

. ,

id delegate = [[self delegate] retain];
if ([self didFinishSelector] && [delegate respondsToSelector:[self didFinishSelector]]) {
    [delegate performSelectorOnMainThread:[self didFinishSelector]
                               withObject:self 
                            waitUntilDone:[NSThread isMainThread]];
}
[delegate release];

[self delegate] , , Apple @synthesized , , ,

[[delegate retain] autorelease];

, !

+1

Source: https://habr.com/ru/post/1753959/


All Articles