<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

       runloop運行流程圖

       

       

       

      系統默認注冊了5個Mode:
      kCFRunLoopDefaultMode:App的默認Mode,通常主線程是在這個Mode下運行
      
      UITrackingRunLoopMode:界面跟蹤 Mode,用于 ScrollView 追蹤觸摸滑動,保證界面滑動時不受其他 Mode 影響
      
      UIInitializationRunLoopMode: 在剛啟動 App 時第進入的第一個 Mode,啟動完成后就不再使用
      
      GSEventReceiveRunLoopMode: 接受系統事件的內部 Mode,通常用不到
      
      kCFRunLoopCommonModes: 這是一個占位用的Mode,不是一種真正的Mode
      

       

      CFRunLoopModeRef代表RunLoop的運行模式
      一個 RunLoop 包含若干個 Mode,每個Mode又包含若干個Source/Timer/Observer
      
      每次RunLoop啟動時,只能指定其中一個 Mode,這個Mode被稱作 CurrentMode
      
      如果需要切換Mode,只能退出Loop,再重新指定一個Mode進入
      
      這樣做主要是為了分隔開不同組的Source/Timer/Observer,讓其互不影響
      

        

       

      定時器

          dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
      //         定時器可以運行
              NSTimer *timer = [NSTimer timerWithTimeInterval:2 target:self selector:@selector(run) userInfo:nil repeats:YES];
              
              [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
          });
          
          dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
      //         定時器無法運行
              NSTimer *timer = [NSTimer timerWithTimeInterval:2 target:self selector:@selector(run) userInfo:nil repeats:YES];
              
              [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
          });
          
          dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
              NSTimer *timer = [NSTimer timerWithTimeInterval:2 target:self selector:@selector(run) userInfo:nil repeats:YES];
      //         定時器無法運行
              [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
          });
          
          dispatch_async(dispatch_get_main_queue(), ^{
              NSTimer *timer = [NSTimer timerWithTimeInterval:2 target:self selector:@selector(run) userInfo:nil repeats:YES];
      //         定時器可以運行
              [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
              
          });
          
      

       結論:如果定時器在主線程中開啟,可以正常運行;定時器在子線程中開啟,無法正常運行; 如果對應線程沒有 RunLoop 該方法也會失效,也就是說currentRunloop中 沒有timer,沒有source,也沒有OBServer,添加 [NSRunLoop currentRunLoop] run]試試;  主線程中能夠運行是因為timer添加到runloop中后,主線程runloop默認是啟動的,子線程中的runloop添加的timer,runloop需要手動啟動.

      Runloop要啟動要素:1.runloop中要有timer | source | observer其中一個條件 2.runloop得自己啟動

       

      常駐線程

      實例:開啟一個線程,不讓線程退出,這個線程一直在接受任務的處理,當一有任務,線程就接受處理,沒有任務就休眠

      - (void)viewDidLoad {
          [super viewDidLoad];
          
          self.thread = [[HJThread alloc] initWithTarget:self selector:@selector(invoke) object:nil];
          [self.thread start];
      }
      
      - (void)invoke
      {
        @autoreleasepool{ NSLog(@"******invoke*****%@", [NSThread currentThread]);    // 添加一個port讓runloop可以運行循環 [[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode]; [[NSRunLoop currentRunLoop] run];
        } NSLog(@"************"); } - (void)touchInvoke { NSLog(@"*********touchInvoke*********%@", [NSThread currentThread]); NSLog(@"%@", [NSRunLoop currentRunLoop]); }
      // 屏幕點擊 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [self performSelector:@selector(touchInvoke) onThread:self.thread withObject:nil waitUntilDone:NO]; }

       注意:經測試子線程雖然在defaultMode,但是拖動UIScrollView時并不會阻塞當前子線程的runloop defalutMode,因為拖動的view是在主線程的模式UITrackingMode,2個線程的模式互不干擾

       

      停止runloop

      1.需要保存當前runloop

      2.使用CF函數開啟運行runloop

      3.使用CF函數停止runloop

      #import "ViewController.h"
      
      @interface ViewController () <NSURLConnectionDataDelegate>
      /** runLoop */
      @property (nonatomic, assign) CFRunLoopRef runLoop;
      @end
      
      @implementation ViewController
      
      - (void)viewDidLoad {
          [super viewDidLoad];
          
          // 如果在子線程中使用NSURLConnection發送請求是不會有效果,因為子線程的runloop沒有啟動,子線程runloop默認是不啟動的
          dispatch_async(dispatch_get_global_queue(0, 0), ^{
              NSURLConnection *conn = [NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.baidu.com/images/234234324limgAB/2342lkjasdf3kkkkk.jpg"]] delegate:self];
              // 決定代理方法在哪個隊列中執行
              [conn setDelegateQueue:[[NSOperationQueue alloc] init]];
              
              // 啟動子線程的runLoop
      //        [[NSRunLoop currentRunLoop] run];
              
              // 保存當前runloop
              self.runLoop = CFRunLoopGetCurrent();
              
              // 啟動runLoop
              CFRunLoopRun();
          });
      }
      
      #pragma mark - <NSURLConnectionDataDelegate>
      - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
      {
          NSLog(@"didReceiveResponse******%@", [NSThread currentThread]);
      }
      
      - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
      {
          
          NSLog(@"didReceiveData******%@", [NSThread currentThread]);
      }
      
      - (void)connectionDidFinishLoading:(NSURLConnection *)connection
      {
          NSLog(@"connectionDidFinishLoading******%@", [NSThread currentThread]);
          
          // 停止RunLoop
          CFRunLoopStop(self.runLoop);
      }
      
      @end
      

        

       

      定時器自動調度

      //     任務自動調度,無需手動fire
          [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(run) userInfo:nil repeats:YES];
          
          ------------------2種方式等價------------------
          
      //    任務自動調度,無需手動fire
          NSTimer *timer = [NSTimer timerWithTimeInterval:3 target:self selector:@selector(run) userInfo:nil repeats:YES];
          //         定時器可以運行
          [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
      

       

      監聽runloop運行循環的事件狀態變化,可以用以攔截一些事件的處理

      typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
          kCFRunLoopEntry = (1UL << 0),        // : 即將到 runloop
          kCFRunLoopBeforeTimers = (1UL << 1), // : 即將處理 timer 之前
          kCFRunLoopBeforeSources = (1UL << 2),// : 即將處理 source 之前
          kCFRunLoopBeforeWaiting = (1UL << 5),// : 即將休眠
          kCFRunLoopAfterWaiting = (1UL << 6), // : 休眠之后
          kCFRunLoopExit = (1UL << 7),         // : 退出
          kCFRunLoopAllActivities = 0x0FFFFFFFU// : 所有的活動
      };
      

       

      - (IBAction)btnClick:(id)sender {
          NSLog(@"btnDidClick*****");
      }
      
      - (void)viewDidLoad {
          [super viewDidLoad];
          
        // 監聽runloop狀態變化 [self observer]; } - (void)observer { // 創建observer CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) { NSLog(@"****監聽到RunLoop狀態發生改變**%zd", activity); }); // 添加觀察者:監聽RunLoop的狀態 CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode); // 釋放Observer CFRelease(observer); }

       

      Autorelease Pool

      為啥OC程序的Main函數使用autorelease pool包括了,從運行循環中也可以解釋,運行循環中不斷的在接受和處理事件,中間的會產生很多的變量和資源,產生的這些變量和資源會放到自動釋放池中,因runloop一直沒有退出,那么變量就可能沒有被釋放,但是加上了autorelease pool后,在runloop進入休眠前時,autorelease pool就會釋放臨時變量和資源,這樣內存就可以得到管理; runloop重新運行時就又會創建一個自動釋放池

      自動釋放池會再在Runloop休眠前(beforeWait)釋放,又會緊接著創建一個新的自動釋放池,用以下次喚醒時使用

       

      Runloop應用:

      .NSTimer

      .ImageView顯示

      .PerformSelecor 可以給線程發送消息

      .常駐線程,開啟一個常駐線程,讓線程不銷毀,等待其他線程發送消息,然后處理任務和事件

      >在子線程中開啟一個定時器

      >在子線程中進行一些長期監控,語音通話,或是傳輸數據等業務場景

      .自動釋放池

      .可以添加Observer監聽Runloop的狀態,這樣可以攔截一些事件處理,比如過濾器功能等.

      .可以讓某些事件(行為,任務)在特定的模式下執行

       

      總結:

      >運行循環,跑圈. 可以查看源碼里面內部是一個do while循環,循環內部不斷處理任務和事件(source,timer,observer)

      >創建開啟運行要素最少得要有source(消息源,source0,source1),timer中的一個條件

      >一個線程對應一個Runloop(底層是通過字典保存Runloop,線程作為key,Runloop作為value),主線程的Runloop默認已經開啟,子線程的Runloop的手動啟動,通過調用[runloop run]方法啟動

      >Runloop只能選擇一個Mode模式啟動,如果當前模式Mode沒有任何Source(消息源),timer,Runloop就會直接退出

      >當kCFRunLoopEntry會創建新的釋放池用以Runloop被喚醒時使用,自動釋放池在runloop即將進入休眠時(kCFRunLoopBeforeWaiting)釋放或kCFRunLoopExit退出時,自動釋放池釋放 

      >子線程runloop默認是不啟動的,如果子線程runloop需要手動啟動

       

       

       可以參考文獻:

      http://www.cocoachina.com/ios/20150601/11970.html

       

      posted on 2017-09-04 23:00  HJiang  閱讀(580)  評論(0)    收藏  舉報

      主站蜘蛛池模板: 无码激情亚洲一区| 亚洲国产精品高清线久久| 久久精品国产再热青青青| 欧美一本大道香蕉综合视频| 日本熟妇浓毛| 国产一区二区精品久久呦| 人体内射精一区二区三区| 韩国精品一区二区三区在线观看| 90后极品粉嫩小泬20p| 少妇人妻偷人精品视蜜桃| 十八岁污网站在线观看| 大地资源中文第二页日本| 亚洲国产一区二区三区亚瑟| 国产美女午夜福利视频| 丰满少妇内射一区| 国产精品一区二区三区卡| 久久亚洲av成人无码软件| 蜜桃av亚洲精品一区二区| 性xxxx搡xxxxx搡欧美| 国模精品视频一区二区三区| 蜜臀91精品国产高清在线| 人人澡人人妻人人爽人人蜜桃| 强伦人妻一区二区三区| 成人激情视频一区二区三区| 国产男女猛烈无遮挡免费视频网站| 日韩中文字幕有码午夜美女| 不卡国产一区二区三区| 年轻女教师hd中字3| 一本无码人妻在中文字幕免费| 亚洲小说乱欧美另类| 色欲狠狠躁天天躁无码中文字幕| 野外做受三级视频| 寿光市| JIZZJIZZ国产| 日韩人妻一区中文字幕| 国产日韩一区二区三区在线观看| 国99久9在线 | 免费| 亚洲中文无码手机永久| 欧美videos粗暴| 高清偷拍一区二区三区| 亚洲第一香蕉视频啪啪爽|