Why doesn't AVPlayer work with a URL found with FileManager? - swift

If I use a file URL fetched with NSOpenPanel, creating an AVPlayerItem and replacing AVPlayer:s current item with that works fine. But if I fetch the same file URL with FileManager, AVPlayer won't open the file, even though no errors are generated. I even made a '==' comparison of the file URL:s for debug purposes and it evaluates to true (the same file URL fetched with NSOpenPanel and fetched with FileManager).
I'm fetching the file URL:s of videos in a directory and then populating a NSPopUpButton with the names of the video files. Selecting a video from the NSPopUpButton should load that video into AVPlayer, but this is not working even though the URL:s that I'm passing to AVPlayerItem are correct.
Any ideas?

Sandboxing prevents opening files that have not been opened with NSOpenPanel. Removing the Sandbox slice from project target capabilities by clicking the X, removes this restriction.
As I am creating a program for my own use, removing sandboxing is not a problem. I don't know if and how it affects AppStore eligibility.

Related

How to compress video after getting result from PHPickerViewController xcode swift

I know that UIImagePickerController allows you to compress media content upon selection. However, I'm not sure how to do the same with PHPickerViewController. How can I compress a video after getting a result (didFinishPicking), (so I can reduce the amount of time to upload and download the data from then on)
I don't think PHPickerViewController does that, but there are other ways to do it depending on how you work with the picker:
If you're using the default picker configuration (i.e. creating a PHPickerConfiguration without passing the photo library and therefore not having the need to request permissions), you'll have to work with NSItemProvider. From what I learned, the only option might be to save the video to a temporary file using the item provider and the convert it to a lower resolution/bitrate using AVAssetExportSession (see some examples here: How can I reduce the file size of a video created with UIImagePickerController?).
If you are using the picker with an explicitly passed photo library, the PHPickerResult will have the assetIdentifier provided to you, and you can use it to get a respective PHAsset. Then, use PHImageManager's requestAVAsset method to get a video asset of a desired quality. You'll still need to export the AVAsset via AVAssetExportSession though, but with this approach you won't have a (potentially large) full-res temporary file on disk. I was recently working on a open source app that uses this technique, you can find some examples here: https://github.com/vadimbelyaev/TbilisiCleanups/blob/main/TbilisiCleanups/Services/MediaUploadService.swift

openURL on local file in temporary directory does nothing

I'm saving a downloaded PDF file to a temporary directory on my device, and have the URL for the resultant file:
file:///Users/colinbasnett/Library/Developer/CoreSimulator/Devices/A057DDAD-B116-424B-8383-442321530EEC/data/Containers/Data/Application/A0AEF93A-5B1D-4CB4-B39F-F6DFECEDD9E9/tmp/FF5C09A9-45CD-454E-B55A-4F5CEBFEBC7F-24875-000014B657DC6436/23659.pdf
Where fileURL is a valid NSURL object representing the path above, I call this:
UIApplication.sharedApplication().openURL(fileURL)
and nothing happens.
Despite this, the following call returns true:
UIApplication.sharedApplication().canOpenURL(fileURL) // returns true
Ideally this would open in Safari or whatever the preferred browser application is. Interestingly enough, I can manually open Safari, paste that directory in the address bar and it is able to display the PDF.
I'm using Swift 2.2 (can't switch to 3 yet because dependencies have not been upgraded).
I think the problem is that openURL() wants to launch a separate application, but you're passing a file: URL that points to a file in your sandbox. I suspect UIDocumentInteractionController might be more what you're after.

Where to store a preview of a UIDocument?

I'm working on UIDocument application and I'd like to show the user a preview of the document before he opens it. I can render that preview into an image when the document get's closed. But where should I save that image? In an other file? or is there a designated way to do this?
Right now I'm developing it without iCloud support. But I want to have a solution that would work with iCloud too. The UIDocument is a UIManagedDocument. But saving the image into the database would make it kind a pointless. Because then I have to open the document before I can get the preview.
What do you recommend here? Where to put a preview for a UIManagedDocument?
You can store your documents in your ubiquity container's Documents directory and document preview files in the container's Data directory.
If preview file names will be based on the documents names you will be able to use metadata query result to get the document names and then resolve document preview urls.
This way you could download the document previews only but not the whole document.
I don't know about UIManagedDocuments, but in case of a UIDocument I would recommend using a NSFileWrapper as file format (where the document is actually a bundled folder) and save the preview within the document, as "Preview.jpg" (or .png) inside a folder labeled "QuickLook".
This way, you'll get the preview in Finder on the Mac as well (for free).
Of course this may or may not be an ideal solution (also depending on if your document is text-only). But it might be a good hint for working with previews for UIDocuments in general.
You should save an image under (app_directory)/Library/Caches. That way iCloud won't affect your app.

