iOS/CloudSearch/AAPLTableViewController.m
/* |
Copyright (C) 2016 Apple Inc. All Rights Reserved. |
See LICENSE.txt for this sample’s licensing information |
Abstract: |
The primary view controller for displaying iCloud documents. |
*/ |
#import "AAPLTableViewController.h" |
#import "AAPLCloudDocumentsController.h" |
#import "AAPLFilterViewController.h" |
enum FilterTableItems |
{ |
kTXTItem = 0, |
kJPGItem, |
kPDFItem, |
kHTMLItem, |
kVideoItem, |
kNoneItem |
}; |
@interface AAPLTableViewController () <AAPLCloudDocumentsControllerDelegate, AAPLFilterViewControllerDelegate> |
@property (nonatomic, strong) id ubiquityToken; |
@property (nonatomic, strong) NSURL *ubiquityContainer; |
@property (nonatomic, strong) NSDateFormatter *dateFormatter; |
@property (nonatomic, strong) NSIndexPath *currentExtension; |
@property (nonatomic, weak) IBOutlet UIView *switchView; |
@property (nonatomic, weak) IBOutlet UISwitch *thumbSwitch; |
@property (nonatomic, strong) UIActivityIndicatorView *activityIndicator; |
@end |
#pragma mark - |
@implementation AAPLTableViewController |
// ------------------------------------------------------------------------------- |
// initiateScan |
// ------------------------------------------------------------------------------- |
- (void)initiateScan |
{ |
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ |
// remember our ubiquity container NSURL for later use |
_ubiquityContainer = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]; |
dispatch_async(dispatch_get_main_queue(), ^{ |
// we are connected to iCloud, start scanning for documents |
if ([self isLoggedIn]) |
{ |
if (![[AAPLCloudDocumentsController sharedInstance] startScanning]) |
{ |
// present an error to say that it wasn't possible to start the iCloud query |
// |
UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil |
message:NSLocalizedString(@"Search_Failed", nil) |
preferredStyle:UIAlertControllerStyleAlert]; |
UIAlertAction *OKAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK_Button_Title", nil) |
style:UIAlertActionStyleDefault |
handler:nil]; |
[alert addAction:OKAction]; |
[self.navigationController presentViewController:alert animated:YES completion:nil]; |
} |
} |
}); |
}); |
} |
// ------------------------------------------------------------------------------- |
// rescanForDocuments |
// |
// Called from our app delegate in case it wants to rescan for documents |
// (likely when default documents are first copied up to the cloud) |
// ------------------------------------------------------------------------------- |
- (void)rescanForDocuments |
{ |
if (self.activityIndicator == nil) |
{ |
// create and center the activity indicator to our table |
_activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; |
[self.tableView addSubview:self.activityIndicator]; |
self.activityIndicator.translatesAutoresizingMaskIntoConstraints = NO; |
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.activityIndicator |
attribute:NSLayoutAttributeCenterX |
relatedBy:NSLayoutRelationEqual |
toItem:self.view |
attribute:NSLayoutAttributeCenterX |
multiplier:1.0 |
constant:0.0]]; |
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.activityIndicator |
attribute:NSLayoutAttributeTop |
relatedBy:NSLayoutRelationEqual |
toItem:self.view |
attribute:NSLayoutAttributeTop |
multiplier:1.0 |
constant:12.0]]; |
} |
[self.activityIndicator startAnimating]; |
[[AAPLCloudDocumentsController sharedInstance] restartScan]; |
} |
// ------------------------------------------------------------------------------- |
// viewDidLoad |
// ------------------------------------------------------------------------------- |
- (void)viewDidLoad |
{ |
[super viewDidLoad]; |
// create our refresh control so users can rescan for cloud content |
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] initWithFrame:CGRectZero]; |
[refreshControl addTarget:self action:@selector(refresh:) forControlEvents:UIControlEventValueChanged]; |
self.refreshControl = refreshControl; |
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:self.switchView]; |
// remember our login token in case the user logs out or logs in with a different account |
_ubiquityToken = [NSFileManager defaultManager].ubiquityIdentityToken; |
// listen for when the current ubiquity identity has changed (user logs in and out of iCloud) |
[[NSNotificationCenter defaultCenter] addObserver:self |
selector:@selector(ubiquityIdentityChanged:) |
name:NSUbiquityIdentityDidChangeNotification |
object:nil]; |
_dateFormatter = [[NSDateFormatter alloc] init]; |
(self.dateFormatter).dateStyle = NSDateFormatterLongStyle; |
AAPLCloudDocumentsController *docsController = [AAPLCloudDocumentsController sharedInstance]; |
docsController.delegate = self; // we need to be notified when cloud docs are found |
_currentExtension = [NSIndexPath indexPathForRow:kNoneItem inSection:0]; |
// obtain our ubiquity container identifier and start the scan for documents |
[self initiateScan]; |
} |
// ------------------------------------------------------------------------------- |
// dealloc |
// ------------------------------------------------------------------------------- |
- (void)dealloc |
{ |
[[NSNotificationCenter defaultCenter] removeObserver:self |
name:NSUbiquityIdentityDidChangeNotification |
object:nil]; |
} |
// ------------------------------------------------------------------------------- |
// isLoggedIn |
// ------------------------------------------------------------------------------- |
- (BOOL)isLoggedIn |
{ |
return (self.ubiquityContainer != nil); |
} |
#pragma mark - Actions |
// ------------------------------------------------------------------------------- |
// refresh:sender |
// |
// Called when UIRefreshControl is pulled down from our table |
// ------------------------------------------------------------------------------- |
- (void)refresh:(id)sender |
{ |
if ([self isLoggedIn]) |
{ |
[[AAPLCloudDocumentsController sharedInstance] restartScan]; |
} |
else |
{ |
[self.refreshControl endRefreshing]; |
} |
} |
// ------------------------------------------------------------------------------- |
// useThumbnail:sender |
// ------------------------------------------------------------------------------- |
- (IBAction)useThumbnail:(id)sender |
{ |
if ([self isLoggedIn]) |
{ |
[[AAPLCloudDocumentsController sharedInstance] restartScan]; |
} |
} |
#pragma mark - UITableViewDataSource |
// ------------------------------------------------------------------------------- |
// numberOfRowsInSection:section |
// ------------------------------------------------------------------------------- |
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section |
{ |
return [AAPLCloudDocumentsController sharedInstance].numberOfDocuments; |
} |
// ------------------------------------------------------------------------------- |
// cellForRowAtIndexPath:indexPath |
// ------------------------------------------------------------------------------- |
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath |
{ |
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cellID" forIndexPath:indexPath]; |
AAPLCloudDocumentsController *docsController = [AAPLCloudDocumentsController sharedInstance]; |
// Note: |
// Some key/values might not available right now probably because of early login state or |
// document is not fully downloaded. So we take that into account when building our table cell. |
// We will eventually get our data when our AAPLCloudDocumentsController's NSMetaDataQuery notifies us of an update |
// |
NSString *docTitle = [docsController localizedTitleForDocumentAtIndex:indexPath.row]; |
cell.textLabel.text = (docTitle != nil) ? docTitle : [[AAPLCloudDocumentsController sharedInstance] documentTitleForDocumentAtIndex:indexPath.row]; |
// first we attempt to use what the UI dictates (thumbnail vs. icon) |
if (self.thumbSwitch.isOn) |
{ |
UIImage *thumbnailImage = [docsController thumbNailForDocumentAtIndex:indexPath.row]; |
cell.imageView.image = (thumbnailImage != nil) ? thumbnailImage : [docsController iconForDocumentAtIndex:indexPath.row]; |
} |
else |
{ |
// no thumbnails wanted, use the generic icon |
cell.imageView.image = [docsController iconForDocumentAtIndex:indexPath.row]; |
} |
NSString *modDateStr = [self.dateFormatter stringFromDate:[docsController modDateForDocumentAtIndex:indexPath.row]]; |
cell.detailTextLabel.text = (modDateStr != nil) ? modDateStr : @"-"; |
NSString *downloadedStateStr = [docsController documentIsDownloadedAtIndex:indexPath.row] ? @"Downloaded\nYes" : @"DownLoaded\nNo"; |
UILabel *downloadStateLabel = [[UILabel alloc] init]; |
downloadStateLabel.font = [UIFont systemFontOfSize:9.0]; |
downloadStateLabel.text = downloadedStateStr; |
downloadStateLabel.numberOfLines = 2; |
downloadStateLabel.textAlignment = NSTextAlignmentCenter; |
[downloadStateLabel sizeToFit]; |
cell.accessoryView = downloadStateLabel; |
return cell; |
} |
#pragma mark - CloudDocumentsControllerDelegate |
// ------------------------------------------------------------------------------- |
// didRetrieveCloudDocuments |
// ------------------------------------------------------------------------------- |
- (void)didRetrieveCloudDocuments |
{ |
self.activityIndicator.hidden = YES; |
[self.activityIndicator stopAnimating]; |
// we have stopped looking for documents, stop progress |
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO; |
[self.refreshControl endRefreshing]; |
[self.tableView reloadData]; |
} |
// ------------------------------------------------------------------------------- |
// didRetrieveCloudDocuments |
// ------------------------------------------------------------------------------- |
- (void)didStartRetrievingCloudDocuments |
{ |
// we are looking for documents, show progress |
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES; |
} |
// ------------------------------------------------------------------------------- |
// prepareForSegue:Sender |
// ------------------------------------------------------------------------------- |
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender |
{ |
// setup ourselves as delegate to "didSelectExtension" will be called |
UINavigationController *navController = (UINavigationController *)segue.destinationViewController; |
AAPLFilterViewController *filterViewController = (AAPLFilterViewController *)navController.visibleViewController; |
filterViewController.filterDelegate = self; |
filterViewController.extensionToFilter = self.currentExtension; |
} |
#pragma mark - AAPLFilterViewControllerDelegate |
// ------------------------------------------------------------------------------- |
// didSelectExtension:extension |
// ------------------------------------------------------------------------------- |
- (void)filterViewController:(AAPLFilterViewController *)viewController didSelectExtension:(NSIndexPath *)extension |
{ |
_currentExtension = extension; |
AAPLCloudDocumentsController *docsController = [AAPLCloudDocumentsController sharedInstance]; |
NSString *extensionToUse = nil; |
switch (extension.row) |
{ |
case kTXTItem: |
extensionToUse = @"txt"; |
break; |
case kJPGItem: |
extensionToUse = @"jpg"; |
break; |
case kPDFItem: |
extensionToUse = @"pdf"; |
break; |
case kHTMLItem: |
extensionToUse = @"html"; |
break; |
case kVideoItem: |
extensionToUse = @"m4v"; |
break; |
case kNoneItem: |
extensionToUse = @""; |
break; |
} |
docsController.fileType = extensionToUse; |
if ([self isLoggedIn]) |
{ |
[docsController restartScan]; |
} |
} |
#pragma mark - Notifications |
//---------------------------------------------------------------------------------------- |
// ubiquityIdentityChanged |
// |
// Notification that the user has either logged in our out of iCloud. |
//---------------------------------------------------------------------------------------- |
- (void)ubiquityIdentityChanged:(NSNotification *)note |
{ |
id token = [NSFileManager defaultManager].ubiquityIdentityToken; |
if (token == nil) |
{ |
// present an error to say that it wasn't possible to start the iCloud query |
// |
UIAlertController *alert = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Logged_Out_Message", nil) |
message:NSLocalizedString(@"Logged_Out_Message_Explain", nil) |
preferredStyle:UIAlertControllerStyleAlert]; |
UIAlertAction *OKAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK_Button_Title", nil) |
style:UIAlertActionStyleDefault |
handler:nil]; |
[alert addAction:OKAction]; |
[self.navigationController presentViewController:alert animated:YES completion:nil]; |
_ubiquityContainer = nil; // no more container to point to |
[self.tableView reloadData]; |
} |
else |
{ |
if ([self.ubiquityToken isEqual:token]) |
{ |
NSLog(@"user has stayed logged in with same account"); |
} |
else |
{ |
// user logged in with a different account |
NSLog(@"user logged in with a new account"); |
} |
// store off this token to compare later |
self.ubiquityToken = token; |
// re-obtain our ubiquity container identifier and start the scan for documents |
[self initiateScan]; |
} |
} |
@end |
Copyright © 2016 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2016-03-24