如何读取IOS共享目录的文件
来源:互联网 发布:php 字符串查找函数 编辑:程序博客网 时间:2024/05/20 09:09
最近开发了桥牌PBN、围棋SGF、国际和中国象棋PGN等文件在iMac电脑上的阅读软件,想转换到IOS版本,这些文件可以通过 iTunes 的 file sharing 功能将文件导入到iPhone/iPad中的App中,前提是你的App在开发时,将info.plist文件中的Application supports iTunes file sharing 设置为Yes。
通过 iTunes将文件导入到你的应用中,操作比较简单,打开 iTunes,连接你的iPhone/iPad,选择你的设备,找到你要导入文件的应用,比如我的Chess PGN Viewer,然后,点击添加,就可以将PGN文件导入到Chess PGN Viewer的共享文件夹,这样,就可以用Chess PGN Viewer打开这些文件了。
原来,没在IOS上做过这种功能,搜索IOS共享文件的读取,有几个例子,按一个简单的例子做好,提交到AppStore,审核被拒绝!原因是审核人员在导入文件后,无法看到导入的文件,就以功能缺陷为由拒绝了。我的App当时确实不能及时显示导入的文件,而是需要自己刷新一下,才能显示。但审核人员认为应该在导入后应可以立即显示出文件列表。
审核被拒绝后,又搜索了一下,按例子做了一个实时监控文件变化的,功能确实是可以实现的,但延迟时间比较长,有时候需要好几秒钟才能显示出文件列表来,不可忍受。最后,找到了苹果公司官方的例子,DirectoryWatcher,经测试效果非常好,一旦文件导入,立即就能显示。引入DirectoryWatcher后,提交Appstore,审核通过。代码比较简单,全部代码如下:
DirectoryWatcher.h
#import <Foundation/Foundation.h>
@class DirectoryWatcher;
@protocol DirectoryWatcherDelegate <NSObject>
@required
- (void)directoryDidChange:(DirectoryWatcher *)folderWatcher;
@end
@interface DirectoryWatcher : NSObject
{
id <DirectoryWatcherDelegate>__weak delegate;
int dirFD;
int kq;
CFFileDescriptorRef dirKQRef;
}
@property (nonatomic,weak) id <DirectoryWatcherDelegate> delegate;
+ (DirectoryWatcher *)watchFolderWithPath:(NSString *)watchPath delegate:(id<DirectoryWatcherDelegate>)watchDelegate;
- (void)invalidate;
@end
DirectoryWatcher.m
#import "DirectoryWatcher.h"
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#include <fcntl.h>
#include <unistd.h>
#import <CoreFoundation/CoreFoundation.h>
@interface DirectoryWatcher (DirectoryWatcherPrivate)
- (BOOL)startMonitoringDirectory:(NSString *)dirPath;
- (void)kqueueFired;
@end
#pragma mark -
@implementation DirectoryWatcher
@synthesize delegate;
- (instancetype)init
{
self = [superinit];
delegate =NULL;
dirFD = -1;
kq = -1;
dirKQRef =NULL;
returnself;
}
- (void)dealloc
{
[selfinvalidate];
}
+ (DirectoryWatcher *)watchFolderWithPath:(NSString *)watchPath delegate:(id)watchDelegate
{
DirectoryWatcher *retVal =NULL;
if ((watchDelegate !=NULL) && (watchPath != NULL))
{
DirectoryWatcher *tempManager = [[DirectoryWatcheralloc] init];
tempManager.delegate = watchDelegate;
if ([tempManagerstartMonitoringDirectory: watchPath])
{
// Everything appears to be in order, so return the DirectoryWatcher.
// Otherwise we'll fall through and return NULL.
retVal = tempManager;
}
}
return retVal;
}
- (void)invalidate
{
if (dirKQRef !=NULL)
{
CFFileDescriptorInvalidate(dirKQRef);
CFRelease(dirKQRef);
dirKQRef =NULL;
// We don't need to close the kq, CFFileDescriptorInvalidate closed it instead.
// Change the value so no one thinks it's still live.
kq = -1;
}
if(dirFD != -1)
{
close(dirFD);
dirFD = -1;
}
}
@end
#pragma mark -
@implementation DirectoryWatcher (DirectoryWatcherPrivate)
- (void)kqueueFired
{
assert(kq >=0);
structkevent event;
structtimespec timeout = {0,0};
int eventCount;
eventCount = kevent(kq,NULL, 0, &event,1, &timeout);
assert((eventCount >=0) && (eventCount < 2));
// call our delegate of the directory change
[delegatedirectoryDidChange:self];
CFFileDescriptorEnableCallBacks(dirKQRef,kCFFileDescriptorReadCallBack);
}
static void KQCallback(CFFileDescriptorRef kqRef,CFOptionFlags callBackTypes,void *info)
{
DirectoryWatcher *obj;
obj = (__bridgeDirectoryWatcher *)info;
assert([obj isKindOfClass:[DirectoryWatcher class]]);
assert(kqRef == obj->dirKQRef);
assert(callBackTypes == kCFFileDescriptorReadCallBack);
[obj kqueueFired];
}
- (BOOL)startMonitoringDirectory:(NSString *)dirPath
{
// Double initializing is not going to work...
if ((dirKQRef ==NULL) && (dirFD == -1) && (kq == -1))
{
// Open the directory we're going to watch
dirFD =open([dirPath fileSystemRepresentation],O_EVTONLY);
if (dirFD >=0)
{
// Create a kqueue for our event messages...
kq =kqueue();
if (kq >=0)
{
structkevent eventToAdd;
eventToAdd.ident =dirFD;
eventToAdd.filter =EVFILT_VNODE;
eventToAdd.flags =EV_ADD | EV_CLEAR;
eventToAdd.fflags =NOTE_WRITE;
eventToAdd.data =0;
eventToAdd.udata =NULL;
int errNum =kevent(kq, &eventToAdd,1, NULL,0, NULL);
if (errNum ==0)
{
CFFileDescriptorContext context = {0, (__bridgevoid *)(self),NULL, NULL,NULL };
CFRunLoopSourceRef rls;
// Passing true in the third argument so CFFileDescriptorInvalidate will close kq.
dirKQRef =CFFileDescriptorCreate(NULL,kq, true,KQCallback, &context);
if (dirKQRef !=NULL)
{
rls = CFFileDescriptorCreateRunLoopSource(NULL,dirKQRef, 0);
if (rls !=NULL)
{
CFRunLoopAddSource(CFRunLoopGetCurrent(), rls,kCFRunLoopDefaultMode);
CFRelease(rls);
CFFileDescriptorEnableCallBacks(dirKQRef,kCFFileDescriptorReadCallBack);
// If everything worked, return early and bypass shutting things down
returnYES;
}
// Couldn't create a runloop source, invalidate and release the CFFileDescriptorRef
CFFileDescriptorInvalidate(dirKQRef);
CFRelease(dirKQRef);
dirKQRef =NULL;
}
}
// kq is active, but something failed, close the handle...
close(kq);
kq = -1;
}
// file handle is open, but something failed, close the handle...
close(dirFD);
dirFD = -1;
}
}
returnNO;
}
@end
将DirectoryWatcher.h和DirectoryWatcher.m导入到你的工程中。
在myViewController.h中,添加与读取共享文件夹的变量定义
#import <UIKit/UIKit.h>
#import "DirectoryWatcher.h"
@interface myViewController : UIViewController <DirectoryWatcherDelegate> {
//显示文件列表
IBOutlet UITableView *fileTableView;
//存储沙盒子里的所有文件
NSMutableArray *dirArray;
//苹果的方法
DirectoryWatcher *docWatcher;
}
@end
在myViewController.m中,实现读取共享文件清单
#pragma mark -
#pragma mark 文件变动监听方法
- (NSString *)applicationDocumentsDirectory {
//
return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES) lastObject];
}
- (void)directoryDidChange:(DirectoryWatcher *)folderWatcher {
//
dirArray = [[NSMutableArrayalloc] init];
NSString *documentsDirectoryPath = [selfapplicationDocumentsDirectory];
NSArray *documentsDirectoryContents = [[NSFileManagerdefaultManager] contentsOfDirectoryAtPath:documentsDirectoryPath
error:NULL];
for (NSString* curFileNamein [documentsDirectoryContentsobjectEnumerator]) {
//
NSString *filePath = [documentsDirectoryPathstringByAppendingPathComponent:curFileName];
//
BOOL isDirectory;
[[NSFileManagerdefaultManager] fileExistsAtPath:filePathisDirectory:&isDirectory];
// proceed to add the document URL to our list (ignore the "Inbox" folder)
if (!isDirectory)
{
//这里显示共享文件夹内的所有文件,如果想只显示你的PGN文件,就对curFileName是否是PGN进行判断
[dirArrayaddObject:curFileName];
}
}
//step6. 刷新列表,显示数据
[fileTableViewreloadData];
}
#pragma mark -
#pragma mark 文件变动监听方法结束
在viewDidLoad中加入相关代码
- (void)viewDidLoad {
[superviewDidLoad];
// Do any additional setup after loading the view from its nib.
//苹果监听Document目录的文件改动
// start monitoring the document directory…
docWatcher = [DirectoryWatcherwatchFolderWithPath:[selfapplicationDocumentsDirectory]delegate:self];
// scan for existing documents
[selfdirectoryDidChange:docWatcher];
//保存一份txt文件到设备document文件夹中(为了测试方便)
//NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
//NSString *documentsPath = [paths objectAtIndex:0]; //Get the docs directory
//NSString *filePath;
//char *saves = "test_files";
//NSData *data = [[NSData alloc] initWithBytes:saves length:10];
//filePath = [documentsPath stringByAppendingPathComponent:@"test.pgn"];
//[data writeToFile:filePath atomically:YES];
}
在TableView的代理方法中加入
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
//
return [dirArraycount];
}
//设置cell的显示
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//
staticNSString *SimpleTableIdentifier =@"SimpleTableIdentifier";
UITableViewCell *cell = [tableViewdequeueReusableCellWithIdentifier:SimpleTableIdentifier];
if (cell ==nil) {
cell = [[UITableViewCellalloc]
initWithStyle:UITableViewCellStyleSubtitlereuseIdentifier:SimpleTableIdentifier];
}
NSUInteger row = [indexPathrow];
NSString *str = [dirArrayobjectAtIndex:row];
cell.textLabel.text = str;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//选中某文件,读取文件
NSString *str = [dirArrayobjectAtIndex:[indexPathrow]];
NSString *path=[[NSHomeDirectory()stringByAppendingPathComponent:@"Documents"]stringByAppendingPathComponent:str];
NSData *reader = [NSDatadataWithContentsOfFile:path];
//获得reader后,你想干什么,就是你自己的事了,哈哈。
}
- 如何读取IOS共享目录的文件
- C# 读取共享目录文件
- qt iOS app 如何获取共享文件夹文件,如何使用document文档目录文件
- VM ubutun 下如何共享WINDOWS的文件目录
- sqlite如何读取指定目录下的db文件
- 如何读取assets目录下存放的原生资源文件
- 如何使用DDMS读取data/data目录下的文件
- Java如何读取Resources目录下的文件
- 读取共享文档的文件
- .net 如何读取共享文件 (UNC)
- Java的目录文件读取
- Java的目录文件读取
- 读取当前目录的文件
- iOS如何设置app支持文件共享
- iOS如何设置app支持文件共享
- IOS应用如何配置iTunes文件共享
- 【iOS】如何设置app支持文件共享
- 让自己开发的iOS App通过iTunes共享文件到Document目录
- http/https 1.0、1.1、2.0
- 数据结构实验之栈六:下一较大值(二)
- 回调函数
- 编程语言——C#基础知识
- HDU 2017多校联赛-Is Derek lying?
- 如何读取IOS共享目录的文件
- vue.js初学记录
- json(pickle)用法记录
- 常见错误:赋值和恒等混淆
- hdu 6053 TrickGCD(容斥,分段,莫比乌斯函数)
- odoo在Windows平台下部署无内容显示问题
- 用arm-linux-gdb调试ARM上的应用程序
- 使用Spring的@Scheduled实现定时任务
- yii2.0 最简单rbac实现方法