使用NSmetadataQuery查询文档,增加,删除,编辑
界面设计完成后效果如图:
程序清单:FKDiary.h
@interface FKDiary : UIDocument @property (nonatomic,strong) NSData *diaryData; @property (nonatomic,copy) NSString *fileURL; @end
程序清单FKDiary.m
#import "FKDiary.h" @implementation FKDiary //保存该对象时自动调用该方法 -(id)contentsForType:(NSString *)typeName error:(NSError *__autoreleasing *)outError { NSLog(@"保存文件到URl %@!",self.fileURL); if (self.diaryData == nil) { return [[NSData alloc]init]; } //将diaryData作为放回值,程序将会把该返回值保存到云端 return [self.diaryData copy]; } //读取该对象时自动调用该方法 -(BOOL)loadFromContents:(id)contents ofType:(NSString *)typeName error:(NSError *__autoreleasing *)outError { NSLog(@"从云端下载的数据为:%@",contents); //将从云端下载得到的数据赋给diaryData数据 self.diaryData = [contents mutableCopy]; return true; }
程序清单:FKMasterController.m
#import "FKDiary.h" #import "ViewController.h" @interface FKMasterController ()<UIAlertViewDelegate> { //定义导航栏左边的按钮 UIBarButtonItem *deleteButton; } @property (strong,nonatomic)NSMetadataQuery *query; @property (strong,nonatomic)NSMutableArray *documentFilenames; @property (strong,nonatomic)NSMutableArray *documentURLs; @property (strong,nonatomic)FKDiary *chosenDiary; @end @implementation FKMasterController - (void)viewDidLoad { [super viewDidLoad]; //创建导航栏邮编的按钮 UIBarButtonItem *addButton = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addDiary)]; //将导航栏按钮设置为导航栏的右边按钮 self.navigationItem.rightBarButtonItem = addButton; //创建导航栏左边的按钮 deleteButton = [[UIBarButtonItem alloc]initWithTitle:@"删除" style:UIBarButtonItemStylePlain target:self action:@selector(deleteDiary)]; //创建导航栏左边的按niu self.navigationItem.leftBarButtonItem = deleteButton; //调用reloadFiles从云端下载文件 [self reloadFiles]; } -(void)addDiary { //使用UIAlertView来获取文件名字 UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"输入日记名" message:@"输入日记名称" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"创建", nil]; //设置该UIAlertView的风格为带输入框的UIAlertView alert.alertViewStyle = UIAlertViewStylePlainTextInput; [alert show]; } -(NSURL *)urlForFilename:(NSString *)filename { //获取默认的NSFileManager对象 NSFileManager *fileManager = [NSFileManager defaultManager]; //根据Identifier获取系统的Ubiquity Container //如果传入nil参数,则默认获取第一个Ubiquity Container NSURL *baseURL = [fileManager URLForUbiquityContainerIdentifier:nil]; //获取云端Ubiquity Container的Documents子目录 NSURL *pathURL = [baseURL URLByAppendingPathComponent:@"Documents"]; //在Documents子目录下添加文件名,作为保存文件的URL NSURL *destinationURL = [pathURL URLByAppendingPathComponent:filename]; return destinationURL; } -(void)reloadFiles { //创建一个NSMetataQuery对象 self.query = [[NSMetadataQuery alloc]init]; //设置查询谓词 self.query.predicate = [NSPredicate predicateWithFormat:@"%K like '*.diary'",NSMetadataItemFSNameKey]; //设置查询范围,此处指定查询范围为NSMetadataQueryUbiquitousDocumentsScope // 即在云端的Documents目录下查询 self.query.searchScopes = [NSArray arrayWithObject:NSMetadataQueryUbiquitousDataScope]; //获取数据结束时激发updateUbiquitousDocuments方法 [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(updateUbiquitousDocuments:) name:NSMetadataQueryDidFinishGatheringNotification object:nil]; //查询更新完成时激发updateUbiquitousDocuments方法 [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(updateUbiquitousDocuments:) name:NSMetadataQueryDidUpdateNotification object:nil]; //开始查询 [self.query startQuery]; } -(void)updateUbiquitousDocuments:(NSNotification *)notification { self.documentURLs = [NSMutableArray array]; self.documentFilenames = [NSMutableArray array]; //对查询结果进行排序,排序所使用的比较标准是创建时间 NSArray *results = [self.query.results sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) { NSMetadataItem *item1 = obj1; NSMetadataItem *item2 = obj2; //比较两个NSMetadataItem的时间 return [[item2 valueForAttribute:NSMetadataItemFSCreationDateKey] compare:[item1 valueForAttribute:NSMetadataItemFSCreationDateKey]]; }]; //遍历查询结果 for (NSMetadataItem *item in results) { //查询结果中包含的NSURL属性 NSURL *url = [item valueForAttribute: NSMetadataItemURLKey]; //将NSURL添加到documentURLs集合中 [self.documentURLs addObject:url]; //将NSURL的最后一个路径(文件名)添加到documentfilenames集合中 [self.documentFilenames addObject:url]; } //控制界面上表哥重新加载数据 [self.tableView reloadData]; } -(void)perpareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { //如果sender等于self,则表明是新建FKDiary后导航到查看,编辑日记的视图空孩子气 if (sender == self) { UIViewController *destination = segue.destinationViewController; //将用户新建的FKDiary对象传给目标视图控制器 if ([destination respondsToSelector:@selector(setDetailItem:)]) { [destination setValue:self.chosenDiary forKey:@"detailItem"]; } }else { //获取激发视图切换的单元格所在的NSIndexPath NSIndexPath *indexPath = [self.tableView indexPathForCell:sender]; //获取激发视图切换的单元格中显示的文件名 NSString *filename = [self.documentFilenames objectAtIndex:indexPath.row]; //获取该文件名对应的FKDiary的存储URL NSURL *docURl = [self urlForFilename:filename]; //以指定的docUrl创建FKDiary对象 self.chosenDiary = [[FKDiary alloc]initWithFileURL:docURl]; //读取chosenDiary文档 [self.chosenDiary openWithCompletionHandler:^(BOOL success) { //如果读取成功 if (success) { ViewController *destination = (ViewController *)segue.destinationViewController; //将读取成功的chosenDiary传给destination destination.detailItem = self.chosenDiary; //调用destination的changeDisplay更新显示 [destination changeDisplay]; } else { NSLog(@"failed to load!"); } }]; } } -(void)deleteDiary { //使用动画切换表格的编辑状态 [self.tableView setEditing: !self.tableView.editing animated:YES]; //修改deleteButton按钮的文本 deleteButton.title = [deleteButton.title isEqualToString:@"删除"]?@"完成":@"删除"; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { // Return the number of sections. return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { // Return the number of rows in the section. return [self.documentFilenames count]; } #pragma mark - UIAlertViewDelegate -(void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex { if (buttonIndex == 1) { //获取用户zaiUIAlerView中输入的文件名,并添加.diary扩展名 NSString *filename = [NSString stringWithFormat:@"%@.diary",[alertView textFieldAtIndex:0].text]; //获取云端文档存储的url NSURL *saveURL = [self urlForFilename:filename]; //创建一个fKDiary (UIDocument的子类)对象 self.chosenDiary = [[FKDiary alloc]initWithFileURL:saveURL]; //保存chosenDiary文档 [self.chosenDiary saveToURL:saveURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) { if(success) { NSLog(@"保存成功"); [self reloadFiles]; //执行masterTodetail segue,导航到查看,编辑日记的视图控制器 [self performSegueWithIdentifier:@"masterToDetail" sender:self]; }else { NSLog(@"保存失败"); } }]; } } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cellID" forIndexPath:indexPath]; //根据单元格所在的行号获取对应的文档名 NSString *path = [self.documentFilenames objectAtIndex:indexPath.row]; //设置该单元格的文本为文档名取消后缀 cell.textLabel.text = path.lastPathComponent.stringByDeletingPathExtension; // Configure the cell... return cell; } - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath { //返回UITableViewCellEditingStyleDeleter代表删除 return UITableViewCellEditingStyleDelete; } /* // Override to support conditional editing of the table view. - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { // Return NO if you do not want the specified item to be editable. return YES; } */ // Override to support editing the table view. - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { // Delete the row from the data source //获取用户视图删除的行号 NSInteger rowNo = [indexPath row]; //调用NSfileMangaer的removeItemAtURL:error:方法即可删除云端文档 [[NSFileManager defaultManager]removeItemAtURL:[self.documentURLs objectAtIndex:rowNo] error:nil]; //从底层NSArray集合中删除指定数据项 [self.documentFilenames removeObjectAtIndex:rowNo]; //从UITableView程序界面删删除指定表格行 [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; } else if (editingStyle == UITableViewCellEditingStyleInsert) { // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view } }