iOS中的系統目錄(Documents、tmp、Library)、RunLoop的一些知識點

學習內容

歡迎關注我的iOS學習總結——每天學一點iOS://github.com/practiceqian/one-day-one-iOS-summary

實現輪播圖需要注意的地方

  1. 需要幾張輪播圖就設置UIScrollView的contentSize的寬度為自身的幾倍

    • //設置高度為0是為了限制UIScrollView只能在x軸方向滾動,如果設置x為0那麼只能在y軸方向滾動
      CGSizeMake(自身寬度*n,0)
      
  2. 使用NSTImer定時器定時滾動時避免循環引用

    • 這裡一般使用系統的BLock方法加上__weak和__strong的使用
  3. 給UISCrollView加上圖片時,每一張圖片的x方向位移是初始偏移量加上圖片下標*UISCrollView的寬度

    • CGRectMake(初始偏移量+i*(bounds.size.width),0,bounds.size.width-2*初始偏移量,bounds.size.height)
      
  4. 定時器的使用需要及時的刪除/添加,同時注意創建定時器的方式

    • 使用timerwithInterval創建的定時器不會自動添加到RunLoop中,需要手動開啟RunLoop

      [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
      [[NSRunLoop mainRunLoop] addTimer:timer forMode: UITrackingRunLoopMode];
      //或者直接添加到NSRunLoopCommonModes中
      [[NSRunLoop mainRunLoop] addTimer:timer forMode: NSRunLoopCommonModes];
      
    • 通過timerWithTimeInterval和initWithFireDate方法創建出來的定時器,都需要手動加入到RunLoop中才會執行,否則不會執行;但是通過scheduledTimerWithTimeInterval創建出來的定時器是自動加入到RunLoop,而且會自動執行

    • 當用戶拖動UIScrollView時需要及時的移除定時器,停止拖動時需要及時的加上定時器

      //這裡可以設置兩個函數,addTimer,removeTimer
      -(void)addTimer{
        __weak typeof(self) weakSelf = self;
        self.bannerTimer = [NSTimer timerWithTimeInterval:3.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
          __strong typeof(weakSelf) strongSelf = weakSelf;
          [strongSelf changePage];
        }];
        [[NSRunLoop mainRunLoop]addTimer:self.bannerTimer forMode:NSDefaultRunLoopMode];
      }
      -(void)removeTimer{
        [self.bannerTimer invalidate];
        self.bannerTimer = nil;
      }
      //scrollview即將開始被拖動
      - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
          [self removeTimer];
      }
      //scrollview即將停止拖動
      - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
          [self addTimer];
      }
      

iOS中的系統目錄

  1. 獲取當前應用程式的根目錄

    • NSString* homePath = NSHomeDirectory()
      
  2. 獲取應用程式的幾個主要目錄

    • Documents

      • 保存用戶創建的文檔文件的目錄,用戶可以通過文件分享分享該目錄下的文件,在iTunes和iCloud備份時會自動備份該目錄

      • //NSSearchPathForDirectoriesInDomains返回的是一個字元串數組,但是數組裡面只有一個元素
        NSString* docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
        
    • Library

      • 不建議在該目錄下保存任何用戶相關數據,而是保存APP運行需要的修改數據,用戶也可以根據自己的需要進行保存
      • Caches
        • 建議保存數據快取使用,在用戶的磁碟空間已經使用完畢時可能刪除該目錄中的文件,在APP試用期間不會被刪除,但是在APP沒有運行的時候系統可能會刪除,需要持久化的數據不建議保存在該目錄下,防止被系統刪除
      • preferences
        • 用戶偏好存儲目錄,使用NSUserDefaults或者CFPreferences介面保存的數據都保存在該目錄下,編程人員不需要對該目錄進行管理,iTunes和iCloud會自動對該目錄進行備份
      • Application State
        • 用來保存與用戶數據以外的所有文件,如遊戲的新關卡,iTunes和iCloud會自動備份該目錄
    • tmp

      • 該目錄用來保存臨時使用的數據,編程人員應該在數據長時間不使用時主動刪除該目錄下的文件,在APP不運行期間,系統可能刪除該目錄下的文件,iTunes和iCloud不會備份該目錄的文件
    • SystemData(暫無介紹)

  3. 綜上所述,我們保存數據可以保存在Documents、Application State目錄下,而preferences用於保存系統介面數據不建議使用,而tmp目錄和cache目錄中的內容可能會被系統磁碟壓力緊張時刪除

關於Runloop的一些知識點

  1. RunLoop是什麼?

    • RunLoop是一種事件循環,一般的while循環會導致CPU進入忙等狀態,而RunLoop則是一種閑等待,當沒有事件時,RunLoop會進入休眠狀態,當有事件時,Runloop回去尋找相應的Handler處理事件,Runloop可以讓執行緒在需要做事的時候忙起來,在不需要的時候進入休眠狀態

      do{
        //獲取消息
        //處理消息
      }while(消息!=退出)
      
    • 一個Runloop對象,包含了一個執行緒,若干個mode,還有當前運行的mode

    • Runloop和執行緒是綁定在一起的,每個執行緒都有一個對應的Runloop對象,我們不能自己創建Runloop對象,但是可以獲取到系統提供的Runloop對象

    • 主執行緒的Runloop會在系統啟動時完成啟動,其他執行緒的Runloop默認並不會啟動,需要我們手動啟動

  2. RunLoop Mode

    • Mode可以視為事件的管家,一個Mode管理著各種事件
    • Mode實際上是source,observer,timer的集合,不同的Mode把不同組的source,observer,timer隔絕開,Runloop在某個時刻只能運行在一個Mode下,處理這一個Mode下的source,observer,timer
    • 蘋果文檔中提到的Mode共有五個
      • NSDefaultRunLoopMode
      • NSConnectionReplyMode
      • NSModePanelRunLoopMode
      • NSEventTrackingRunLoopMode
      • NSRunLoopCommonModes
      • 但是公開暴露出來介面的只有NSDefaultRunLoopMode和NSRunLoopCommonModes
    • NSRunLoopCommonModes是一個Mode的集合,包含了NSDefaultRunLoopMode和NSEventTrackingRunLoopMode,並不是說RunLoop會運行在這兩種模式下,而是相當於分別註冊了default和eventtracking兩種模式。
  3. RunLoop Source

    • RunLoopSource分為source,timer,observer三種,它們被稱作ModeItem
  4. 獲取RunLoop

    • //獲取當前執行緒的RunLoop,子執行緒的RunLoop要在子執行緒獲取
      +(NSRunLoop*)currentRunLoop;
      //獲取主執行緒的RunLoop
      +(NSRunLoop*)mainRunLoop;
      
Tags: