2012-02-01 26 views
14

Tôi có UIImageView được đặt trong UIScrollView, Cơ bản UIImageView này giữ bản đồ rất lớn và tạo hoạt ảnh trên đường dẫn được xác định trước với hướng mũi tên chỉ định.NSTimer không được kích hoạt khi sự kiện uiscrollview xảy ra

Nhưng, bất cứ khi nào xảy ra sự cố, tôi nghĩ MainLoop bị đóng băng và NSTimer không bị sa thải và hoạt ảnh dừng lại.

Có bất kỳ tài sản hiện có nào giải quyết vấn đề này, trên UIScrollView, CAKeyFrameAnimation hoặc NSTimer không?

//viewDidLoad 
    self.myTimer = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(drawLines:) userInfo:nil repeats:YES]; 

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

    CALayer *arrow = [CALayer layer]; 
    arrow.bounds = CGRectMake(0, 0, 5, 5); 
    arrow.position = CGPointMake(line.x1, line.y1); 
    arrow.contents = (id)([UIImage imageNamed:@"arrow.png"].CGImage); 

    [self.contentView.layer addSublayer:arrow]; 

    CAKeyframeAnimation* animation = [CAKeyframeAnimation animation]; 
    animation.path = path; 
    animation.duration = 1.0; 
    animation.rotationMode = kCAAnimationRotateAuto; // object auto rotates to follow the path 
    animation.repeatCount = 1; 
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; 
    animation.fillMode = kCAFillModeForwards; 

    [arrow addAnimation:animation forKey:@"position"]; 
} 
+0

bản sao có thể có của [UIScrollView tạm dừng NSTimer trong khi cuộn] (http://stackoverflow.com/questions/7059366/uiscrollview-pauses-nstimer-while-scrolling) –

Trả lời

51

Ứng dụng iOS chạy trên NSRunLoop. Mỗi NSRunLoop có các chế độ thực hiện khác nhau cho các tác vụ khác nhau. Ví dụ, nstimer mặc định được lên lịch chạy dưới NSDefaultRunMode trên NSRunLoop. Điều này có nghĩa là tuy nhiên là UIEvents nhất định, scrollviewing là một, sẽ làm gián đoạn bộ đếm thời gian, và đặt nó trên một hàng đợi để được chạy ngay sau khi sự kiện ngừng cập nhật. Trong trường hợp của bạn, để có được bộ đếm thời gian để không bị gián đoạn, bạn cần phải lên kế hoạch cho một chế độ khác nhau, cụ thể là NSRunLoopCommonModes, như vậy:

self.myTimer = [NSTimer scheduledTimerWithTimeInterval:280 
                   target:self 
                   selector:@selector(doStuff) 
                   userInfo:nil 
                   repeats:NO]; 
    [[NSRunLoop currentRunLoop] addTimer:self.myTimer forMode:NSRunLoopCommonModes]; 

Chế độ này sẽ cho phép hẹn giờ của bạn để không bị gián đoạn bằng cách di chuyển . Bạn có thể tìm thêm thông tin tại đây: https://developer.apple.com/documentation/foundation/nsrunloop Ở dưới cùng, bạn sẽ thấy định nghĩa về các chế độ bạn có thể chọn. Ngoài ra, huyền thoại có nó, bạn có thể viết các chế độ tùy chỉnh của riêng bạn, nhưng ít người đã từng sống để kể câu chuyện.

+0

Giải thích hay. – Robert

+2

Hey @GregPrice. Cảm ơn lời giải thích, thậm chí 3 năm sau. Tuy nhiên, doc nói 'scheduleTimerWithTimeInterval: ...' tạo một bộ đếm thời gian và * lên lịch cho nó trên vòng lặp chạy hiện tại ở chế độ mặc định *. Vậy tại sao bạn thêm nó hai lần trong RunLoop mặc định, không chỉ một lần trong chế độ 'NSRunLoopCommonModes'? – Martin

+0

'UIScrollView' chạy vòng lặp chạy trong' UITrackingRunLoopMode', khác với 'NSDefaultRunLoopMode'. Nó không đủ để lên lịch hẹn giờ cho chế độ mặc định nếu bạn cũng muốn nó chạy ở các chế độ khác. –

Các vấn đề liên quan