Post

Replies

Boosts

Views

Activity

SwiftUI Canvas Text - scale to fill rectangle
How do I draw a single line of text in a SwiftUI Canvas, scaled to fill a given rectangle? Example: Canvas { context, size in let r = CGRect(origin: CGPointZero, size: size); // Whole canvas let t = Text("Hello World"); context.draw(t, in: r); } Outside of Canvas I'd add .minimumScaleFactor(0) .lineLimit(1), and I guess set a large default font size, and I'd get the result I want. But inside Canvas, .minimumScaleFactor and .lineLimit don't seem to be available; they return some View, not Text, which can't be used in context.draw. (Is there a trick to make that work?) I have written the following to do this, but I think there must be an easier way to achieve this! Suggestions? extension GraphicsContext { mutating func draw_text_in_rect(string: String, rect: CGRect) { let text = Text(string) .font(.system(size: 25)); // The font size used here does matter, because e.g. letter spacing // varies with the font size. let resolved = resolve(text); let text_size = resolved.measure(in: CGSize(width: CGFloat.infinity, height: CGFloat.infinity)); let text_aspect = text_size.width / text_size.height; let fit_size = CGSize(width: min(rect.size.width, rect.size.height*text_aspect), height: min(rect.size.height, rect.size.width/text_aspect)); let fit_rect = CGRect(x: rect.origin.x + (rect.size.width-fit_size.width)/2, y: rect.origin.y + (rect.size.height-fit_size.height)/2, width: fit_size.width, height: fit_size.height); let scale = fit_size.width / text_size.width; // For debug: // var p = Path(); // p.addRect(fit_rect); // stroke(p, with: GraphicsContext.Shading.color(.red), lineWidth: 1); translateBy(x: fit_rect.minX, y: fit_rect.minY); scaleBy(x:scale, y:scale); draw(resolved, at: CGPointZero, anchor: UnitPoint.topLeading); transform = CGAffineTransformIdentity; } };
0
0
71
3d
SwiftUI Animation - Spooky Action At A Distance
I have a grid-like container with subviews. I recently changed some internal details of the subviews, so that changes to the values they display animate. Now, the behaviour of the grid container has changed: the animation duration used for the internal changes is now also used when the grid is re-ordered or subviews are added or removed. I can see why this happens: the grid repositions the subviews, and the subview has declared an animation that applies to all of its properties however they are modified. This doesn't seem like a good idea to me. The principle of encapsulation suggests that I should be able to make internal changes to a component without suffering "spooky action at a distance", i.e. other components unexpectedly changing their behaviour. Is this an inherent issue with SwiftUI animations, or does it suggest that I am doing something wrong?
1
0
98
4d
SwiftUI flash animation
I'm struggling to implement a flash animation in SwiftUI. Generally animations animate from one value to another. I'd like to animate from normal to the flashed state and then back to normal, each time the data shown by the view changes. The "flashed state" could be transparent, or a white background, or it could be a scale change for a pulse effect, or something. Example: struct MyView: View { let value: String; var body: some View { ZStack { Capsule() .fill(Color.green); Text(value); } }; }; Each time value changes, I'd like the colour of the capsule to quickly animate from green to white and back to green. I feel this should be easy - am I missing something? For bonus points: I'd like the Text to change to its new value at the midpoint of the animation, i.e. when the white text is invisible on the white background. I'd like to get the flash effect whenever I have a new value even if the new value is equal to the old value, if you see what I mean.
3
0
124
1w
SwiftUI Text is larger when empty
I have a simple SwiftUI Text: Text(t) .font(Font.system(size: 9)) Strangely its ideal height seems to be larger when it is empty. I initially observed this in a custom Layout container that wasn't working quite right. Eventually I looked at the height returned by v.dimensions(in:), and found that when t is non-empty the height is 11; when empty, it's 14. Subsequently I observed similar behaviour in a regular VStack container. Has anyone seen anything similar? Are there any properties that could affect this behaviour? (This is on a watch - I don't know if that matters.)
0
0
81
1w
Assertions in View bodies
I would like to be able to write something like: struct FooView: View { let foo: Foo; var body: some View { assert(foo.valid); ...... } }; but of course I can't, because "Type () cannot conform to View". What's the best way to achieve this?
3
0
137
1w
Swift/objC combined with Swift/C++ interop
Consider this Swift struct: public struct Example { public func foo(callback: ()->Void) { .... } public func blah(i: Int) { .... } .... } Using Swift/C++ interop, I can create Example objects and call methods like blah. But I can't call foo because Swift/C++ interop doesn't currently support passing closures (right?). On the other hand, Swift/objC does support passing objC blocks to Swift functions. But I can't use that here because Example is a Swift struct, not a class. So I could change it to a class, and update everything to work with reference rather than value semantics; but then I also have to change the objC++ code to create the object and call its methods using objC syntax. I'd like to avoid that. Is there some hack that I can use to make this possible? I'm hoping that I can wrap a C++ std::function in some sort of opaque wrapper and pass that to swift, or something. Thanks for any suggestions!
1
0
258
2w
StoreKitSubscriptionView presents an unfriendly message when network is unavailable
I have a rather simple StoreKitSubscriptionView for my app's single subscription. Question: Am I expected to write code to handle lack of network connectivity? When I run the app on development device, not using the local StoreKit configuration but rather the real app store, if the network is not available I get a not-user-friendly error message instead of the normal SubscriptionStoreView content. I'm uncertain if end-users actually see this. Maybe they see a more appropriate "Cannot connect to App Store, try later" message? Maybe I am supposed to check for network and not present the view if it is not available. I don't recall any mention of this in the WWDC video but I guess I should check again. Ideas anyone?
1
0
167
3w
UIColor labelColor in macOS made-for-iPad app is not solid black
When my iOS app runs on macOS in "designed for iPad" mode, the system foreground colour RGBA values seem strange. Looking at [UIColor labelColor], [UIColor secondaryLabelColor] etc. on iOS, I see values like these: (Light Mode) // R G B A fg0 = 0 0 0 255 fg1 = 10 10 13 153 fg2 = 10 10 13 76 fg3 = 10 10 13 45 Note in particular that fg0, aka labelColor, is solid black. When I run it on my Mac, the values I see are: // R G B A fg0 = 0 0 0 216 fg1 = 0 0 0 127 fg2 = 0 0 0 66 fg3 = 0 0 0 25 Here, fg0 has alpha = 216. The result is that it looks like a dark grey, on a white background. Of course it's reasonable for macOS to have a different colour palette than iOS - but native macOS apps seem to have solid 100% black as their foreground colour. Do others see this? What should I be doing? Note that I'm getting colour values using UIColor's getRed: blue: green: alpha: method and then using these colour values for some custom GPU drawing. Previously I was using solid black and white, but at some point I updated it to use UIColor in order to respond to light/dark-mode changes.
0
0
182
3w
Is "remotepairingd" Xcode-related?
Is remotepairingd part of Xcode? It seems to be stuck using 119% CPU. This may have started when I recently paired my new Apple Watch with Xcode - or maybe that is a coincidence. The console is full of: error 16:40:26.237601+0000 remotepairingd socket-1: No more data can be received, connection was closed
0
0
191
Dec ’24
Crash report from user unexpectedly looks like beta app
According to this page: https://developer.apple.com/documentation/xcode/interpreting-the-json-format-of-a-crash-report the storeInfo element of a JSON crash log may contain a deviceIdentifierForVendor element, but quote "This field is only present for TestFlight builds of an app". A user has just sent me a crash report which contains this key, but this isn't a testflight build. The suspicion is of course that the app is "cracked" in some way, but having interacted with the user for some time I think this is unlikely. He has had various issues with the app, affecting multiple devices; I have been wondering if there is something wrong with his Apple account. The docs also say that this "replaces the CrashReporter Key field", yet this crash report contains both. So my question for other developers: if you have any .ips crash logs, obtained from non-testflight users of your apps, please could you grep them for deviceIdentifierForVendor and let me know what you find. If any Apple people have any clues about how this could innocently end up in a crash report, please let me know. Maybe it's a documentation bug?
0
0
195
Dec ’24
SimpleWatchConnectivity sample - modernizing it
Dear Experts, I have been looking at thr SimpleWatchConnectivity sample code: https://developer.apple.com/documentation/watchconnectivity/transferring-data-with-watch-connectivity There are a couple of things in there that look out of date. Firstly, it uses a WKApplicationDelegate to receive the background tasks. I believe this can probably be entirely removed, and replaced with .backgroundTask(.watchConnectivity) { ... } on the App. Is that true? What do I need something inside the { ... } there? Secondly, it is using NSNotificationCenter to send received data from the WCSessionDelegate to the SwiftUI view hierarchy. Is there a better way to do that? I have spent a while trying to work out how a WCSessionDelegate class can connect to a binding to a SwiftUI @State property, and cause the UI to update in response to received data, but I haven't made it work. Are there any newer examples of how to do this? I'm currently only trying to send some simple applicationContext state from the phone to the watch and have some views update to show the latest values. Thanks, Phil.
3
0
251
Dec ’24
Per-project ProjectName-Swift.h, rather than per-target
Dear Experts, I have an Xcode project that generates two iOS app targets. Most of the code is shared between the two targets. Let's call them "Project", "App1" and "App2". I have some Swift code that is called from objC++. To make this work, in the objC++ files currently I #include "App1-Swift.h". Clearly this only works when building App1. What's the right way to set this up to work for both targets? Looking at the build settings, currently the "Generated Header Name" is set to "$(SWIFT_MODULE_NAME)-Swift.h". Presumably, SWIFT_MODULE_NAME expands to the target name. There are various possible ways to fix this, but which one is "right"? I bet that if I fix it in the wrong way, something else will go wrong later. I could: Change the objC++ to #include different headers depending on the target being built. Change the build setting to use the project name (from a variable?) instead of the SWIFT_MODULE_NAME. Somehow cause SWIFT_MODULE_NAME to equal the project name, rather than the target name. Any advice? Thanks.
0
0
213
Nov ’24
Battery state notifications, when app is in the background
Does anyone know how battery state notification (UIDevice.batteryStateDidChangeNotification) is supposed to work regarding app foreground/background state? Assume there is no other reason why the app is running in the background. I have enabled UIDevice.current.isBatteryMonitoringEnabled when the app was in the foreground. What should happen if the external power is later connected or removed when the app is in the background? The docs don't mention this. Possibilities include I don't get a notification, so I should check the state myself when the app next comes to the foreground. I'll get a notification when the app next comes to the foreground, if the state changed while it was in the background. The app will be woken up in the background to receive the notification. The app will be kept running in the background while isBatteryMonitoringEnabled is true. It looks as if it's doing either 3 or 4, which I find a bit surprising. But is this influenced by the fact that it's connected (wirelessly) to the debugger?
4
0
309
Nov ’24
Why I am seeing "Grace Period" events for my new subscription app?
Dear All, I've recently released a new app with a subscription. It has a 3-day free trial and a 1-year subscription, and I've enabled a grace period of 16 days, but the grace period is enabled only for paid-to-paid renewals. As it's a new app, no-one has reached the end of their subscription yet; there will not have been any paid-to-paid renewals. Yet I see a small number of "enter grace period" and "renewal from grace period" events reported in App Store Connect. Can anyone explain why this could be?
3
1
529
Sep ’24