Error while saving JPG/PNG photo to gallery in IOS 11 - ios

I was testing our application on new device with beta iOS 11 and found an intresting error.
We are creating an image which can be saved to user gallery, using UIActivityViewController (some system share view controller):
NSMutableArray *sharingItems = [NSMutableArray new];
UIImage *screenShot = [self shareViewScreenShot];
NSString *filename = #"notImportant";
NSString *path = [NSString stringWithFormat:#"%#%#.jpg", NSTemporaryDirectory(), filename];
[UIImageJPEGRepresentation(screenShot, 1.0) writeToFile:path atomically:YES];
NSURL *pathUrl = [NSURL fileURLWithPath:path];
[sharingItems addObject:pathUrl];
UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:sharingItems applicationActivities:nil];
[self presentViewController:activityController animated:YES completion:nil];
This works fine, presenting share dialog, until user press "save image". Then I got error about not suporting this image format
2017-07-19 10:51:54.292881+0200 appName[6632:766119] Video
/private/var/mobile/Containers/Data/Application/29B8C33B-9247-45FE-B51F-A35A035019A9/tmp/notImportant.jpg
cannot be saved to the saved photos album: Error
Domain=AVFoundationErrorDomain Code=-11828 "Nie można otworzyć"
UserInfo={NSUnderlyingError=0x1c08558d0 {Error
Domain=NSOSStatusErrorDomain Code=-12847 "(null)"},
NSLocalizedFailureReason=Ten format multimediów nie jest obsługiwany.,
NSURL=file:///private/var/mobile/Containers/Data/Application/29B8C33B-9247-45FE-B51F-A35A035019A9/tmp/notImportant.jpg,
NSLocalizedDescription=Nie można otworzyć}
The same happens when I use png/UIImagePNGRepresentation.
So the questions are:
Are png/jpg supported in iOS 11?
Should I use/and how HEIF (new apple image format) for devices with os version >= 11?

NSOSStatusErrorDomain code means the property data size was not correct.
OSStatus is a type commonly used for error codes in OS X and iOS. If the magnitude of the code is less than 1 million, then the code is probably listed in MacErrors.h in the CarbonCore framework. Otherwise, it is probably a four-character code listed in the same header as the function which returned it. You can find the header of a function by command-clicking it in Xcode. The codes will most likely be listed near the top, grouped together. To convert the number to a code, use the Calculator app in Developer view to convert it to hexadecimal and convert each byte to a character.

iOS treates image as video? Is this a bug on iOS or some permission is missing.
Solution:
Add permissions that was missing in Info.plist file:
<key>NSPhotoLibraryUsageDescription</key>
<string>Application needs to access photos</string>
for iOS 11+
<key>NSPhotoLibraryAddUsageDescription</key>
<string>Application needs to access photos</string>
Now Save Image action is working ok.

Related

UIActivityViewController not showing PDF option

