iOS 系統提供了文件共享支持
當手機通過數據線連接到 Mac 的 iTunes 時, 可以在 iTunes 將電腦上的文件傳輸到 App 的沙盒目錄當中. 為 App 添加離線數據. 也可以將 App 沙盒目錄下保存的文件通過 iTunes 導出到電腦當中.
官方文檔中的描述
在 "iOS 9.3 Documentation" > "General" > "Guides" > "iOS Technology Overview" 文章中, 對 iOS 系統中相關技術做了大致的介紹. 其中 Core Services 層里面, 可以查找到 File-Sharing Support的相關說明.
以下是官方文檔的原始描述
File-sharing support lets apps make user data files available in iTunes 9.1 and later. An app that declares its support for file sharing makes the contents of its /Documents directory available to the user. The user can then move files in and out of this directory as needed from iTunes. This feature does not allow your app to share files with other apps on the same device; that behavior requires the pasteboard or a document interaction controller object.
To enable file sharing for your app, do the following:
Add the UIFileSharingEnabled key to your app’s Info.plist file, and set the value of the key to YES.
Put whatever files you want to share in your app’s Documents directory.
When the device is plugged into the user’s computer, iTunes displays a File Sharing section in the Apps tab of the selected device.
The user can add files to this directory or move files to the desktop.
Apps that support file sharing should be able to recognize when files have been added to the Documents directory and respond appropriately. For example, your app might make the contents of any new files available from its interface. You should never present the user with the list of files in this directory and ask them to decide what to do with those files.
For additional information about the UIFileSharingEnabled key, see Information Property List Key Reference.
簡單總結一下:
File-sharing support是在 iTunes9.1 及之后的版本開始支持的.
該功能支持將 App 沙盒目錄下 Document 文件夾中的內容進行共享, 即可以通過 iTunes 軟件對 App 的 Document 文件夾的內容進行操作, 比如添加,刪除, 導出 Document 中的文件.
File-sharing support并不支持與該設備上其它 App 進行文件共享
支持文件共享的 App 應該識別添加到 Document 目錄中的文件并做出適當的響應. 比如當有新的文件可用時, App 可以在界面上顯示新的內容, 但不應該向用戶展示新添加文件列表并詢問用戶對該文件做出什么操作.
使用方式:
- 其實開發當中需要做的配置就一步, 其它都是引導用戶怎么去使用文件共享功能
在 Info.plist 文件中添加 UIFileSharingEnabled 這個Key, 并設置該值為 YES 即可
-
在填寫完 UIFileSharingEnabled 并回車后, 發現會自動更正為 Application supports iTunes file sharing , 將值設置為 YES 即可
image -
引導用戶如何使用 iTunes 與 App 進行文件共享
當設備連接到用戶電腦時, iTunes會在選中設備的Apps標簽頁顯示文件共享的會話
可以添加, 復制, 刪除指定App的沙盒目錄中的文件, 最后執行"Sync"按鈕進行數據同步
監聽Document目錄的文件改動
使用GCD 與 file descriptor 實現對文件夾內容的修改進行監聽, 實現的關鍵代碼如下
// 這里邊需要定義兩個成員變量
{
dispatch_queue_t _zDispatchQueue;
dispatch_source_t _zSource;
}
// 開始監聽Document目錄文件改動, 一旦發生修改則發出一個名為ZFileChangedNotification的通知
- (void)startMonitoringDocumentAsynchronous
{
// 獲取沙盒的Document目錄
NSString *docuPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
[self startMonitoringDirectory:docuPath];
}
// 監聽指定目錄的文件改動
- (void)startMonitoringDirectory:(NSString *)directoryPath
{
// 創建 file descriptor (需要將NSString轉換成C語言的字符串)
// open() 函數會建立 file 與 file descriptor 之間的連接
int filedes = open([directoryPath cStringUsingEncoding:NSASCIIStringEncoding], O_EVTONLY);
// 創建 dispatch queue, 當文件改變事件發生時會發送到該 queue
_zDispatchQueue = dispatch_queue_create("ZFileMonitorQueue", 0);
// 創建 GCD source. 將用于監聽 file descriptor 來判斷是否有文件寫入操作
_zSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE, filedes, DISPATCH_VNODE_WRITE, _zDispatchQueue);
// 當文件發生改變時會調用該 block
dispatch_source_set_event_handler(_zSource, ^{
// 在文件發生改變時發出通知
// 在子線程發送通知, 這個通知觸發的方法會在子線程當中執行
[[NSNotificationCenter defaultCenter] postNotificationName:ZFileChangedNotification object:nil userInfo:nil];
});
// 當文件監聽停止時會調用該 block
dispatch_source_set_cancel_handler(_zSource, ^{
// 關閉文件監聽時, 關閉該 file descriptor
close(filedes);
});
// 開始監聽文件
dispatch_resume(_zSource);
}
// 停止監聽指定目錄的文件改動
- (void)stopMonitoringDocument
{
dispatch_cancel(_zSource);
}
獲取Document目錄下的所有文件
這里邊DirectoryWatcher是做成一個單例的工具類, 具體代碼就不全部寫上了. 關鍵的實現代碼也比較簡單. 只要監聽ZFileChangedNotification并做出相應處理即可
- (void)viewDidLoad
{
[super viewDidLoad];
// 監聽Document目錄的文件改動
[[DirectoryWatcher defaultWatcher] startMonitoringDocumentAsynchronous];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(fileChanageAction:) name:ZFileChangedNotification object:nil];
}
- (void)dealloc
{
// 取消監聽Document目錄的文件改動
[[DirectoryWatcher defaultWatcher] stopMonitoringDocument];
[[NSNotificationCenter defaultCenter] removeObserver:ZFileChangedNotification];
}
- (void)fileChanageAction:(NSNotification *)notification
{
// ZFileChangedNotification 通知是在子線程中發出的, 因此通知關聯的方法會在子線程中執行
NSLog(@"文件發生了改變, %@", [NSThread currentThread]);
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *filePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSError *error;
// 獲取指定路徑對應文件夾下的所有文件
NSArray <NSString *> *fileArray = [fileManager contentsOfDirectoryAtPath:filePath error:&error];
NSLog(@"%@", fileArray);
}