Posts

Post not yet marked as solved
0 Replies
80 Views
Hey all, In UIKit, we were able to specify options when using the UIView animation apis, and one of those options was .beginFromCurrentState. I'm working on some animations in SwiftUI. This is a view that animates when some state gets updated. However, the animation is relatively long (2 seconds), and so that state might change mid-animation, triggering a new animation. Currently, the ongoing animation simply gets stopped, and the view jumps to the starting point of the new animation immediately. Is there a way to specify an animation to start from the current state of the view? In UIKit there is beginFromCurrentState, and in CoreAnimation we are able to use the presentation layer to achieve starting from currentState. However, I am unable to find if / how to do this in SwiftUI. Is this possible at all? If so, what documentation did I miss?
Posted
by Joride.
Last updated
.
Post not yet marked as solved
0 Replies
132 Views
Hey folks, I need to implement a view for a live activity (so using. WidgetKit), so any UIKit/SceneKit is a non-starter. The thing to implement is a horizontal representation of a 360 degree protractor ('degree triangle'). I would like this view to be inifintely scrollable as if the user has a circular shape around their head and they can rotate their head to look at all the numbers, and when they reach 360/0, they simply continue with new round. In both directions. I've managed to get this working for the positive values by using a LazyHStack and which is populated using ForEach, using a custom class that implements RandomAccessCollection where the endIndex is Int.max (not truly infinite, but good enough). However, I can't get the scrollview/ForEach to start in the 'center' of the Int.max range (I'm sure this would cause some performance issue as well). So my question is: how to get a SwiftUI scrollview to behave like a infinite scrollview, pretty much like Josh Shaffer explained in WWDC 2011 in the session with Eliza Block called 'Advanced ScrollView Techniques'?
Posted
by Joride.
Last updated
.
Post not yet marked as solved
0 Replies
316 Views
Hey all, Tl;dr: In debug-build using a .storekit file, all is good. When uploading a release build to testflight, purchasing follow the expected flow, but it does not seem the subscription status is reflected. Full description I've implemented auto-renewable subscriptions in my app. In debug, I've setup a scheme to use products.storekit. When I run this scheme on my device, I can subscrbe, cancel etc, and it all works as expected. When I upload my release scheme to testflight, purchasing can be done, but changes do not seem to be reflected inside the app (i.e.e no features get unlocked). Same thing when I run this scheme on my device. This scheme has None set for Storekit configuration. When I set 'Storekit configuration' to the Products.storekit, file I can't make a purches at all: SubscriptionStoreView shows Subscription unavailable. The subscription is unavailable in the current storefront'. I've watched a number of WWDC sessions on the topic, read most (all?) of the documentation, and I just can't seem to find out what it is that needs to be done. Unfortunately, debugging has been rather cumbersome and sometimes impossible lately, especially when trying to debug a release build. Anyone can tell me what it is I am overlooking, or what piece of information or link I missed? Here is the relevant code (which works OK in debug) private func listenForTransactions() -> Task<Void, Error> { return Task.detached { for await anUpdate in Transaction.updates { do { let transaction = try self.checkVerified(anUpdate) await self.checkSubscriptionStatus() await transaction.finish() } } } } And here's checkSubscriptionStatus(): @MainActor private func checkSubscriptionStatus() async { var hasActiveSubscription = false do { for aStatus in try await Product.SubscriptionInfo.status(for: "718A7488") { let state = aStatus.state hasActiveSubscription = (state == .inGracePeriod) || (state == .subscribed) } } catch { print(error) } self.hasActiveSubscription = hasActiveSubscription }
Posted
by Joride.
Last updated
.
Post not yet marked as solved
1 Replies
247 Views
Hi all, I've implemented in-app purchases to have auto-renewing subscriptions. However, when I use Xcode's Transaction Manager to expire a subscription, there seems to be no callback Transaction.updates or Transaction.currentEntitlements I can see an expiry through Transaction.all but I can't imagine the intention is to poll that while the app is running. What am I missing here?
Posted
by Joride.
Last updated
.
Post not yet marked as solved
2 Replies
777 Views
Xcode Version 15.2 in general is very, very slow when debugging. If I get to that, often, xcode just shows a message "Preparing iPhone 15 Pro Joride. Xcode will continue when the operation completes" This box will stay there for at least 3 min. Then it is follow by a message about a developer image not being able to get mounted: "Previous preparation error: The developer disk image could not be mounted on this device.. Error mounting image: 0xe8000115 (kAMDMobileImageMounterDevicePropertyQueryFailure: Failed to query device property.)" If I eventually do manage to debug my app, it is soooooo slow. The launchscreen is there for easily 20 seconds (I'm guessing debugger is trying to attach during this time). When there are breakpoints present at all, things just occur very very slowly, expecially when trying to PO variables. The app itself runs fine though. I've noticed there is a checkbox for this device that says 'Connect via network'. This clearly seems to be broken for my combination of factors, so I wanted to uncheck it. Not possible! For those of use with a similar experience, any suggestions? (I did try to power cycle both computer and iPhone, but that did not change much. Both devices are connected to the same home wifi which has no special setup or restrictions)
Posted
by Joride.
Last updated
.
Post not yet marked as solved
1 Replies
332 Views
Hi all, I'm using AVPictureInPictureController to show CMSampleBuffers. No problems with that. When the Picture in Picture view/window is active and the phone is locked for long enough (~30 seconds), the Picture in Picture view/window will show black. I've noticed the same happens with Netflix, so I assume there is no way around that. So when that happens (i.e. Picture in Picture view/window will showing black), I would like to just stop Picture-in-Picture mode. For this, I would need to be able to detect when Picture in Picture view/window will starts showing black pixels. I've tried listening for UIApplication lifetime events (such as didResignActive. and didMoveToBackground), but as my app is a location-based app that received Location updates in the background, those are not at all an indicator of the black PiP window. Any suggestions for me on how to handle the PiP window showing a black window upon unlocking the phone?
Posted
by Joride.
Last updated
.
Post marked as solved
3 Replies
1.2k Views
As part of a hobby project, I'm working on a 2D game engine that will draw each pixel every frame, using a color from a palette. I am looking for a way to do that while maintaining a reasonable frame rate (60fps being the minimum). Without any game-logic in place, I am updating the values of my pixels with some value form the palette. I'm currently taking the mod of an index, to (hopefully) prevent the compiler from doing some loop-optimisation it could do with a fixed value. My very naive implementation of updating the bytes in the pixel array goes like this. On an iPhone 12 Pro, each run of updating all pixel values takes on average 43 ms, while on a simulator running on an M1 mac, it takes 15 ms. Both unacceptable, as that would leave not for any additional game logic (which would be much more operations than taking the mod of an Int). I was planning to look into Metal and set up a surface, but clearly the bottleneck here is the CPU, so if I can optimize this code, I could go for a higher-level framework. Any suggestions on a performant way to write this many bytes much, much faster (parallelisation is not an option)? struct BGRA { let blue: UInt8 let green: UInt8 let red: UInt8 let alpha: UInt8 } let BGRAPallet = [ BGRA(blue: 124, green: 124, red: 124, alpha: 0xff), BGRA(blue: 252, green: 0, red: 0, alpha: 0xff), // ... 62 more values in my code, omitting here for brevity ] private func test() { let pixelBufferPtr = UnsafeMutableBufferPointer<BGRA>.allocate(capacity: screenWidth * screenHeight) let runCount = 1000 let start = Date.now for _ in 0 ..< runCount { for index in 0 ..< pixelBufferPtr.count { pixelBufferPtr[index] = BGRAPallet[index % BGRAPallet.count] } } let elapsed = Date.now.timeIntervalSince(start) print("Average time per run: \((Int(elapsed) * 1000) / runCount) ms") }
Posted
by Joride.
Last updated
.
Post not yet marked as solved
1 Replies
510 Views
As a proof of concept, I am trying to create bare-bones mac-command line app (in Swift) that allows me to send a string as push notification to my own iPhone. I'm trying to follow the guide from Apple, however, I'm stuck creating the Jason Web Token. The guide kindly refers to JWT documentation, and leaves the most difficult part as an exercise to the user: actually creating the JWT (turning the difficulty up to 11 for me ;) ). I've tried a number of things (mostly by scraping on the internets, sadly), but when I try to verify my token at the [JWT site](https://jwt. io), is always invalid. High level, here is my understanding (let's sanity check my thinking, before diving into details: Create 3 JSON-strings: header, claims and payload Base64 encode each one separately Combine these three pieces of data like so let Data((headerBase64String + "." + claimsBase64String + "." + payloadBase64String).utf8) Encrypt this this data using an algorithm called 'ES256' (no idea how to do this, could not find any documentation within Cryptokit on this one). Print the data as string, and enter the results into [JWT site](https://jwt. io). No joy. I would like to use nothing but default libraries (i.e. Foundation, Cryptokit etc), and not make use of IBM's Kibana project (which is what majority of online suggestions seem to be doing). I'm aiming for a thorough understanding here. Where do I need help to kickstart my understanding?
Posted
by Joride.
Last updated
.
Post marked as solved
5 Replies
3.8k Views
I'm pretty sure I'm missing something completely obvious, but I can't see what. I watched WWDC session, read the Swift evolution blog, and they all make sense, but still it doesn't click for me. Please help me out here :) . I'm diving into adopting the 'new' async/await style of coding (I know, it's old news at this point, but I could only get to it now), and so I'm all pumped to get my code to go eleven and therefore I wrote a small data-downloader class. It has one method, well two: one oldskool function with a completionHandler, and one new style async/await one. When using the oldskool one, it works as everyone would expect: print(1) dataFetcher.fetchSomeData { print(2) let data = $0 // process data ... print(3) } print(4) The output is, unsurprisingly: 1 4 2 3 Now, when I use my new style function: let data = await dataFetcher.fetchSomeData() // process data ... Xcode gives me an error: 'async' call in a function that does not support concurrency That makes sense, I am calling this in the viewDidLoad() method of a UIViewController subclass. Can't mark viewDidLoad() as await, as super's implementation is not async. No problem, let me wrap it in Task: print(1) Task { print(2) let data = await dataFetcher.fetchSomeData() // process data ... print(3) } print(4) No errors, and this code works exactly as expected, the output is: 1 4 2 3 So now I am wondering: why take the effort of changing/adding code for async/await style function that ultimately end up requiring exactly the same amount of code, and is exactly as non-linear as completionHandlers? Note that the dataFetcher only has one property, an instance ofURLSession, so I am also not even managing my own queues or threads in the oldskool method vs the new one. They just wrap URLSession's functions: func dataTask(with request: URLRequest, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask and func download(for request: URLRequest, delegate: URLSessionTaskDelegate? = nil) async throws -> (URL, URLResponse) Is async/await useful only with SwiftUI maybe? What am I missing here? Please help me see the light.
Posted
by Joride.
Last updated
.
Post marked as solved
8 Replies
2.1k Views
In my app, users can select from a range of UI color-palettes to customize the look of the app to suite their preference. The app's root viewcontroller is a UINavigationController (this app is not using SwiftUI, nor has it adopted UIScene yet). However, I noticed only the first time (to be specific: this is in the appDelegate's application(:didFinishLaunchingWithOptions:), so before anything is actually rendered to the screen) the appearance settings are applied, but subsequent changes do not take effect. However, the following code seems to 'fix' the issue: self.window?.rootViewController = nil self.updateAppearance() self.window?.rootViewController = navigationController This to me seems hacky/kludgy and unlikely to be a sustainable 'fix', and I think it indicates that the appearance information is only taken into account when a view(controller) gets inserted into the view(controller) hierarchy, in other words: when it gets drawn. So then the question would be: how to tell a UINavigationController / Bar to redraw using the updated appearance settings? I'm sure I'm overlooking something relatively simple (as I imagine this kind of thing is something many apps do to support darkmode), but alas, I can't seem to find it. I setup a small test-project to isolate this issue. It has only one custom viewcontroller (ContentViewController) which only sets the backgroundColor in viewDidLoad(), and an AppDelegate (code below). No storyboards, no UIScene related things. So, here is the minimal code that reproduces my issue: AppDelegate.swift: import UIKit @main class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? var rootNavigationController: UINavigationController? let contentViewController = ViewController() let timer = DispatchSource.makeTimerSource(queue: DispatchQueue.main) func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { window = UIWindow() let navigationController = UINavigationController(rootViewController: contentViewController) rootNavigationController = navigationController window?.rootViewController = navigationController window?.makeKeyAndVisible() // initial setup of appearance, this first call will take effect as expected updateAppearance() // setup a timer to repeatedly change the appearance of the navigationbar timer.setEventHandler { /// ! uncommenting this line and the one after `self.updateAppearance()` /// will cause `self.updateAppearance()` to take effect as expected // self.window?.rootViewController = nil self.updateAppearance() //self.window?.rootViewController = navigationController } timer.schedule(deadline: .now(), repeating: .seconds(2), leeway: .milliseconds(50)) timer.resume() return true } // some vars to automatically toggle between colors / textstyles var colorIndex = 0 let colors = [ UIColor.blue, UIColor.yellow] let textStyles: [UIFont.TextStyle] = [.title3, .body] func updateAppearance() { let color = colors[colorIndex] let textStyle = textStyles[colorIndex] contentViewController.title = "bgColor: \(colorIndex) \(textStyle.rawValue)" colorIndex = (colorIndex == 0) ? 1 : 0 let textColor = colors[colorIndex] self.rootNavigationController?.navigationBar.isTranslucent = false let navigationBarAppearance = UINavigationBarAppearance() navigationBarAppearance.configureWithOpaqueBackground() navigationBarAppearance.backgroundColor = color         let textAttributes: [NSAttributedString.Key : Any] =         [.font: UIFont.preferredFont(forTextStyle: textStyle),          .foregroundColor: textColor ] navigationBarAppearance.titleTextAttributes = textAttributes UINavigationBar.appearance().standardAppearance = navigationBarAppearance UINavigationBar.appearance().compactAppearance = navigationBarAppearance UINavigationBar.appearance().scrollEdgeAppearance = navigationBarAppearance } } ViewController: import UIKit class ViewController: UIViewController {     override func viewDidLoad()     {         super.viewDidLoad()         view.backgroundColor = UIColor.lightGray     } }
Posted
by Joride.
Last updated
.
Post not yet marked as solved
0 Replies
687 Views
As per the title, but let me provide some more context: on macos, using the Photos app, I can change the ‘poster frame, for a video. This frame is the one displayed as a thumbnail. on iOS’ Photos app this functionality does not (see to?) exist. So, to solve my own problem, I would like to build an app that does just that. I am not sure how ‘poster frame’ is implemented, and have no idea where to start looking (perusing the PhotoKit and AVAssetWriter documentation, I didn’t find any hints on ‘poster frame’. I am just looking for some pointers at this point, to understand if this is at all possible.
Posted
by Joride.
Last updated
.
Post not yet marked as solved
1 Replies
713 Views
Hey all, I'm currently investigating whether to integrate an app with HealthKit. I can't seem to find how a dev would go about testing that integration. This app would only be writing data to HealthKit, not reading from it. What is a good dev-strategy for working with HealthKit? "No need, non-production builds write into some kind of sandbox, does not affect 'real' HK data" ? Use a separate device + iCloud account Write some test/dev data, and delete Any suggestion (or links to docs that I missed) are much appreciated!
Posted
by Joride.
Last updated
.
Post not yet marked as solved
2 Replies
897 Views
When using UIDocumentBrowserViewController in conjunction with a 'file' created by UIManagedDocument, the 'file' is seen by UIDocumentBrowserViewController as what it really is: a folder. Tapping on the folder shows a subfolder named 'StoreContent', which in turn shows the CoreData generated files ('persistentStore', 'persistenStore.shm' and 'persistentStore.wal'). These are grayed out, and also show the icon of another app.How would one go about using UIManagedDocument in conjunction with UIDocumentBrowserViewController?I filed a bug for this on July 30, but this one was ignored so far.
Posted
by Joride.
Last updated
.
Post not yet marked as solved
0 Replies
545 Views
I built a mac app, using old fashioned frameworks, cocoa.I'm running Xcode Version 11.2.1 (11B500), on macOS Mojave 10.14.6 (18G1012).My app runs in what appears to be non retina-resolution (labels, textfields, mapkit) when I launch the app from the /Applications folder.The build is obtained by choosing 'Archive', then 'Distribute App' and then 'Copy App'. The exported folder contains the app-bundle. When I launch this bundle from that folder, stored on ~/Desktop, it runs in seemingly retina resolution, but when I run it from /Applications, it runs in what appears non-retina resolution.The app has all Icons set, for all resolutions. What couls be causing this behaviour?
Posted
by Joride.
Last updated
.
Post not yet marked as solved
6 Replies
922 Views
Question:How can I make it so that the 'undo' menuItem actions reaches the NSApplication-subclass?Context:In my storyboard there is an NSMenuItem called 'Undo', it came with the template.My app uses a subclass of NSApplication, and in this class I implemented@objc func undo(_ sender: Any){}I did not implementoverride func validateMenuItem(_ menuItem: NSMenuItem) -&gt; BoolIn the storyboard the menuItem's action is 'undo:', and the target is 'first responder'.The problem I have is that the menuItem is never enabled, and when I implement 'validateMenuItem(_:)', it is called only for 'startDictation:' and 'orderFrontCharacterPalette:'.However, when I change the method signature in my NSApplication subclass to:@objc@IBActionfunc undo2(_ sender: Any)and update the storyboard to use this action, this method DOES get called (note that it is called undo2)My application is not document based, and the structure is:WindowController -&gt; Window -&gt; ViewController -&gt; TableViewNot sure it if this is relevant, but the viewController implements cut, copy, paste and delete, and as such has a validateMenuItem(_:) implementation.
Posted
by Joride.
Last updated
.