I'm developping a mac application that allow to transcribe/subtitles video. I must deal with two kind of document type:
SRT file (read/write)
Video file (read only)
For now SRT is the only document type of my application. I open video with an Open a video... menu item (under File), I connected to the openVideo action of the First responder.
Here is the code of my VideoControlerView called when pressing Open a video... :
#IBAction func openVideo(sender: AnyObject) {
let dlg = NSOpenPanel()
dlg.runModal()
if let url = dlg.URL {
self.playerView.player = AVPlayer(URL: url)
}
}
I'm sure it is possible to benefit from the multi document type handling of document based application but I can't figure how. Any idea?
After questionning Apple Developer support about it, DocumentType is only designed for the editing document (SRT in my case).
The way I handle my asset (video file) is the proper way to go!
Related
I am trying to use pieces of the YouTubePlayerKit for a project I am working on. It looks like the library does the following:
Creates a player instance from a videoId
Creates a webview to load the video in
Evaluates some JS to get the video loaded
Re: the 3rd step, I was browsing the source code and i saw this function:
// Send YouTubePlayer Event with optional data
function sendYouTubePlayerEvent(event, data) {
var locationHref = 'youtubeplayer://' + event;
if (data) {
locationHref = locationHref + '?data=' + data;
}
window.location.href = locationHref
}
What I can't understand is, why are they using a youtubeplayer:// protocol? Is it inferring where to send events based on the name of the player class? Just for reference, I was looking at this library as well, and they use the protocol ytplayer://. What's going on here?
ytplayer:// is the start of a URL
https://developer.apple.com/documentation/xcode/defining-a-custom-url-scheme-for-your-app
https://developer.apple.com/ios/universal-links/
From the looks of your code it would ultimately look like
youtubeplayer://play?data=fghdfgjhdfgjdfgj
With fghdfgjhdfgjdfgj being some data object.
window.location would take that URL and do something with it like set the location of the current view or direct the webview to that website.
If you look at the code for the "Widget Code Along" You will find a good example for this setup, they only glance over it in the video but a
Link in a Widget uses a URL to open the detail view of a character.
https://developer.apple.com/news/?id=yv6so7ie
It's easy to populate the Open Recent menu following the advice from here
UIDocument.open() automatically adds opened files to the "Open Recents" menu
However, File Save out of the Sandbox is different. I'm using code like this, where I move a file from inside the sandbox out:
let documentPicker = UIDocumentPickerViewController(forExporting: [urlOfFileInSandbox], asCopy: false)
topVC.present(documentPicker, animated: true)
This is great but the file's URL doesn't show up in the "Open Recent" menu. Is there an easy way to do this?
(I can obtain the URL in the UIDocumentPickerDelegate, of course)
The solution is pretty simple. You need a UIDocument subclass that does nothing at all when you open a file URL
/// Call .open to add the fileURL to the recent menu
private class OpenRecentMenuModifier: UIDocument {
/// no-op
override func load(fromContents contents: Any, ofType typeName: String?) throws {
debugPrint("Adding \(fileURL.absoluteString) to Open Recent Menu")
}
}
Just call this after save to pretend that you just opened the file.
I'm supposed to test PSPDFKit in a way that lets the user open a locally saved pdf file.
For this i require the files url(e.g. path, i guess). How can i let the user pick a local document?
Can anybody help me out?
I'm using storyboard and swift.
You can present a PDF document in PSPDFKit using the PDFViewController like so:
// Create the `Document`.
let fileURL = Bundle.main.url(forResource: "Document", withExtension: "pdf")!
let document = Document(url: fileURL)
// Create the PDF view controller.
let pdfController = PDFViewController(document: document)
// Present the PDF view controller within a `UINavigationController` to enable the toolbar.
present(UINavigationController(rootViewController: pdfController), animated: true)
For more details, take a look at the following guide here.
Also, to present a document that your end-user has selected, consider using a document picker or a file browser. Please refer to DocumentPickerSidebarExample.swift from Catalog and SwiftUI Document Browser for runnable example projects.
In the future, please reach out to our support portal at pspdfkit.com/support/request/ - we're happy to provide support there for our commercial SDK.
I'm trying to export an UIImage as a sticker for Messages app, but I can't find any documentation about this.
I have my project with the Sticker Pack extension enabled and see that Xcode created a new Stickers.xcassets, every image that I add there manually appears on Messages app to use as a sticker, but how can I save an image programatically there, so the user can create stickers from any image ?
All I can find is information related to creating stickers without doing any code, just shipping an app with predefined images.
let sticker = try MSSticker(contentsOfFileURL: url, localizedDescription: "Test")
I know how create a MSSticker from the image file, but after this I don't know how to proceed and make this newly created sticker appear on Messages app.
Stickers are loaded from stickers assets catalog .xcstickers.
This catalog is a resource file/folder, that means this is placed inside your bundle. All files inside your bundle are not writable and they have only read permissions. IMO what you need to do is:
You have to store your users custom images in any one of the sandboxed folders (Documents, Library and temp).
Read image from this folder and create MSSticker from it same way as you did. - let sticker = try MSSticker(contentsOfFileURL: url, localizedDescription: "Test") and add. this sticker to array.
In your MSStickerBrowserViewController you will load stickers from array created in previous step.
Like this
override func numberOfStickers(in stickerBrowserView: MSStickerBrowserView) -> Int {
stickers.count
}
override func stickerBrowserView(_ stickerBrowserView: MSStickerBrowserView,
stickerAt index: Int) -> MSSticker {
stickers[index]
}
I'm subclassing the NSDocument class in order have a specific behavior during the save. I save the project in a folder and I create specific sub-folders with audio files used for this project.
I override the following function save(to:ofType:for:delegate:didSave:contextInfo) but I noticed a weird behaviour. Let's say I've the following implementation:
override func save(to url: URL,
ofType typeName: String,
for saveOperation: NSDocument.SaveOperationType,
delegate: Any?,
didSave didSaveSelector: Selector?,
contextInfo: UnsafeMutableRawPointer?) {
guard let customURL = createCustomUrlFrom(url: url) else { return }
super.save(to: customURL,
ofType: typeName,
for: saveOperation,
delegate: delegate,
didSave: didSaveSelector,
contextInfo: contextInfo)
}
I try to create a custom URL and if I don't manage to do it I cancel the save operation.
Now if I quit the app before saving, the app prompts me to save. If I cannot create the custom URL and I return (before the super.save… call), the quit button or "cmd+q" doesn't work! I've to force quit to close the app.
Anyone see what I did wrong here? Does something is running in the background that prevents me to close the app?
UPDATE
Maybe it comes from the sheet prompted when we quit an edited document. We have the window saying Do you want to save the changes made to the document “Untitled”? with 3 buttons Dont's save, cancel save...
If I click on save, then the project already exists I show a window to let the user replace the project or cancel the save (it's done in the createTargetUrlFrom(url:) func. If the user choose to cancel the app cannot be quit.
So I think about the first window running in background maybe…
I found the solution to this issue!
In fact the application was waiting a reply to the NSTerminateLater. I needed to use the reply(toApplicationShouldTerminate:) function. So I just added NSApp.reply(toApplicationShouldTerminate: false) before returning from the guard statement.