UIDocumentStateSavingError for file in the iCloud: possible causes and how to recover

With the coming update, our iOS app is supposed to export data to a text file in the iCloud and to import data from it. The implementation is mostly completed and we started beta-testing. Everything seems to be working fine for all but one of the beta-testers.
What I gather from debugging output collected by the TestFlight API, one of the testers somehow managed to get the file into the UIDocumentStateSavingError state. So far, we could not manage to pop the file out of that state no matter what we had him try.
This is what happens on the tester's device:
iCloud access is successfully detected using URLForUbiquityContainerIdentifier.
An NSMetadataQuery is started to locate the file and returns exactly one result.
An subclass of UIDocument is created for the resulting URL using initWithFileURL:.
The document is in the UIDocumentStateSavingError state. Also, this is the only state flag that is set.
The call to openWithCompletionHandler: returns failure to the handler and loadFromContents:ofType:error: on the UIDocument is not called.
We then made a new version of the app that continues as follows:
The app tries to delete the erroneous file using [[NSFileManager defaultManager] removeItemAtURL:doc.fileURL error:&err].
The resulting NSError indicates that "The operation couldn’t be completed. No such file or directory".
Deleting the file was about the last thing we could come up with in order to resolve the file's state. Any hints on how to solve this or on what might be causing the error in the first place would be very much appreciated!

Streaming and playing an MP3 stream. .mp3 URL format

I used the sample code from http://cocoawithlove.com/2008/09/streaming-and-playing-live-mp3-stream.html. it runs OK with default URL. But when I replace with my URL "http://dl.mp3.kapsule.info/fsfsdfdsfdserwrwq3/fc90613208cc3f16ae6d6ba05d21880c/4b5244f0/b/7e/b7e80afa18d06fdd3dd9f9fa44b51fc0.mp3?filename=Every-Day-I-Love-You.mp3", this app shows an message as "Audio not Found". But when I put my URL on Address Bar of Web Browser, I can download this .mp3 file.
really, I can't understand why it is?
pleased tell me!
Thank you very much
My guess would be that the app is designed to play a MP3 encoded audio stream with no limit in length (which is different from your ordinary music file). To set this up, you need a streaming server on the client side.
I think you can find out for sure by trying with a different radio station that transmits in MP3. If that works, it's most likely that your app doesn't like your file.
You should, as Vivek recommends, also try using a simpler download URL for your file, in case the App gets confused by the URL's length and/or structure.
As mentioned, this is due to the URL of the file. The AudioStreamer code specifically checks for the extension of the file and tries to figure out the audio type based on that. If you change that logic to handle your custom URLs, it will start working
So to point you in the right direction: open AudioStreamer.m and look for the references of
hintForFileExtension:
This function returns the type of file based on the extension. If you know the file type won't change (always mp3), the quick and dirty solution is to always assign mp3 type without any logic... like this:
err = AudioFileStreamOpen(self, MyPropertyListenerProc, MyPacketsProc, kAudioFileMP3Type, &audioFileStream);
Note: I've put kAudioFileMP3Type constant instead of calculated value
PS yes, it does work with static mp3 files, even though it's designed for streams and hence misses some of the functionality one would expect from a player that plays a static file on the server (caching, prefetching, proper seeking)
Thats because the default url directly points to a file in the webserver, whereas the the url you've mentioned is a HTTP (POST/GET) operation, which the application may not be designed to handle.
I suspect that your URL is one-time-use. When I try to visit it, I see 408 - Request Timeout.
Many links on mass file sharing websites are like this. If you could download the file directly, you wouldn't sit through a page of ads and premium account offers.
Try again with a file on a normal website, like this one.