IOS RunLoop 의 이벤트 순환 메커니즘 분석

6420 단어 IOSRunLoop
RunLoop 이 시작 되면 관찰자 에 게 알림 을 보 냅 니 다.
Timer/Source 0 이 벤트 를 처리 하 겠 다 는 알림 을 보 냅 니 다.
Source 0 이벤트 처리
Source 1 이 처리 할 것 이 있 으 면,이 때 는 go to 문장의 실현 을 통 해 코드 논리의 도약 을 하고,깨 우 는 것 을 처리 하 는 것 은 받 은 메시지 입 니 다.
Source 1 이 처리 하지 않 으 면 스 레 드 는 휴면 하고 관찰자 에 게 알림 을 보 냅 니 다.
그 다음 에 스 레 드 는 한 사용자 상태 에서 커 널 상태 로 전환 하고 휴면 한 다음 에 깨 우 기 를 기다 리 고 깨 우 는 조건 은 약 세 가 지 를 포함한다.
1、Source1
2.타이머 이벤트
3.외부 수 동 각성
스 레 드 가 깨 어 난 후에 도 관찰자 에 게 알 리 고 깨 어 날 때 받 은 메 시 지 를 처리 해 야 합 니 다.
Timer/Source 0 이 벤트 를 처리 할 알림 의 발송 으로 돌아 가기
그리고 위 절 차 를 다시 진행 합 니 다.이것 이 바로 RunLoop 의 이벤트 순환 체제 입 니 다.
내부 코드 논리 정 리 는 다음 과 같다.

///  DefaultMode  
void CFRunLoopRun(void) {
    CFRunLoopRunSpecific(CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, 1.0e10, false);
}
 
///     Mode  ,    RunLoop    
int CFRunLoopRunInMode(CFStringRef modeName, CFTimeInterval seconds, Boolean stopAfterHandle) {
    return CFRunLoopRunSpecific(CFRunLoopGetCurrent(), modeName, seconds, returnAfterSourceHandled);
}
 
