Post

Replies

Boosts

Views

Activity

Reply to In SwiftUI, any way to intercept each character entered in a TextField?
I've had good luck providing a Formatter which just passes through its string value, in which you can override methods like func isPartialStringValid(_ partialStringPtr: AutoreleasingUnsafeMutablePointer<NSString>, proposedSelectedRange proposedSelRangePtr: NSRangePointer?, originalString origString: String, originalSelectedRange origSelRange: NSRange, errorDescription error: AutoreleasingUnsafeMutablePointer<NSString?>?) -> Bool and do whatever you want with the user's entered string, change it, move the selection, etc...
Jun ’21
Reply to SwiftUI TextField inside UIViewController
You'll have to be more precise about the context in which you're placing this code. For instance addChild(_:) is a method on a UIViewController, and not on a UIView. But frame is a property on a UIView, not a UIViewController. So I don't know where you're getting the frame from on the right hand side of the = operator on line 4. If it's the parent view controller's view frame, then... frame is the view's position in its super view's coordinate system, whereas bounds is its position in its own coordinate system. So depending on frame, maybe you're covering it up? But if you're trying to add the hosting controller onto the navigation stack, then you should be using pushViewController(_:_:) not addChild(_:). And then, if you have navigationBarHidden(_:) (which we don't know is not the case from the code you posted) in your swiftUI view, who knows, maybe the hosting controller is setting that property correctly, too? And if your swift view has a navigation view in it, I don't even know how much more could go wrong. But we can't see that from your example. If you have a particular bug in particular code, please construct a minimal example that still causes the bug, and post that, and then we can tell for sure.
Jun ’21
Reply to Is there a sample app for UIDocument using UIScene for MacCatalyst?
Filed a DTS incident... It turns out that the os does not correctly handle typing command-q, whereas it does "correctly" handle using the mouse to select quit from the application menu. How does it not handle that correctly? The sandbox does not know that the file is still 'ok' to be written to. So writing out contents to autosave works, but when UIDocument goes to replace the original file with the version it wrote to the temp dir, it gets a sandbox error. This bug is still in macOS 11.2.2. I know, I know, isn't it just a UIKeyCommand? Well, it is, but actually it's hacked somehow, because the quit command selector is terminate:, which is not a documented selector in UIKit. And if you try to make your own, it just crashes. And using a Mac obj-c plug-in to access appkit to call terminate: on the nsapplication instance doesn't do any of the things the uiscenes need done. BUT, when I click the menu command for quit instead of the shortcut, it goes ahead and proactively discards my scene sessions, thus meaning there's never going to be a scene to restore when the app launches again. Which, I think is definitely not the expectation, but it's better than opening blank windows and never giving me a session to restore. A year and a half of my life.... a year and a half. That's how long I've been re-writing apps to UIKit so I could more easily and more rapidly release apps than using AppKit. And the OS literally just never worked.
Apr ’21
Reply to Is there a sample app for UIDocument using UIScene for MacCatalyst?
It appears the system is throwing the sessions away because the watch dog timer killed the app. After 5 seconds after hitting command-q, I see this in the console. [Lifecycle] Watchdog: App took too long to enter the background-only state. Exiting immediately! (5.0s) [Lifecycle] Watchdog timeout. Exiting immediately. (App took too long to enter the background-only state.) [Assert] App took too long to enter the background-only state. When I pull up the Console console, I get a serious of incomprehensible excuses for not saving the document. UIDocument unrecoverable error with description: You don’t have permission to save the file “Untitled.txt” in the folder “Documents”. reason: You don’t have permission. Failed to recover from error with description: You don’t have permission to save the file “Untitled.txt” in the folder “Documents”. reason: You don’t have permission. Why not? I opened it? I have read/write permissions in the entitlements. Sandbox: MyAppName(5631) deny(1) file-read-data /Users/myusername/Documents/mydocument.txt Why? If I close the doc by dismissing the view controller and calling .close directly, it saves successfully. So how did I lose permissions to save my work just because I'm quitting the app? Seems like a major major major design flaw in the OS.
Mar ’21
Reply to How do I do showInFinder in Mac Catalyst
Apparently, it can only be done using NSWorkspace. Which is part of AppKit. Which can't be imported into the code compiled directly into your frameworks. However... I heard others say code importing AppKit can be included in a "plug-in", which can be added for only the Mac-os version of your app and can be loaded at run time. So here's my code for this: I create a plug-in called "AppKitCompatibility". The plug-in bundle is listed in the General pane of the project editor of my maccatalyst app, with Platforms set to "macOS" and Embed set to "Embed &amp; Sign". It contains 2 obj-c files.: WorkspaceCompatibility.h #import Foundation/Foundation.h NS_ASSUME_NONNULL_BEGIN @interface WorkspaceCompatibility : NSObject (void)showInFinder:(NSArrayNSURL * *)urls; @end NS_ASSUME_NONNULL_END WorkspaceCompatibility.m #import "WorkspaceCompatibility.h" #import AppKit/AppKit.h @implementation WorkspaceCompatibility (void)showInFinder:(NSArrayNSURL * *)urls { [NSWorkspace.sharedWorkspace activateFileViewerSelectingURLs:urls]; } @end The plug-in's info.plist lists WorkspaceCompatibility as the principal class. I don't think that's strictly necessary, as the swift code below loads it by name. Then in the swift UIKit portion of the app : import Foundation class MacCompatibility { static let shared:MacCompatibility = MacCompatibility() private init() { } #if targetEnvironment(macCatalyst) //the classes loaded only live as long as the bundle instance, so the bundle must be retained for the duration of the app private lazy var bundle:Bundle? = newBundle() private func newBundle()-Bundle? { let bun = Bundle(path: Bundle.main.builtInPlugInsPath?.appending("/AppKitCompatibility.bundle") ?? "") bun?.load() return bun } #endif func revealUrlsInFinder(_ urls:[URL]) { #if targetEnvironment(macCatalyst) let files = urls as [NSURL] let fileArray = files as NSArray guard let macClass:AnyClass = bundle?.classNamed("WorkspaceCompatibility")   ,let macCompatibility = macClass as AnyObject as? NSObjectProtocol //in Obj-c, classes are objects, too else { return } _ = macCompatibility.perform(NSSelectorFromString("showInFinder:"), with:fileArray) //so we can call a class method on the class #endif } } I normally hate singletons, but in this case the MacCompatibility is held as a singleton for 3 reasons: 1) the bundle must remain in memory as long as the code will be run, 2) it can be accessed from anywhere just as the workspace was, and 3) it's so little code, surely it's not a problem. I have tested this, and it works. But I have not shipped it. I have heard other people say using plug-ins is supported by the MacAppStore.
Mar ’21
Reply to is it possible to have a "floating" window in macCatalyst?
In the future, I'd like to build a feature where my app has a specialized display for external screens, which would involve creating a separate window. Super easy in UIKit on iOS. Super easy in AppKit on Mac. Next to impossible with UIKit on Mac. However, someone posted a demo of how to create a "plugin" written in Objective-C, and include it only in my Mac version of the app. The objective-c bundle code #import AppKit, queries appkit and some other frameworks for screen information, creates an NSWindow with an NSViewController, and then vends its CALayer through the plugin's one method. Since CALayer is the same class in both frameworks, I can actually insert the CALayers I have from the uikit side of the app into the NSView in the NSWindow from the plugin. Of course, I have to use run-time bundle loading with objective-c runtime method calls, like performSelector:, to do that... but it works. I haven't shipped it yet. There are so many issues just getting document-based apps to work in maccatalyst, this ground-up-re-write of my app in MacCatalyst has been delayed for many months until I get those fixed. I don't know if there's anyway to get it to work with SwiftUI; I've never tried playing with SwiftUI and CALayer together. But SwiftUI works on Mac, too, without catalyst. So you may be able to write a shared framework that relies on swiftui and create a hosting view / view controller in the plugin which vends the hosting view to the obj-c code that runs the bundle. Then you only need methods for updating your data source in both directions. Since you can't send swift structs through the obj-c protocol, maybe you could serialize it all down, kind of like xpc does for inter-process communication? I dunno. just thinking out of the box here.
Mar ’21
Reply to Facing issues with document-based app on macOS Big Sur 11.1
re: B 2, I think maybe possibly you're calling the "import" method on the document browser view controller in response to your external open request? I think the import method on the document browser vc is for moving a file into the directory alongside the other url in the call. i.e. it doesn't mean "open me". I'm only using import when "openInPlace" is false, or when the user selects a file in a file format that I support converting from but not saving in. i.e. I have my native file format I'll call "s" and there is a public standard other apps create I'll call "x". I have "x" listed as a document format in my app, and as an imported type, and when the user selects one, I convert it into a temp file in format "s", then use "import" to bring it into the dir next to the original file, this causes the system to prompt the user to save the new file, which is a little unexpected nicety which is probably the right thing to do. But I wouldn't use "import" when the original document is in a format I would save in or the openInPlace was true.
Mar ’21
Reply to Facing issues with document-based app on macOS Big Sur 11.1
I worked around problem B 1 by not presenting my document vc until after the document successfully opens. so my code is create document create document view controller open document in completion block, if successful open, present document view controller on top of UIDocumentBrowserViewController I tried presenting a "spinner" view controller I created on top of the browser, but when I do the browser dismisses itself ( dismiss(... is getting called and I'm not calling it in my code) out from under the presented view controller. This seems to be related to why the repeated showing of the browser happens - something to do with the browser getting dismissed out from under the document view controller.
Mar ’21