I know there are many posts on this type of thing. And I believe I have tried all of the suggestions. I have a very simple problem. I have a url to a PDF and I want to be able to "share" this to the adobe pdf reader app. To remove one of the possible issues I took the PDF I was downloading and put it into my bundle so it was local. I am on iOS 8.4. Here is the code I tried:
NSURL * url2 = [NSURL fileURLWithPath: [[NSBundle mainBundle] pathForResource: # "data" ofType: # "pdf"]];
//Tried with the data in the file
NSData *data2 = [NSData dataWithContentsOfURL:url2];
UIActivityViewController *act=[[UIActivityViewController alloc]initWithActivityItems:#[data2] applicationActivities:nil];
//Tried with just the URL
UIActivityViewController *act=[[UIActivityViewController alloc]initWithActivityItems:#[url2] applicationActivities:nil];
act.popoverPresentationController.barButtonItem = button;
act.popoverPresentationController.sourceView = self.view;
[self presentViewController:act animated:YES completion:nil];
return;
Neither of these show the PDF option. I of course have it installed and have run it once to make sure its registered properly. Both of these I can share to Mail and the actual file is sent fine but the only share options I get are Mail, Copy and Print. I would like to see the other options like Open in iBooks and Open in Adobe Acrobat like I get from safari.
Ideas?

UIActivityViewController thinks my jpg is video when share by file URL

I have jpg files saved in the Documents directory that can be shared from a standard UIActivityViewController. All activity items (including Save Image) work as expected, but when Save Image is tapped, the following error shows in the console, despite the fact that the jpg does actually get saved to the camera roll.
Is this a bug in iOS, or do I have to somehow specify that my file is a jpg (and not a video) in the file URL?
2015-07-29 06:46:58.317 AppName[4658:893408] Video /var/mobile/Containers/Data/Application/A63DF08E-21D0-435D-A0D7-84D73D632FC9/Documents/ImageStore/805/23.jpg cannot be saved to the saved photos album: Error Domain=AVFoundationErrorDomain Code=-11828 "Cannot Open" UserInfo=0x1702e8b80 {NSLocalizedFailureReason=This media format is not supported., NSLocalizedDescription=Cannot Open, NSURL=file:///var/mobile/Containers/Data/Application/A63DF08E-21D0-435D-A0D7-84D73D632FC9/Documents/ImageStore/805/23.jpg, NSUnderlyingError=0x170c4f9f0 "The operation couldn’t be completed. (OSStatus error -12847.)"}
Here's the code I'm using:
NSURL *fileURL = [NSURL fileURLWithPath: [...path to my file...] isDirectory:NO];
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:#[fileURL] applicationActivities:nil];
activityViewController.excludedActivityTypes = #[UIActivityTypeCopyToPasteboard, UIActivityTypePrint, UIActivityTypeAssignToContact, UIActivityTypeAddToReadingList, UIActivityTypePostToVimeo];
[self presentViewController:activityViewController animated:YES completion:nil];
I got the above message when trying to save a png file. Also noticed some other error messages. In tracking those down, got rid of both problems by applying the OS_ACTIVITY_MODE with disable as seen in following question/answer: "Reading from public effective user settings" in iOS 10

How to implement Open In apps for plain text

I would like to provide the ability for users to tap the Action button and up pops the usual share sheet, which should include other apps to the right of the Messages, Facebook, etc icons - applications that can work with .txt files, or just an NSString.
I am currently displaying a Share sheet via UIActivityViewController, which is working great but it does not include other apps in the list. From reading other SO questions I concluded it's only possible to get those other apps to appear if you use UIDocumentInteractionController instead. I looked into creating a .txt file in a temp directory to share that file (instead of just sharing an NSString), but only Mail (no Copy) shows up when I tap the Share button. [Do note that if I run it on a real device not the simulator more apps other than Mail will appear and AirDrop too.] When I tap Mail, the app crashes: Unable to get data for URL: The operation couldn’t be completed. (Cocoa error 260.) Something is wrong with the way I'm creating/retrieving the .txt file.
My questions are:
Why is my code resulting in a crash when attempting to share the .txt file?
How can I get the Copy option to appear in the same Share sheet as the one that includes other apps?
To summarize: I need a share sheet that includes: Copy, AirDrop, Messages, Mail, Facebook, Twitter, Pages, Dropbox, etc for a simple string of text. Thanks!
The following lines of code lie inside my IBAction share button tap function:
UIActivityViewController approach:
UIActivityViewController *activityView = [[UIActivityViewController alloc] initWithActivityItems:#[self.myUITextField.text] applicationActivities:nil];
[self presentViewController:activityView animated:YES completion:nil];
Result:
UIDocumentInteractionController approach:
NSString *fileName = [NSString stringWithFormat:#"%#mytextfile.txt", NSTemporaryDirectory()];
[self.myUITextField.text writeToFile:fileName
atomically:NO
encoding:NSStringEncodingConversionAllowLossy
error:nil];
NSURL *textFileURL = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:#"mytextfile.txt"]];
UIDocumentInteractionController *documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:textFileURL];
[documentInteractionController presentOptionsMenuFromBarButtonItem:sender animated:YES];
Result (will show more apps and AirDrop if I run on a real device):
Example of what I want to obtain - minus the 3 extra options at the bottom:
If I cannot obtain the above screenshot with a string (instead of a photo) for some reason, I am willing to implement it how Dropbox has done it. They added an Open In button at the bottom that presents a different sheet that only shows additional apps. Note that I would still need a Copy option on the original sheet.
Question 1: Why is my code resulting in a crash
Cocoa error 260 is an NSFileReadNoSuchFileError according to the Foundation Constants Reference document. Looking at your code, the only way how I can see that file creation might fail is if self.myUITextField is nil.
I suggest that you check this first. If the property is not nil, then check whether writeToFile:atomically:encoding:error: returns an error.
Question 2: How can I get the Copy option to appear
First, assign a delegate to the controller:
documentInteractionController.delegate = self;
Then implement the following two delegate methods:
- (BOOL) documentInteractionController:(UIDocumentInteractionController*)controller canPerformAction:(SEL)action
{
if (#selector(copy:) == action)
return YES;
else
return NO;
}
- (BOOL) documentInteractionController:(UIDocumentInteractionController*)controller performAction:(SEL)action
{
if (#selector(copy:) != action)
return NO;
// Perform the copy: action
return YES;
}
Both methods are marked deprecated since iOS 6, but they still seem to work in iOS 7. Unfortunately, I have no idea how to implement the copy: action without those two methods - and neither does Apple, or so it seems to me, since they do not offer a replacement, and the official Document Interaction Programming Topics for iOS document still happily refers to the methods without indication that they are deprecated.
Anyway, here's a simple but complete implementation of the second delegate method:
- (BOOL) documentInteractionController:(UIDocumentInteractionController*)controller performAction:(SEL)action
{
if (#selector(copy:) != action)
return NO;
NSStringEncoding usedEncoding;
NSError* error;
NSString* fileContent = [NSString stringWithContentsOfURL:controller.URL
usedEncoding:&usedEncoding
error:&error];
UIPasteboard* pasteboard = [UIPasteboard generalPasteboard];
[pasteboard setString:fileContent];
return YES;
}

MPMediaItemPropertyAssetURL returning null only for iPhone 5s

I have been using the following code to extract the asset url from the MPMediaItem object returned from the MPMediaItemPickerController so that I can copy music files from a users iPhone itunes music library to the documents folder for processing, but on iPhone 5s I always get a null value from the MPMediaItemPropertyAssetURL, but when I run the same code on iPhone 4 or iPhone 5 it works as it should returning a proper url.
- (void) mediaPicker: (MPMediaPickerController *) mediaPicker didPickMediaItems: (MPMediaItemCollection *) mediaItemCollection {
[self dismissViewControllerAnimated:YES completion:nil];
if(mediaItemCollection){
MPMediaItem *mediaItem = (MPMediaItem *)[mediaItemCollection.items objectAtIndex: 0];
NSString *songTitle = [mediaItem valueForProperty: MPMediaItemPropertyTitle];
NSLog(#"songtitle: %#", songTitle);
NSURL *assetURL = [mediaItem valueForProperty: MPMediaItemPropertyAssetURL];
NSLog(#"%#", assetURL);
}
}
I have tried removing arm64 from valid architectures and only building for armv7 and armv7s, but that didn't fix this problem.
Does anyone know why this is happening and how I can fix it or if there is a workaround I can use? I need to be able to copy music from the iPhone's music library to the documents folder so that I can process the music properly for a dj application.
Thanks
I found out that the problem was the song I was trying to get the MPMediaItemPropertyAssetURL property for was actually not on my device. It was listed in the media library, but was actually still in iCloud. Once I downloaded the song to my device then the problem was solved. As much as I don't like answering my own question I took Jeroen's advice so that it can hopefully help others.
We can add filter that does not show iCloud items with
[mediaPicker setShowsCloudItems:NO];

Converting an iPhone IOS Video File Uploader to work with a file stored in document directory

This is my first real project. I have an app that captures several seconds of video using AVFoundation, outputs this to a file in the documents directory and lets the user preview the video before they upload it using HTTP and a PHP script on my website.
All the video capture and preview work perfectly but I am stuck on uploading the video file.
I learnt a lot from this simpleSDK video which shows how to achieve the desired effect using a video file stored in the apps main bundle.
The code from the tutorial that set up videoData ready to upload originally looked like this:
NSData *videoData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"Movie" ofType:#"mov"]];
NSString *urlString = #"http://www.iphonedevnation.com/video-tutorial/upload.php";
The filename of the video file that I need to upload is always unique and generated using CFUUIDCreateString. I join this string to the path for the documents directory, add ".mov" to the end of it and save it into a text file for retrieving later.
This all works as I am able to retrieve the filename from the file and use it to preview the movie clip elsewhere in the app.
My path is in an NSString, that I have tried converting to NSURL and removing the file suffix to get it to work with the NSData *videoData.........line but it doesn't compile, I get an "No known class method for selector 'dataWithContentsOfFile:ofType.' error. I am targeting iOS 5 and using Xcode 4.3 with ARC and Storyboards.
I've been at this for best part of 5 hours now so hopefully someone can help. My code, which included tips from elsewhere on converting from a NSString to NSURL follows:
NSString *content = [[NSString alloc] initWithContentsOfFile:lastSavedTalentFilenamePath
usedEncoding:nil
error:nil];
NSLog(#"content=%#",content);
//Need to now remove the '.mov' file type identifier
NSString *shortContent= [content substringToIndex:[content length]-4];
NSLog(#"***************shortContent***************%#", shortContent);
NSURL *convertedContent = [NSURL fileURLWithPath:shortContent];
NSLog(#"***************convertedContent***********%#",convertedContent);
NSData *videoData = [NSData dataWithContentsOfFile:convertedContent ofType:#"mov"];];
There is no NSData method called dataWithContentsOfFile:ofType:
The methods available are:
+ dataWithContentsOfFile:
+ dataWithContentsOfFile:options:error:
both of which take the file location as an NSString so there's not need to convert to an NSURL

Resources