/// RunLoop   
int CFRunLoopRunSpecific(runloop, modeName, seconds, stopAfterHandle) {
    
    ///     modeName    mode
    CFRunLoopModeRef currentMode = __CFRunLoopFindMode(runloop, modeName, false);
    ///   mode   source/timer/observer,     。
    if (__CFRunLoopModeIsEmpty(currentMode)) return;
    
    /// 1.    Observers: RunLoop      loop。
    __CFRunLoopDoObservers(runloop, currentMode, kCFRunLoopEntry);
    
    ///     ,  loop
    __CFRunLoopRun(runloop, currentMode, seconds, returnAfterSourceHandled) {
        
        Boolean sourceHandledThisLoop = NO;
        int retVal = 0;
        do {
 
            /// 2.    Observers: RunLoop      Timer   。
            __CFRunLoopDoObservers(runloop, currentMode, kCFRunLoopBeforeTimers);
            /// 3.    Observers: RunLoop      Source0 ( port)   。
            __CFRunLoopDoObservers(runloop, currentMode, kCFRunLoopBeforeSources);
            ///       block
            __CFRunLoopDoBlocks(runloop, currentMode);
            
            /// 4. RunLoop    Source0 ( port)   。
            sourceHandledThisLoop = __CFRunLoopDoSources0(runloop, currentMode, stopAfterHandle);
            ///       block
            __CFRunLoopDoBlocks(runloop, currentMode);
 
            /// 5.     Source1 (  port)    ready   ,       Source1          。
            if (__Source0DidDispatchPortLastTime) {
                Boolean hasMsg = __CFRunLoopServiceMachPort(dispatchPort, &msg)
                if (hasMsg) goto handle_msg;
            }
            
            ///    Observers: RunLoop          (sleep)。
            if (!sourceHandledThisLoop) {
                __CFRunLoopDoObservers(runloop, currentMode, kCFRunLoopBeforeWaiting);
            }
            
            /// 7.    mach_msg      mach_port    。       ,             。
            /// •      port  Source    。
            /// •    Timer     
            /// • RunLoop          
            /// •             
            __CFRunLoopServiceMachPort(waitSet, &msg, sizeof(msg_buffer), &livePort) {
                mach_msg(msg, MACH_RCV_MSG, port); // thread wait for receive msg
            }
 
            /// 8.    Observers: RunLoop          。
            __CFRunLoopDoObservers(runloop, currentMode, kCFRunLoopAfterWaiting);
            
            ///     ,    。
            handle_msg:
 
            /// 9.1      Timer     ,    Timer   。
            if (msg_is_timer) {
                __CFRunLoopDoTimers(runloop, currentMode, mach_absolute_time())
            } 
 
            /// 9.2    dispatch main_queue block,  block。
            else if (msg_is_dispatch) {
                __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__(msg);
            } 
 
            /// 9.3      Source1 (  port)      ,      
            else {
                CFRunLoopSourceRef source1 = __CFRunLoopModeFindSourceForMachPort(runloop, currentMode, livePort);
                sourceHandledThisLoop = __CFRunLoopDoSource1(runloop, currentMode, source1, msg);
                if (sourceHandledThisLoop) {
                    mach_msg(reply, MACH_SEND_MSG, reply);
                }
            }
            
            ///      Loop block
            __CFRunLoopDoBlocks(runloop, currentMode);
            
 
            if (sourceHandledThisLoop && stopAfterHandle) {
                ///   loop            。
                retVal = kCFRunLoopRunHandledSource;
            } else if (timeout) {
                ///               
                retVal = kCFRunLoopRunTimedOut;
            } else if (__CFRunLoopIsStopped(runloop)) {
                ///            
                retVal = kCFRunLoopRunStopped;
            } else if (__CFRunLoopModeIsEmpty(runloop, currentMode)) {
                /// source/timer/observer      
                retVal = kCFRunLoopRunFinished;
            }
            
            ///      ,mode   ,loop     ,   loop。
        } while (retVal == 0);
    }
    
    /// 10.    Observers: RunLoop     。
    __CFRunLoopDoObservers(rl, currentMode, kCFRunLoopExit);
}
실제로 RunLoop 은 이러한 함수 이 고 그 내 부 는 do-while 순환 이다.CFRunLoopRun()을 호출 하면 스 레 드 는 이 순환 에 머 물 러 있 습 니 다.시간 이 초과 되 거나 수 동 으로 멈 출 때 까지 이 함수 가 되 돌아 올 수 있 습 니 다.
이러한 문제 가 있 습 니 다.우리 가 app 을 클릭 하면 프로그램 이 시작 되 고 프로그램 이 실행 되 며 프로그램 이 죽 는 과정 까지 시스템 에 무슨 일이 일 어 났 습 니까?
실제 적 으로 main 함 수 를 호출 한 후에 UIApplicationMain 함 수 를 호출 합 니 다.이 함수 내부 에서 메 인 스 레 드 의 RunLoop 을 시작 한 다음 에 일련의 처 리 를 거 쳐 최종 적 으로 메 인 스 레 드 의 RunLoop 은 휴면 상태 에 있 을 것 입 니 다.그리고 우 리 는 이때 화면 을 클릭 하면 Source 1 로 전환 하여 메 인 스 레 드 를 깨 울 것 입 니 다.그리고 우리 가 프로그램 을 죽 일 때 RunLoop 의 종 료 를 호출 하고 관찰자 에 게 알림 을 보 냅 니 다.
총 결 도 를 찾 아 기억 을 돕 기:

이상 은 IOS RunLoop 의 이벤트 순환 체 제 를 분석 하 는 상세 한 내용 입 니 다.IOS RunLoop 의 이벤트 순환 체제 에 관 한 자 료 는 저희 의 다른 관련 글 을 주목 하 세 요!

좋은 웹페이지 즐겨찾기