《iOS 6高级开发手册(第4版)》——2.3节秘诀:监测Documents文件夹
本节书摘来自异步社区《iOS 6高级开发手册(第4版)》一书中的第2章,第2.3节秘诀:监测Documents文件夹,作者 【美】Erica Sadun,更多章节内容可以访问云栖社区“异步社区”公众号查看
2.3 秘诀:监测Documents文件夹
iOS 6高级开发手册(第4版)
iOS文档并没有受困在它们的沙盒中,你可以并且应该与用户共享它们。应该允许用户直接控制他们的文档,以及访问他们可能在设备上创建的任何资料。一个简单的Info.plist设置将使iTunes能够显示用户的Documents文件夹的内容,并使那些用户能够根据需要添加和删除资料。
在将来某个时间,你可能使用一个简单的NSMetadataQuery监测器来监视Documents文件夹并报告更新。在编写本书时,元数据监视还没有扩展到iCloud之外以用于其他的文件夹。从OS X导出的代码无法像期望的那样在iOS上工作。目前,准确地讲,有两个搜索域可供iOS使用:即普遍存在的数据范围和普遍存在的文档范围(即iCloud和iCloud)。
直到iOS中出现了一般的功能之后,才能使用kqueue。这种老式技术提供了可伸缩的事件通知。利用kqueue,可以监测添加和清除事件。这粗略地等同于寻找要添加和删除的文件,它们是你想做出反应的主要更新类型。秘诀2-3展示了一个用于监视Documents文件夹的kqueue实现。
2.3.1 支持文档文件共享
要支持文件共享,可以向应用程序的Info.plist中添加一个UIFileSharingEnabled键,并把它的值设置为YES,如图2-2所示。在处理非原始的键和值时,这个项目被称为支持iTunes文件共享的Application。iTunes将在每个设备的Apps选项卡中列出所有声明文件共享支持的应用程序,如图2-3所示。
在iTunes中,将在设备的Apps选项卡中列出每个安装的声明了UIFileSharingEnabled的应用程序
2.3.2 用户控制
不能指定在Documents文件夹中允许存放哪些类型的项目。用户可以添加他们喜欢的任何项目,以及删除他们希望删除的任何项目。不过,他们不能做的是使用iTunes界面导航子文件夹。注意图2-3中的Inbox文件夹,这是一个从应用程序之间的文档共享中遗留下来的工件,但它不应该出现在那里。用户不能直接管理数据,不应该把子文件夹留在那里以使他们混淆。
用户在iTunes中不能像删除其他文件和文件夹那样删除Inbox,应用程序应该也不能直接把文件写到Inbox中。尊重Inbox的角色,它用于捕获从其他应用程序传入的任何数据。在实现文件共享支持时,总是要检查Inbox以恢复活动状态,并且处理该数据以清空Inbox,以及无论何时应用程序启动和恢复运行时都要删除它。在本章后面将讨论处理传入的文档的最佳实践。
2.3.3 Xcode访问
作为一位开发人员,你不仅能够访问Documents文件夹,而且能够访问整个应用程序沙盒。使用Xcode Organizer (Command-2) > Devices选项卡>“设备”> Applications >“应用程序名称”可以浏览沙盒,以及从中上传和下载文件。
通过启用应用程序的UIFileSharingEnabled属性,可以测试基本的文件共享,以及把数据加载到Documents文件夹中。在创建了那些文件之后,可以使用Xcode和iTunes检查、下载和删除它们。
2.3.4 扫描新文档
秘诀2-3通过在其beginGeneratingDocumentNotificationsInPath:方法中请求kqueue通知来工作。在这里,它获取一个用于你所提供的路径(在这里是Documents文件夹)的文件描述符,并请求用于添加和清除事件的通知。它将把这个功能添加到当前的运行循环中,无论何时监测的文件夹更新,都会启用通知。
一旦接收到那个回调,它将发布一条通知(我自定义的kDocumentChanged,在kqueueFired方法中),并且继承监视新事件。在主线程上的主运行循环中都会运行它,因此一旦接收到通知,GUI就可以响应并更新它自身。
下面的代码段演示了如何使用秘诀2-3的监视器来更新GUI中的文件列表。无论何时内容改变了,更新通知都允许应用程序刷新那些目录内容清单:
- (void) scanDocuments
{
NSString *path = [NSHomeDirectory()
stringByAppendingPathComponent:@"Documents"];
items = [[NSFileManager defaultManager]
contentsOfDirectoryAtPath:path error:nil];
[self.tableView reloadData];
}
- (void) loadView
{
[self.tableView registerClass:[UITableViewCell class]
forCellReuseIdentifier:@"cell"];
[self scanDocuments];
// React to content changes
[[NSNotificationCenter defaultCenter]
addObserverForName:kDocumentChanged
object:nil queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification *notification){
[self scanDocuments];
}];
// Start the watcher
NSString *path = [NSHomeDirectory()
stringByAppendingPathComponent:@"Documents"];
helper = [DocWatchHelper watcherForPath:path];
}
把设备连接到iTunes,测试这个秘诀。使用iTunes App选项卡界面添加和删除项目。设备的机载文件列表将会更新,以实时反映那些改变。
在使用这个秘诀时,要知道一些警告。首先,对于较大的文档,在收到了创建它们的通知之后,不应该立即阅读它们。你可能希望调查文件大小,以确定何时应该停止写入数据。第二,iTunes File Sharing在必要时可以暂缓传输,要相应地进行编码。
秘诀2-3 使用kqueue文件监测器
#import <fcntl.h>
#import <sys/event.h>
#define kDocumentChanged \
@"DocumentsFolderContentsDidChangeNotification"
@interface DocWatchHelper : NSObject
{
CFFileDescriptorRef kqref;
CFRunLoopSourceRef rls;
}
@property (strong) NSString *path;
+ (id) watcherForPath: (NSString *) aPath;
@end
@implementation DocWatchHelper
@synthesize path;
- (void)kqueueFired
{
int kq;
struct kevent event;
struct timespec timeout = { 0, 0 };
int eventCount;
kq = CFFileDescriptorGetNativeDescriptor(self->kqref);
assert(kq >= 0);
eventCount = kevent(kq, NULL, 0, &event, 1, &timeout);
assert( (eventCount >= 0) && (eventCount < 2) );
if (eventCount == 1)
[[NSNotificationCenter defaultCenter]
postNotificationName:kDocumentChanged
object:self];
CFFileDescriptorEnableCallBacks(self->kqref,
kCFFileDescriptorReadCallBack);
}
static void KQCallback(CFFileDescriptorRef kqRef,
CFOptionFlags callBackTypes, void *info)
{
DocWatchHelper *helper =
(DocWatchHelper *)(__bridge id)(CFTypeRef) info;
[helper kqueueFired];
}
- (void) beginGeneratingDocumentNotificationsInPath:
(NSString *) docPath
{
int dirFD;
int kq;
int retVal;
struct kevent eventToAdd;
CFFileDescriptorContext context =
{ 0, (void *)(__bridge CFTypeRef) self,
NULL, NULL, NULL };
dirFD = open([docPath fileSystemRepresentation], O_EVTONLY);
assert(dirFD >= 0);
kq = kqueue();
assert(kq >= 0);
eventToAdd.ident = dirFD;
eventToAdd.filter = EVFILT_VNODE;
eventToAdd.flags = EV_ADD | EV_CLEAR;
eventToAdd.fflags = NOTE_WRITE;
eventToAdd.data = 0;
eventToAdd.udata = NULL;
retVal = kevent(kq, &eventToAdd, 1, NULL, 0, NULL);
assert(retVal == 0);
self->kqref = CFFileDescriptorCreate(NULL, kq,
true, KQCallback, &context);
rls = CFFileDescriptorCreateRunLoopSource(
NULL, self->kqref, 0);
assert(rls != NULL);
CFRunLoopAddSource(CFRunLoopGetCurrent(), rls,
kCFRunLoopDefaultMode);
CFRelease(rls);
CFFileDescriptorEnableCallBacks(self->kqref,
kCFFileDescriptorReadCallBack);
}
- (void) dealloc
{
self.path = nil;
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), rls,
kCFRunLoopDefaultMode);
CFFileDescriptorDisableCallBacks(self->kqref,
kCFFileDescriptorReadCallBack);
}
+ (id) watcherForPath: (NSString *) aPath
{
DocWatchHelper *watcher = [[self alloc] init];
watcher.path = aPath;
[watcher beginGeneratingDocumentNotificationsInPath:aPath];
return watcher;
}
@end
关注公众号
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
-
上一篇
《Android游戏开发详解》——第1章,第1.4节关于位的一切(位和字节的简单介绍)
本节书摘来自异步社区《Android游戏开发详解》一书中的第1章,第1.4节关于位的一切(位和字节的简单介绍),作者 【美】Jonathan S. Harbour,更多章节内容可以访问云栖社区“异步社区”公众号查看 1.4 关于位的一切(位和字节的简单介绍)Android游戏开发详解在我们继续深入之前,值得先细致地介绍如何具体把值存储到变量中。我前面提到,不同的基本数据类型具有不同的位大小。例如,一个int有32位而一个long有64位。你可能会问,那么,到底什么是位? 位(bit)是一个二进制位的简称。换句话说,如果你有一个只有0和1的二进制数,每个数字就是1位。达到8位的时候,例如,(10101001),你就有了1字节。 对于位,你需要记住的一点是:拥有的位越多,所能表示的数值也越多。为了说明这一点,让我们问一个问题。十进制的1位能够表示多少个数字?当然是10个(0,1,2,3,4,5,6,7,8和9)。两位呢?100个(00,01……99)。我们看到,每增加一个位数,都会使得我们所能表示的数值增多到原来的10倍。对于二进制数字来说,也是如此,只不过每次增加一位,所能表示的数值的数...
-
下一篇
《Android应用开发入门经典(第3版)》——第6.7节问与答
本节书摘来自异步社区《Android应用开发入门经典(第3版)》一书中的第6章,第6.7节问与答,作者 【美】Carmen Delessio , Lauren Darcey , Shane Conder,更多章节内容可以访问云栖社区“异步社区”公众号查看 6.7 问与答Android应用开发入门经典(第3版)问题:Spinner和AutoCompleteTextView之间存在什么区别? 答案:两者都使用了 Adapter,向用户显示信息,然后向用户收集信息。主要的差别在于Spinner向用户展示了一个预先设定好的额列表,用户必须从列表中选择一项。而对于AutoCompleteTextView来讲,单词列表仅仅是建议。用户完全可以输入一些全新的东西。对于Spinner可以通过引用被选中的条目的方法来获取数据。而在AutoCompleteTextView则使用getText()来获取数据。 问题:本章覆盖了在一个Android应用中可以使用的所有视图吗? 答案:没有,没有完全覆盖。本章介绍了常见的控件并展示了一些用法。使用不同的视图是一种更好地理解它们的方法。
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2整合Redis,开启缓存,提高访问速度
- Linux系统CentOS6、CentOS7手动修改IP地址
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- Crontab安装和使用
- Docker安装Oracle12C,快速搭建Oracle学习环境
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Dcoker安装(在线仓库),最新的服务器搭配容器使用

微信收款码
支付宝收款码