ARC없이 Xcode에서 스레드를 전환 할 때 내 객체가 자체적으로 할당 해제 된 이유는 무엇입니까?

첸 리 용

다음과 같은 개체가 있습니다.

typedef void (^ Completion) (Response *);

// Response class
@interface Response : NSObject {
    NSDictionary * kdata;
}
- (id)initWithJson:(NSDictionary *)data;
@property (nonatomic, assign) NSDictionary * data;
@end

@implementation Response
- (id)initWithJson:(NSDictionary *)data { kdata = data; }
- (NSDictionary *) data                 { return kdata; }
- (void) setData: (NSDictionary *)data  { kdata = data; }
- (NSDictionary *) msg                  { return kdata[@"msg"]; }
@end


// inside a networking class X implementation
- (void) doSomething:(completionBlock)completion {
    NSDictionary * json = // get from networking function, which will always have key "msg".
    Response * responseObj = [[Response alloc] initWithJson:json];
    dispatch_async(dispatch_get_main_queue(), ^{
        if (completion != nil) { completion (responseObj); }
    });
}


// inside caller method
[X doSomething:^(Response * response) {
    NSLog (@"%@", [response msg]);
}

이 코드는 액세스시 오류를 발생 kdata[@"msg"]시킵니다. 디버그에서 개체가 사전에 키가 포함 된 상태로 제대로 초기화되었음을 확신하더라도 "msg". 내가 객체를 디버깅 할 때 조사 식 창에, 그것은 KDATA 데이터 형식에서 변화 계속 저를 보여주고 NSArrayM, NSSet, NSDictionary, 등 그 내용도 계속 변경. 나는 심지어 retain호출 할 때 키워드를 추가 completion ([responseObj retain]);하지만 여전히 오류가 발생합니다.

그러나 클래스 X의 코드가 다음과 같이 변경되면 :

// inside a networking class X implementation
- (void) doSomething:(completionBlock)completion {
    NSDictionary * json = // get from networking function, which will always have key "msg".
    Response * responseObj = [[Response alloc] initWithJson:json];
    if (completion != nil) { completion (responseObj); } // here is the change, no more switching to main thread
}

// inside caller method - no change here
[X doSomething:^(Response * response) {
    NSLog (@"%@", [response msg]);
}

코드는 완벽하게 작동합니다. 왜 그럴까요? 이것은 ARC없이 Xcode에 내장되어 있습니다.

편집 : 누군가가 초기화에 대해 언급했습니다. 이것은 위에서 작성된 것이 정확히 내 코드가 아니라는 내 실수이며 init 메소드를 잘못 복사합니다. 이것은 내 초기화 방법입니다.

- (instancetype) initWithData:(NSDictionary *)freshData {
    NSParameterAssert(freshData); // make sure not nil
    self = [super init];
    if (self) {
        kdata = freshData;
    }
    return self;
}
Rhm Akbari

문제는 'async'를 호출 할 때 바로 개체가 해제된다는 것입니다. 컨트롤이 '비동기'가 완료 될 때까지 기다리지 않고 'doSomething'함수의 끝에 도달하고 자동 해제 풀에 추가 된 로컬 개체를 해제하여 컨트롤이 반환되기 때문에 개체를 선언 한 방식이 자동 해제 풀에 추가됩니다. 그 후 메모리 위치가 다른 데이터에 사용되며 혼란스러운 데이터가 표시됩니다. 선언 앞에 __block 지정자를 추가하면 다음 블록에서이 개체를 강력하게 캡처하고 블록 실행이 완료되면 해제하도록 코드에 지시 할 수 있습니다. 시도 해봐.

// inside a networking class X implementation
    - (void) doSomething:(completionBlock)completion {
        NSDictionary * json = // get from networking function, which will always have key "msg".
        __block Response * responseObj = [[Response alloc] initWithJson:json];
        dispatch_async(dispatch_get_main_queue(), ^{
          if (completion != nil) { completion (responseObj); }
        });
    }

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

Related 관련 기사

뜨겁다태그

보관