iOS 의 NSTimer 타이머 초기 사용 분석

5075 단어 iOSNSTimer
타이머 만 들 기(NSTimer)

- (void)viewDidLoad {
  [super viewDidLoad];
  [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(actionTimer:) userInfo:nil repeats:YES];
}

- (void)actionTimer:(NSTimer *)timer
{

}

NSTimer 는 기본적으로 default mode 에서 실 행 됩 니 다.default mode 는 거의 모든 입력 원(NSConnection 제외)NSDefaultRunLoopMode 모드 를 포함 합 니 다.
actionTimer 방법 은 1s 마다 호출 됩 니 다.NSTimer 는 사용 하기에 매우 간단 하지 않 습 니까?NSTimer 의 초기 응용 프로그램 입 니 다.
메 인 화면 이 미 끄 러 졌 을 때 NSTimer 가 효력 을 잃 었 습 니 다.
메 인 화면 이 미 끄 러 지 는 것 은 무슨 뜻 입 니까?즉,메 인 화면 에 UITableView 나 UIScrollView 가 있 고 UITableView 나 UIScrollView 를 미 끄 러 뜨 린 다.이 럴 때 NSTimer 가 효력 을 잃 었 습 니 다.
UITableView 가 있 는 UIViewController 에서 타 이 머 를 시작 하고 1s 마다 1 을 추가 하 며 이 숫자 를 UILabel 에 표시 합 니 다.

- (void)viewDidLoad {
  [super viewDidLoad];
  [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(actionTimer:) userInfo:nil repeats:YES];
}

- (void)actionTimer:(NSTimer *)timer
{
  self.number++;
  self.label.text = [NSString stringWithFormat:@"%d",self.number];
  NSLog(@"%d",self.number);
}

UITableView 와 UILabel 의 생 성에 대해 서 는 생략 하 겠 습 니 다.자세 한 코드 는 여 기 를 클릭 하여 다운로드 할 수 있 습 니 다.iOS StrongDemo,iOS StrongDemo 는 제 가 계속 업데이트 하 겠 습 니 다.여러분 은 github 에 star 를 올 려 주세요.
이렇게 하면 사용자 가 UITableView 가 UITracking RunLoopMode 에 있 을 때 NSTimer 는 효력 을 잃 고 fire 가 될 수 없습니다.self.label 의 숫자 도 업데이트 할 수 없습니다.

NSTimer 의 run loop 수정
해결 방법 은 이 를 UITracking RunLoopMode 모드 나 NSRunLoopCommonModes 모드 에 추가 하 는 것 이다.

[[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];
혹은

[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
NSRunLoop CommonModes:하나의 모드 집합 입 니 다.하나의 이벤트 가 이 모드 로 집합 되 었 을 때 집합 안의 모든 모드 에 연결 되 는 것 과 같 습 니 다.

fire
우 리 는 먼저 NSTimer 로 간단 한 타 이 머 를 만들어 서 5 초 마다 콘 솔 에서 Fire 를 출력 합 니 다.비교적 당연 하 다 고 생각 하 는 방법 은 이렇다.

@interface DetailViewController ()
@property (nonatomic, weak) NSTimer *timer;
@end

@implementation DetailViewController
- (IBAction)fireButtonPressed:(id)sender {
  _timer = [NSTimer scheduledTimerWithTimeInterval:3.0f
                       target:self
                      selector:@selector(timerFire:)
                      userInfo:nil
                       repeats:YES];
  [_timer fire];
}

-(void)timerFire:(id)userinfo {
  NSLog(@"Fire");
}
@end

실행 한 후에 콘 솔 에서 3 초 에 한 번 씩 Fire 를 출력 하 는 것 이 확실 합 니 다.그러나 우리 가 이 인터페이스 에서 다른 인터페이스 로 넘 어 갔 을 때 콘 솔 은 아직도 Fire 를 끊임없이 출력 하고 있 습 니 다.타 이 머 는 멈 추 지 않 은 것 같다.
invalidate
멈 추 지 않 았 으 니 데모 뷰 컨트롤 러 의 dealloc 에 invalidate 방법 을 추가 합 니 다.

-(void)dealloc {
  [_timer invalidate];
  NSLog(@"%@ dealloc", NSStringFromClass([self class]));
}
다시 실행 해도 멈 추 지 않 았 습 니 다.이 유 는 Timer 가 Runloop 에 추 가 될 때 Runloop 에 의 해 강하 게 인용 되 기 때 문 입 니 다.
Note in particular that run loops maintain strong references to their timers, so you don't have to maintain your own strong reference to a timer after you have added it to a run loop.
그리고 Timer 는 Target 에 대한 강 한 인용(즉 self)이 있 습 니 다.
Target is the object to which to send the message specified by aSelector when the timer fires. The timer maintains a strong reference to target until it (the timer) is invalidated.
NSTimer 가 self 를 강하 게 인용 해 self 가 풀 려 나 지 않 아 self 의 dealloc 에 들 어가 지 못 한 다 는 것 이다.
그렇다면 invalidate 단 추 를 추가 할 수 있 습 니 다.

- (IBAction)invalidateButtonPressed:(id)sender {
  [_timer invalidate];
}
이렇게 하면 돼.SOF 에서 어떤 분 이 invalidate 이후 에 실행 해 야 된다 고...timer=nil,이 유 를 이해 하지 못 했 습 니 다.이 유 를 알 고 있다 면 알려 주세요.)
invalidate 방법의 문서 에 다음 과 같은 말 이 있 습 니 다.
You must send this message from the thread on which the timer was installed. If you send this message from another thread, the input source associated with the timer may not be removed from its run loop, which could prevent the thread from exiting properly.
NSTimer 가 어느 스 레 드 에서 만 들 면 어느 스 레 드 에서 멈 춰 야 합 니까?그렇지 않 으 면 자원 이 올 바 르 게 방출 되 지 않 습 니 다.보아하니 각종 구덩이 가 아직 적지 않 은 것 같다.
dealloc
그러면 문제 가 생 겼 습 니 다.만약 에 제 가 이 NSTimer 를 계속 출력 시 키 려 고 했 는데 DemoViewController 가 소각 되 어야 멈 추 었 습 니 다.제 가 어떻게 멈 추 게 해 야 합 니까?
  • NSTimer 는 Runloop 에 의 해 강하 게 인용 되 었 습 니 다.방출 하려 면 invalidate 방법 을 사용 해 야 합 니 다
  • 그러나 저 는 DemoView Controller 의 dealloc 에서 invalidate 방법 을 호출 하고 싶 지만 self 는 NSTimer 에 의 해 강하 게 인용 되 었 습 니 다
  • 4.567917.그래서 나 는 NSTimer 를 먼저 풀 어야 하지만 invalidate 방법 을 사용 하지 않 으 면 풀 수 없다
  • 그러나 당신 이 dealloc 방법 에 들 어가 지 않 으 면 나 는 invalidate 방법 을 사용 할 수 없습니다
  • 4.567917.음...4.567918.

    좋은 웹페이지 즐겨찾기