iOS中的系統目錄(Documents、tmp、Library)、RunLoop的一些知識點
阿新 • • 發佈:2020-05-17
### 學習內容
歡迎關注我的iOS學習總結——每天學一點iOS:https://github.com/practiceqian/one-day-one-iOS-summary
#### 實現輪播圖需要注意的地方
1. 需要幾張輪播圖就設定UIScrollView的contentSize的寬度為自身的幾倍
- ```objective-c
//設定高度為0是為了限制UIScrollView只能在x軸方向滾動,如果設定x為0那麼只能在y軸方向滾動
CGSizeMake(自身寬度*n,0)
```
2. 使用NSTImer定時器定時滾動時避免迴圈引用
- 這裡一般使用系統的BLock方法加上\__weak和\__strong的使用
3. 給UISCrollView加上圖片時,每一張圖片的x方向位移是初始偏移量加上圖片下標*UISCrollView的寬度
- ```objective-c
CGRectMake(初始偏移量+i*(bounds.size.width),0,bounds.size.width-2*初始偏移量,bounds.size.height)
```
4. 定時器的使用需要及時的刪除/新增,同時注意建立定時器的方式
- 使用timerwithInterval建立的定時器不會自動新增到RunLoop中,需要手動開啟RunLoop
```objective-c
[[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時需要及時的移除定時器,停止拖動時需要及時的加上定時器
```objective-c
//這裡可以設定兩個函式,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. 獲取當前應用程式的根目錄
- ```objective-c
NSString* homePath = NSHomeDirectory()
```
2. 獲取應用程式的幾個主要目錄
- Documents
- 儲存使用者建立的文件檔案的目錄,使用者可以通過檔案分享分享該目錄下的檔案,在iTunes和iCloud備份時會自動備份該目錄
- ```objective-c
//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可以讓執行緒在需要做事的時候忙起來,在不需要的時候進入休眠狀態
```objective-c
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
- ```objective-c
//獲取當前執行緒的RunLoop,子執行緒的RunLoop要在子執行緒獲取
+(NSRunLoop*)currentRunLoop;
//獲取主執行緒的RunLoop
+(NSRunLoop*)mainRunLoop;