이 버그는 제 코드에서 며칠 동안 보였습니다. 문제를 해결하려고 노력했지만 아무 소용이 없었습니다. 나는 광범위한 디버깅을했고, 시뮬레이터와 장치, 로깅, 크래시 틱스 (crashlytics)가 크래시 로그를 던져 버렸고, 할당 해제 후 내 NSTimer
메시지와 관련이있다. 더 설명하겠습니다.앱이 포 그라운드로 돌아온 후 NSTimer가 충돌 함
일부 뷰 컨트롤러에이 NSTimer
컨트롤 내 UIToolbar
라벨, 그리고 사용자가 UITableView
을 갱신 할 때의 상대 시간을 표시하는 라벨을 업데이트 유지. 로드 할 때마다 새로 고칠 때마다 Updated just now
이 표시되고 사용자가 새로 고치거나 다른 VC로 이동하지 않으면 60 초마다 업데이트됩니다. 잠시 후에 Updated 1 minute ago
이 표시됩니다. NSTimer
은 UILabel
을 업데이트하는 방법을 트리거합니다. 사용자 새로 고침 (새로 고침 컨트롤을 뽑음으로써)에서이 메서드는 내 getAllItems
내에서 수동으로 호출됩니다 (즉, nil
을 전달하는 이유입니다).
NSTimer
나의 슈퍼 클래스에 정의되어
- (void)getAllItems
{
KILL_TIMER(self.updateDateTimer);
self.updateLabel = [Formatters boldLabelWithLabel:self.updateLabel
withText:@"Checking for items..."
withFont:[UIFont fontWithName:kOpenSansBold size:15.0f]];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self fetchObjectsWithRequest:self.request];
sleep(1);
dispatch_async(dispatch_get_main_queue(), ^{
[self.refreshControl performSelector:@selector(endRefreshing) withObject:nil afterDelay:0];
self.updatedDate = [NSDate date];
[self updateTimer:nil];
self.updateDateTimer = [NSTimer scheduledTimerWithTimeInterval:kToolbarUpdateLabelInterval
target:self
selector:@selector(updateTimer:)
userInfo:nil repeats:YES];
});
});
}
및 KILL_TIMER(q)
같이, 내 슈퍼 클래스에 정의되어있다 : 이것은 내있는 tableview에 항목을 얻을 코드가
@property (nonatomic, weak) NSTimer *updateDateTimer;
:
#define KILL_TIMER(q) if (q) {DDLogVerbose(@"KILLING TIMER: %@", q); [q invalidate]; q=nil;}
이 정의는 다음 두 가지 방법으로 호출됩니다.
) 내 getAllItems
방법 : 그래서 내가 (viewDidLoad
또는 사용자가 테이블보기를 새로 고침하여 해당 메소드를 호출하여) 아이템을로드 할 때, 나는 항상 현재 타이머를 죽이려고 시도합니다. 항목을 가져오고 항목을 가져오고 '지금 업데이트 됨'을 표시 한 다음 타이머를 60 초마다 실행하도록 예약합니다. 등 각 viewWillDisappear`에
B) :
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
KILL_TIMER(self.updateDateTimer);
}
그러나, 나는 홈 버튼을 누르면, 다음 응용 프로그램을 다시 열 경우, 일반적으로 (항상, 내가보기 컨트롤러를 전환 한 경우에만) 다음과 같은 메시지와 충돌 (NSZombies와 함께 사용) :
2013-07-11 17:21:37.576 App[3923:907] *** -[ItemCDTVC setUpdateDateTimer:]: message sent to deallocated instance 0x20bc49f0
내가 호출하는 NSNotification
을해야합니까 내 getAllItems
:
// Notification received when user returns to app (refreshes the table view)
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(getAllItems) name:UIApplicationWillEnterForegroundNotification object:nil];
이것은 메뉴를 사용하여보기 컨트롤러를 전환하고 앱을 종료 한 후 다시 열면 (앱이 종료되지 않음) 발생합니다. 전환하는 뷰 컨트롤러의 수에 관계없이 사용자가 앱에 남아있는 경우 충돌이 발생하지 않습니다.
매우 재현하기는하지만 수정 방법은 잘 모르므로 매우 귀찮은 버그입니다. 어떤 도움을 주셔서 감사합니다.
컨트롤러를 언제 옵저버에서 제거합니까? – Wain
@Wain 당신은 이것을 의미합니까? '[[NSNotificationCenter defaultCenter] removeObserver : self]; '? 그렇다면, 나는이 코드를'dealloc'에 넣었다. – swiftcode
알았어, 브레이크 포인트를 붙이고 때 맞춰. – Wain