Post

Replies

Boosts

Views

Activity

macOS Notification Service killed/fails (but Catalyst/iOS works)
While mutable push notifications process properly in a cousin Catalyst/iOS app, my macOS app does not execute methods in its Notification Service extension to mutate notification content before presentation (when app is active, in background, or terminated). Console logs (below) show the Mac extension is found and launched, but then killed for "sluggish startup". It is the vanilla new file stub with zero dependencies. I'm doubtful this matters, but I am running Monterey RC1/Xcode 13 RC on an M1. What am I configuring improperly? Objective Push a remote notification ~once a month to download a file, locally process user data, and then silence or display a modified alert accordingly. I've Tried Per macOS Notification Service Extension not being used Ensured sandboxed Enabled "Incoming Connection (Server)" (no difference) Wipe DerivedData Run on naive second Mac Per Notification Service Extension Not working Rebooting the Mac Ensuring the deployment target of the app and extension are identical Received Notification From application(_ app: NSApplication, didReceiveRemoteNotification userInfo: [String : Any]) ["customThing": value, "aps": { alert = "Push Mutable"; "mutable-content" = 1; sound = default; }] Signing/Capabilities App Debug/Release Sanboxed w/ outgoing connections Hardened runtime iCloud Push (certificates) Automatic signing w/ cert Notifications Extension Sandboxed Hardened runtime Automatic signing Extension class NotificationService: UNNotificationServiceExtension { var contentHandler: ((UNNotificationContent) -> Void)? var bestAttemptContent: UNMutableNotificationContent? override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { self.contentHandler = contentHandler bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent) if let bestAttemptContent = bestAttemptContent { bestAttemptContent.title = "[modified]" bestAttemptContent.body = "Changed" contentHandler(bestAttemptContent) } } override func serviceExtensionTimeWillExpire() { if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent { contentHandler(bestAttemptContent) } } } Console Perhaps relevant? usernoted <IDENTIFIER> Extension will be killed due to sluggish startup error serviceExt com.apple.unc usernoted LogFromBuildToNotificationPush.txt
4
3
3.4k
Oct ’21
Prevent MTKView camera feed rotation, but allow other on-screen VCs to rotate
Goal With an MTKView, replicate the gravity of the AVCaptureVideoPreviewLayer or Apple's Camera app. Video device orientation does not change. The camera feed's edges do not budge a pixel, never revealing the screen background. Other on-screen VCs rotate normally. Observed Applying Tech QA 1890's transform during viewWillTransition, the MTKView does counter-rotate... BUT that rotation is still uncomfortably visible. The edges of the view come unpinned during the animation, masking some camera pixels and showing a white background set for the VC holding the MTKView. Question How can I make those edges stick to screen bounds like a scared clam? I assume my error is in constraints, but I'm open to being wrong in other ways. :) View Hierarchy A tiny camera filter app has an overlay of camera controls (VC #1) atop an MTKView (in VC #2) pinned to the screen's edges. UINavigationController │ └─ CameraScreenVC │ ├── CameraControlsVC <- Please rotate subviews │ └── MetalCameraFeedVC └── MTKView <- Please no rotation edges Code Buildable demo repo Relevant snippets below. MetalCameraVC.swift final class MetalCameraVC: UIViewController { let mtkView = MTKView() // This VC's only view /// Called in viewDidAppear func setupMetal(){ metalDevice = MTLCreateSystemDefaultDevice() mtkView.device = metalDevice mtkView.isPaused = true mtkView.enableSetNeedsDisplay = false metalCommandQueue = metalDevice.makeCommandQueue() mtkView.delegate = self mtkView.framebufferOnly = false ciContext = CIContext( mtlDevice: metalDevice, options: [.workingColorSpace: CGColorSpace(name: CGColorSpace.sRGB)!]) } ... func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) { // blank } func draw(in mtkview: MTKView) { image = image.transformed(by: scaleToScreenBounds) image = image.cropped(to: mtkview.drawableSize.zeroOriginRect()) guard let buffer = metalCommandQueue.makeCommandBuffer(), let currentDrawable = mtkview.currentDrawable else { return } ciContext.render(image, to: currentDrawable.texture, commandBuffer: buffer, bounds: mtkview.drawableSize.zeroOriginRect(), colorSpace: CGColorSpaceCreateDeviceRGB()) buffer.present(currentDrawable) buffer.commit() } } extension MetalCameraVC { override func viewDidLoad() { super.viewDidLoad() view.addSubview(mtkView) } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) mtkView.frame = view.frame if let orientation = AVCaptureVideoOrientation.fromCurrentDeviceOrientation() { lastOrientation = orientation } } } +Rotation /// Apple Technical QA 1890 Prevent View From Rotating extension MetalCameraVC { override func viewWillLayoutSubviews() { super.viewWillLayoutSubviews() mtkView.center = CGPoint(x: view.bounds.midX, y: view.bounds.midY) } override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) coordinator.animate { [self] context in let delta = coordinator.targetTransform let deltaAngle = atan2(delta.b, delta.a) var currentAngle = mtkView.layer.value(forKeyPath: "transform.rotation.z") as? CGFloat ?? 0 currentAngle += -1 * deltaAngle + 0.1 mtkView.layer.setValue(currentAngle, forKeyPath: "transform.rotation.z") } completion: { [self] context in var rounded = mtkView.transform rounded.a = round(rounded.a) rounded.b = round(rounded.b) rounded.c = round(rounded.c) rounded.d = round(rounded.d) mtkView.transform = rounded } } }
0
0
1.5k
Jun ’21
Obtain / reset a "3rd Party Mac Developer Installer" certificate
Upon trying to upload a new build to App Connect, which worked fine four weeks ago, validate gives an error that: The product archive package's signature is invalid. Ensure that it is signed with your "3rd Party Mac Developer Installer" certificate. Uploading gives the same error: ERROR ITMS-90237: "The product archive package's signature is invalid. Ensure that it is signed with your "3rd Party Mac Developer Installer" certificate." This is despite updating in my developer profile and downloading the new "3rd Party Mac Developer Installer" certificate, which shows up as valid in my keychain. So confused...
11
0
3.7k
Jul ’20
Parameter update from NSView (right click in MacOS SwiftUI)
While function calls work as expected in an NSViewRepresentable, I'm unclear why the parameter passed below (to show a SwiftUI popup) does not update after a function call in the NSView. Any tips? Some View Struct @State var showMenu = false var body: some View { &#9; ZStack { &#9; RightClickableSwiftUIView(onClick: $showMenu) &#9; Image(name) &#9; .popover(isPresented: $showMenu, ...) &#9; } } RightClick.swift import SwiftUI struct RightClickableSwiftUIView: NSViewRepresentable { &#9;&#9;@Binding var onClick: Bool &#9;&#9;func updateNSView(_ nsView: RightClickableView, context: NSViewRepresentableContext&lt;RightClickableSwiftUIView&gt;) { &#9;&#9;} &#9;&#9;func makeNSView(context: Context) -> RightClickableView { &#9;&#9;&#9;&#9;RightClickableView(onClick: $onClick) &#9;&#9;} &#9;&#9;class RightClickableView : NSView { &#9;&#9;&#9;&#9;required init?(coder: NSCoder) { &#9;&#9;&#9;&#9;&#9;&#9;fatalError("init(coder:) has not been implemented") &#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;init(onClick: Binding&lt;Bool&gt;) { &#9;&#9;&#9;&#9;&#9;&#9;_onClick = onClick &#9;&#9;&#9;&#9;&#9;&#9;super.init(frame: NSRect()) &#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;@Binding var onClick: Bool &#9;&#9;&#9;&#9;override func mouseDown(with theEvent: NSEvent) { &#9;&#9;&#9;&#9;&#9;&#9;print("left mouse") &#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;override func rightMouseDown(with theEvent: NSEvent) { &#9;&#9;&#9;&#9;&#9;&#9;onClick = true &#9;&#9;&#9;&#9;&#9;&#9;print("right mouse") &#9;&#9;&#9;&#9;} &#9;&#9;} } This is related to another user's post: https://developer.apple.com/forums/thread/127921
1
0
1.4k
Jul ’20
Buggy look of SwiftUI CommandMenu Buttons
Images cannot be linked here, but the code below produces buttons that are inset differently than all auto-generated MacOS buttons. Keyboard modifiers are white, rather than gray. Dividers also don't work properly, nor accept color changes, nor it is reliable to sort in a Rectangle. Spacer() is selectable, but at least an empty Text("") is not. Why? struct AppMenus: Commands { &#9;&#9;func some() {} &#9;&#9;@CommandsBuilder &#9;&#9;var body: some Commands { &#9;&#9;&#9;&#9;CommandMenu("Why") { &#9;&#9;&#9;&#9;&#9;&#9;Button("So") { some() } &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;.keyboardShortcut( KeyEquivalent("s"), modifiers: .command) &#9;&#9;&#9;&#9;&#9;&#9;Text(" ") Spacer() Divider() .foregroundColor(Color(.doesntCare)) &#9;&#9;&#9;&#9;&#9;&#9;Button("Sad") { some() } &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;.keyboardShortcut( KeyEquivalent("s"), modifiers: .command) } &#9;&#9;&#9;&#9;CommandGroup(before: CommandGroupPlacement.sidebar) { &#9;&#9;&#9;&#9;&#9;&#9;Button("Why my button so sad?") {} &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;.keyboardShortcut(KeyEquivalent("?"), modifiers: .command) &#9;&#9;&#9;&#9;} &#9;&#9;} }
5
0
1.4k
Jul ’20
How to return image from QLThumbnailGenerator
My ProblemHow do I return a cgImage from QLThumbnailGenerator.shared.generateRepresentations(for: ... )?My Hangups/Attempt (Code Below)My attempt has a function (line 13) that returns a CGImage for a ListView entry (line 39). I tried to use an empty CGImage (line 18), but its init parameters are confusing and seem excessive for a simple thumbnail. I'm likely going about this incorrectly.NotesCGImage is used so the same code can work for both iOS and MacOS Catalyst. (Saw this in WWDC 2019 session 719.)I tried but failed to glean an answer from: https://developer.apple.com/documentation/quicklookthumbnailing/creating_quick_look_thumbnails_to_preview_files_in_your_apphttps://forums.developer.apple.com/message/375807App overview: This is a public service app that searches a specified library of PDFs for an array of terms for misidentified biomaterials, helping biologists screen for potentially false results in every paper they've read. It will be free.Apology/Gratitude:Thanks for your patience, as the answer is likely obvious and my vocabulary likely off. My dumb brain tunes out lectures without a little hands-on experience, so I started this first app from zero programming knowledge as a quarantine hobby. I'll return to the theory lectures after.Code: ResultsView.swiftimport SwiftUI import MobileCoreServices import Combine import QuickLookThumbnailing import CoreImage import UIKit struct ResultsView: View { @EnvironmentObject var parsedScreeningData: ParsedScreeningData @EnvironmentObject var search: Search func generateThumbnail(ofThis: String) -&gt; CGImage { let url = self.search.libraryFolder.appendingPathComponent(ofThis) let size: CGSize = CGSize(width: 68, height: 88) let request = QLThumbnailGenerator.Request(fileAt: url, size: size, scale: (UIScreen.main.scale), representationTypes: .all) let generator = QLThumbnailGenerator.shared var image = CGImage() generator.generateRepresentations(for: request) { (thumbnail, type, error) in DispatchQueue.main.async { if thumbnail == nil || error != nil { assert(false, "Thumbnail failed to generate") } else { image = thumbnail!.cgImage } } } return image } var body: some View { VStack{ List(search.searchResults) { datum in HStack { Image(self.generateThumbnail(ofThis: datum.PDFname), scale: (UIScreen.main.scale), label: Text("PDF")) Text("File: \(datum.PDFname)") Text("Cell line: \(self.parsedScreeningData.parsedScreeningData[datum.termFoundIndex].misidentifiedCellLine)") .padding(.trailing, 10) .padding(.leading, 10) Spacer() Image(systemName: "eyeglasses").foregroundColor(ColorManager.iconGreen) // .onTapGesture { // let url = URL.init(string: "\(datum.termFoundIndex)") // guard let thisAddress = url, UIApplication.shared.canOpenURL(thisAddress) else { return } // UIApplication.shared.open(thisAddress) } // HStack } // List }// Vstack .colorMultiply(ColorManager.beigeMedium) .padding(.trailing, 0) .padding(.leading, 0) .listStyle(GroupedListStyle()) } // body } // ResultsView struct struct ResultsView_Previews: PreviewProvider { static var previews: some View { ResultsView().environmentObject(ParsedScreeningData()).environmentObject(Search()) } }
1
0
1.1k
May ’20
Pushed view temporarily displays hidden navBar/Back
The pushed view temporarily renders its contents with space for the hidden navigationBar immediately upon transition. How do I fix this behavior?Barebones demo:ContentView.swiftimport SwiftUI struct ContentView: View { @State var goToNextView = false var body: some View { NavigationView { ZStack { Color.yellow.edgesIgnoringSafeArea(.all) NavigationLink(destination: SecondView(), isActive: $goToNextView) {Text("")} .navigationBarTitle("") .navigationBarHidden(true) .navigationBarBackButtonHidden(true) VStack { Button(action: { print("Button clicked") self.goToNextView = true }) { Text("Go to second view") } .padding() Text("This is the first view.") } } .foregroundColor(Color.blue) } } }SecondView.swiftimport SwiftUI struct SecondView: View { var body: some View { ZStack { Color.purple .edgesIgnoringSafeArea(.all) .navigationBarBackButtonHidden(true) .navigationBarHidden(true) Text("Pushed view") } .foregroundColor(Color.white) } }
0
0
688
May ’20