Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TIMOB-25912] (7_1_X) iOS 11.2: Fix document-viewer URL directory #9977

Merged
merged 3 commits into from
Apr 3, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 5 additions & 5 deletions apidoc/Titanium/UI/iOS/DocumentViewer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ description: |

**Note for iOS 11.2 and later**
Apple introduced a regression in iOS 11.2 that forces **all** files to be in the application data
directory or temporary directory. We handle this workaround for you in Titanium SDK 7.0.2+, but you
directory. We handle this workaround for you in Titanium SDK 7.0.2+, but you
can also work around it without an SDK update. Here is an example:

var fileName = 'example.pdf';
Expand All @@ -48,7 +48,7 @@ description: |
// reference it. It will be removed from filesystem once the app closes.
// Read more here: http://nshipster.com/nstemporarydirectory/
if (isiOS11_2()) {
fileName = fileInTemporaryDirectory(fileName);
fileName = fileInApplicationDataDirectory(fileName);
}

var docViewer = Ti.UI.iOS.createDocumentViewer({
Expand All @@ -66,19 +66,19 @@ description: |
// Create a temporary file with the contents of the old file
// Expects the file to be in the resources directory. If you receive the file
// from an API-call, receive pass the Ti.Blob/Ti.File/text to "write" directly.
function fileInTemporaryDirectory(fileName) {
function fileInApplicationDataDirectory(fileName) {
var file = Ti.Filesystem.getFile(Ti.Filesystem.resourcesDirectory, fileName);

if (!file.exists()) {
alert('File does not exist in resources!');
return;
}

var newFile = Titanium.Filesystem.getFile(Ti.Filesystem.tempDirectory, fileName);
var newFile = Titanium.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, fileName);
newFile.createFile();

if (!newFile.exists()) {
alert('New file could not be created in temporary directory!');
alert('New file could not be created in application data directory!');
return;
}

Expand Down
47 changes: 24 additions & 23 deletions iphone/Classes/TiUIiOSDocumentViewerProxy.m
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ - (id)name
// Workaround for an issue occuring on iOS 11.2+ that causes
// files from the resources-directory (app-bundle) to not be
// recognized properly. This method works around this by creating
// a temporary file that is flushed after the app terminates.
// a temporary file.
- (NSURL *)_toURL:(NSString *)object proxy:(TiProxy *)proxy
{
if (![TiUtils isIOSVersionOrGreater:@"11.2"]) {
Expand All @@ -128,39 +128,36 @@ - (NSURL *)_toURL:(NSString *)object proxy:(TiProxy *)proxy
NSURL *fileURL = [TiUtils toURL:object proxy:self];
NSString *fileName = [[fileURL absoluteString] lastPathComponent];

// Check if the file already exists in the application-data-directory.
// If so, return it.
// If the original (!) file already exists in the application-data-directory, return it!
NSString *documentsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
NSString *file = [documentsPath stringByAppendingPathComponent:fileName];

if ([[NSFileManager defaultManager] fileExistsAtPath:file]) {
return fileURL;
}

// Check if the file already exists in the cache-directory.
// If so, return it.
NSArray *tmpDirectory = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:NSTemporaryDirectory() error:NULL];
for (NSString *file in tmpDirectory) {
if ([file isEqualToString:fileName]) {
return [NSURL fileURLWithPath:file relativeToURL:[NSURL fileURLWithPath:NSTemporaryDirectory() isDirectory:YES]];
}
// If the file does not exist in the application data directory, create it!
NSString *generatedFileName = [NSString stringWithFormat:@"tmp-%@", fileName];
NSError *error = nil;
NSURL *fixedURL = [NSURL fileURLWithPath:documentsPath isDirectory:YES];

// If the generated (!) file already exists in the application-data-directory, return it as well!
if ([[NSFileManager defaultManager] fileExistsAtPath:fixedURL.path]) {
return fileURL;
}

// If the file does not exist in the temporary- and application-data-directory,
// create it in the temporary directory.
NSError *error = nil;
NSURL *temporaryURL = [NSURL fileURLWithPath:NSTemporaryDirectory() isDirectory:YES];
[[NSFileManager defaultManager] copyItemAtURL:fileURL
toURL:[temporaryURL URLByAppendingPathComponent:fileName]
toURL:[fixedURL URLByAppendingPathComponent:generatedFileName]
error:&error];

// In case the file could not be copied, return the old URL and warn the user
if (error != nil) {
NSLog(@"[ERROR] Could not copy file to temporary directory automatically, copy it manually to work around the Apple iOS 11.2+ bug.");
NSLog(@"[ERROR] Could not copy file to application data directory automatically, please copy it manually to work around the Apple iOS 11.2+ bug.");
NSLog(@"[ERROR] %@", error.localizedDescription);
return fileURL;
}

return [temporaryURL URLByAppendingPathComponent:fileName];
return [fixedURL URLByAppendingPathComponent:generatedFileName];
}

#pragma mark Delegates
Expand All @@ -170,12 +167,6 @@ - (UIViewController *)documentInteractionControllerViewControllerForPreview:(UID
return [[TiApp controller] topPresentedController];
}

/*
- (UIView *)documentInteractionControllerViewForPreview:(UIDocumentInteractionController *)controller
{
return viewController.view;
}*/

- (void)documentInteractionControllerWillBeginPreview:(UIDocumentInteractionController *)controller
{
if ([self _hasListeners:@"load"]) {
Expand All @@ -185,6 +176,16 @@ - (void)documentInteractionControllerWillBeginPreview:(UIDocumentInteractionCont

- (void)documentInteractionControllerDidEndPreview:(UIDocumentInteractionController *)controller
{
// Delete temporary copied files from application data directory again
if ([controller.URL.lastPathComponent hasPrefix:@"tmp-"]) {
NSError *error = nil;
[[NSFileManager defaultManager] removeItemAtURL:controller.URL error:&error];

if (error != nil) {
DebugLog(@"[ERROR] Error removing temporary file from application data directory: %@", error.localizedDescription);
}
}

if ([self _hasListeners:@"unload"]) {
[self fireEvent:@"unload" withObject:nil];
}
Expand Down