Post

Replies

Boosts

Views

Activity

Trying to load image & identifier from photo library with PhotosPicker
I'm updating an older Mac app written in Objective C and OpenGL to be a mutliplatform app in SwiftUI and Metal. The app loads images and creates kaleidoscope animations from them. It is a document-based application, and saves info about the kaleidoscope into the document. On macOS, it creates a security-scoped bookmark to remember the user's chosen image. On iOS, I use a PhotosPicker to have the user choose an image from their photo library to use. I would like to get the itemIdentifier from the image they choose and save that into my document so I can use it to fetch the image when the user reloads the kaleidoscope document in the future. However, the call to loadTransferable is returning nil for the itemIdentifier. Here is my iOS/iPadOS code: #if os(macOS) // Mac code #else PhotosPicker("Choose image", selection: $selectedItem, matching: .images) .onChange(of: selectedItem) { Task { if let newValue = selectedItem { scopeState.isHEIC = newValue.supportedContentTypes.contains(UTType.heic) let data = try? await newValue.loadTransferable(type: Data.self) print("newValue = \(newValue)") print("newValue.supportedContentTypes = \(newValue.supportedContentTypes)") scopeState.selectedImageID = newValue.itemIdentifier scopeState.selectedImageData = data } } } #endif The debug print statements show: newValue = PhotosPickerItem(_itemIdentifier: "9386762B-C241-4EE2-9942-BC04017E35C1/L0/001", _shouldExposeItemIdentifier: false, _supportedContentTypes: [<_UTCoreType 0x20098cd40> public.png (not dynamic, declared), <UTType 0x11e4ec060> com.apple.private.photos.thumbnail.standard (not dynamic, declared), <UTType 0x11e4ec150> com.apple.private.photos.thumbnail.low (not dynamic, declared)], _content: _PhotosUI_SwiftUI.PhotosPickerItem.(unknown context at $1e75ee3bc).Content.result(PhotosUI.PHPickerResult(itemProvider: <PUPhotosFileProviderItemProvider: 0x11d2bd680> {types = ( "public.png", "com.apple.private.photos.thumbnail.standard", "com.apple.private.photos.thumbnail.low" )}, _objcResult: <PHPickerResult: 0x11b18cff0>))) newValue.supportedContentTypes = [<_UTCoreType 0x20098cd40> public.png (not dynamic, declared), <UTType 0x11e4ec060> com.apple.private.photos.thumbnail.standard (not dynamic, declared), <UTType 0x11e4ec150> com.apple.private.photos.thumbnail.low (not dynamic, declared)] And the returned item has a nil itemIdentifier. (note the _shouldExposeItemIdentifier=false in the log of the selected item). How do I get the itemIdentifier for the user's chosen image? And is that valid to then fetch the asset when the user reloads their document? Is it like a security-scoped bookmark on macOS, where the itemIdentifier is like a key that gives me permission to reload the image? If not, what do I need to do in order to reload the image the next time the user opens a saved kaleidoscope document?
1
0
403
2w
How to load and draw texture with opacity in Metal
The background I'm finally working to convert my very old Mac kaleidoscope application, ScopeWorks, which was written in OpenGL and Objective-C, to a Multiplatform app in SwiftUI and Metal. I'm using the MetalKit MTKView class, wrapped for SwiftUI as an NSViewRepresentable or UIViewRepresentable. I then provide an MTKViewDelegate that provides a draw method. The draw method fetches the current render pass descriptor, creates a command buffer, sets up a render pipeline, and does its drawing. My renderer's makePipeline method looks like this: func makePipeline() { let library = device.makeDefaultLibrary() let pipelineDesc = MTLRenderPipelineDescriptor() pipelineDesc.vertexFunction = library?.makeFunction(name: "vertex_main") pipelineDesc.fragmentFunction = library?.makeFunction(name: "fragment_main") pipelineDesc.colorAttachments[0].pixelFormat = .bgra8Unorm pipeline = try! device.makeRenderPipelineState(descriptor: pipelineDesc) } And my shaders look like this: struct VertexOut { float4 position [[position]]; float2 texCoord; }; vertex VertexOut vertex_main(const device float2* position [[buffer(0)]], uint vid [[vertex_id]]) { VertexOut out; float2 pos = position[vid]; out.position = float4(pos, 0, 1); out.texCoord = pos * 0.5 + 0.5; // basic mapping return out; } fragment float4 fragment_main(VertexOut in [[stage_in]], texture2d<float> tex [[texture(0)]], constant float4& color [[buffer(1)]]) { constexpr sampler s(address::repeat, filter::linear); // float4 texColor = tex.sample(s, in.texCoord); // return texColor * color; float4 textureColor = {1, 2, 3, 4}; if (all(color == textureColor)) { return tex.sample(s, in.texCoord); } else { return color; } // Sample the texture directly — no color tint applied return tex.sample(s, in.texCoord); } The first part of my MTKViewDelegate's draw method looks like this: func draw(in view: MTKView) { guard let drawable = view.currentDrawable, let descriptor = view.currentRenderPassDescriptor, let pipeline = pipeline, let texture = texture else { return } let commandBuffer = commandQueue.makeCommandBuffer()! let encoder = commandBuffer.makeRenderCommandEncoder(descriptor: descriptor)! encoder.setRenderPipelineState(pipeline) encoder.setFragmentTexture(texture, index: 0) descriptor.colorAttachments[0].clearColor = MTLClearColor(red: 0.0, green: 0, blue: 0, alpha: 1.0) // Draw six equilateral triangles forming the hexagon let radius: Float = 0.6 for i in 0..<6 { let angle = Float(i) * (.pi / 3) let cosA = cos(angle) let sinA = sin(angle) let nextA = Float(i+1) * (.pi / 3) let cosB = cos(nextA) let sinB = sin(nextA) let verts: [simd_float2] = [ simd_float2(0, 0), simd_float2(radius * cosA, radius * sinA), simd_float2(radius * cosB, radius * sinB) ] encoder.setVertexBytes(verts, length: MemoryLayout<simd_float2>.stride * 3, index: 0) // Tell the fragment shader to use the texture color. var textureColor: simd_float4 = simd_float4(1, 2, 3, 4) encoder.setFragmentBytes(&textureColor, length: MemoryLayout<SIMD4<Float>>.stride, index: 1) encoder.drawPrimitives(type: .triangle, vertexStart: 0, vertexCount: 3) One of the things the existing app does is load PNG or TIFF images with an alpha channel, and then overlay parts of the image on top of themselves flipped, so you get interesting Moiré patterns in the lines in the resulting kaleidoscope. For now I'm working on a single sample image, loading it into a texture in Metal, and just rendering it as a hexagon and drawing lines for the triangles that make up the hexagon. (For now I'm using the vertex coordinates as the texture coordinates, so I get a hexagonal part of my texture rather than a single triangular part tessellated into a hexagon. I'll fix that later.) In both iOS and OS I set the clear color to black at the beginning of the draw function. The issue: The source image is mostly transparent, but with a lot of partly transparent pixels. Here's what it looks like in Photoshop, where you can see the transparent parts as a checkerboard pattern: (I tried to crop the original image to show the approximate part that I'm rendering in a hexagon, but it's not exact. Look for the same shapes in the different images to compare them.) When I render my hexagon in the Metal view in the iOS version of the app, it looks like it's forcing each pixel to fully opaque or fully transparent: And in the macOS version of the app, it seems to force ALL the pixels to opaque: I haven't shown all the setup code, because it's' a lot. Is there some rendering mode setup I'm missing in order to get it to draw the pixels into the output based on their opacity, including partial opacity?
2
0
894
Mar ’26
Xcode 26 won't connect to new M5 iPad
I took delivery of a new 11 inch M5 iPad Pro yesterday, and have been unable to get it to connect to Xcode so I can build to it. The iPad is running iPadOS version 26.0.1, and I am using Xcode Version 26.0.1 as well. My MacBook Pro is running MacOS 26.0 I enabled developer mode. When I connected the cable I was asked (twice) to trust the computer, and said yes. I get errors saying: "The developer disk image could not be mounted on this device.; Error mounting image: 0xe800010f (kAMDMobileImageMounterPersonalizedBundleMissingVariantError" I've tried disconnecting and reconnecting the cable, quitting and relaunching Xcode, and rebooting both the iPad and the Mac. I've also tried "Clear Trusted Computers" in the developer menu. That triggers the same sequence of having to trust the computer again when I connect it (the dialog appears twice.) Then I go back to the error message above in the devices and simulators screen. I've also tried the command sudo installer -pkg /Applications/Xcode.app/Contents/Resources/Packages/XcodeSystemResources.pkg -target / Nothing works. It's maddening. Does anybody know how I can can get this working? I'm eager to start developing on my new iPad, but I can't get started.
3
0
250
Oct ’25
FKA Accessibility focus seems broken in SwiftUI
There are several ways we are supposed to be able to control a11y (accessibility) focus in FKA (Full Keyboard Access) mode. We should be able to set up an @AccessibilityFocusState variable that contains an enum for the different views that we want to receive a11y focus. That works from VO (VoiceOver) but not from FKA mode. See this sample project on Github: https://stackoverflow.com/questions/79067665/how-to-manage-accessibilityfocusstate-for-swiftui-accessibility-keyboard Similarly, we are supposed to be able to use accessibilitySortPriority to control the order that views are selected when a user using FKA tabs between views. That also works from VO but not from FKA mode. In the sample code below, the `.accessibilitySortPriority() ViewModifiers cause VO to change to a non-standard order when you swipe between views, but it has no effect in FKA mode. Is there a way to either set the a11y focus or change the order in which the views are selected that actually works in SwiftUI when the user is in FKA mode? Code that should cause FKA to tab between text fields in a custom order: struct ContentView: View { @State private var val1: String = "val 1" @State private var val2: String = "val 2" @State private var val3: String = "val 3" @State private var val4: String = "val 4" var body: some View { VStack { TextField("Value 1", text: $val1) .accessibilitySortPriority(3) VStack { TextField("Value 2", text: $val2) .accessibilitySortPriority(1) } HStack { TextField("Value 3", text: $val3) .accessibilitySortPriority(2) TextField("Value 4", text: $val4) .accessibilitySortPriority(4) } } .padding() } }```
4
0
314
Jul ’25
How to animate arbitrary changes to a SwiftUI Path?
In UIKit/Core Animation, I can create a CABasicAnimation that lets me animate changes to the Path in a CAShapeLayer. As long as the new path has the same number of control points as the previous path, Core Animation creates a smooth animation of the changes. It's also possible to animate things like the start and end of the stroke, but I'm talking about arbitrary changes to the path. In SwiftUI, it's pretty easy to animate the stroke so that it looks like it's being drawn by a pen. I'm not talking about that. Say I have a closed path with N vertexes and some of the vertexes are connected with straight lines, while others are connected by quadratic or cubic Bézier curves. I want to move the control points around in arbitrary ways, and change the control points of the Bézier curves. I have a simple Storyboard based project on Github that creates closed N-sided polygons with either rounded or sharp corners, it manages an array of PolygonPoint structs that look like this: public struct PolygonPoint { let point: CGPoint let isRounded: Bool let customCornerRadius: CGFloat? init(point: CGPoint, isRounded: Bool, customCornerRadius: CGFloat? = nil) { self.point = point self.isRounded = isRounded self.customCornerRadius = customCornerRadius } init(previousPoint: PolygonPoint, isRounded: Bool) { self.init(point: previousPoint.point, isRounded: isRounded, customCornerRadius: previousPoint.customCornerRadius) } } The sample app builds a square out of an array of PolygonPoints, and then presents 4 swtiches that controls whether each vertex is rounded or not. It builds a polygon using the CGPath addArc(tangent1End:tangent2End:radius:transform:) function, with a 0 radius for sharp corners and a non-zero corner radius for rounded corners. It wraps changes to the path in a CABasicAnimation, and the result is a simple animation. The project can be found on Github here: RoundedConerPolygon project As a learning exercise, I'd like to convert this project to SwiftUI. The Swift/UIKit project creates CGPaths, and there is an initializer for the Swift Path object that takes a CGPath, so that part is easy. However, SwiftUI wants to observe changes to a simple scalar, or to some sort of animatableData. I've tried to make my PolygonPoint struct conform to VectorArithmetic, but no joy. My attempt is here: RoundedCornerPolygonSwiftUI This seems like it should be easy, but I can't figure out how to make it work. Is there a way to have SwiftUI animate changes to a Path's underlying CGPath like you can in UIKit? I could probably wrap a UIKIt custom view in SwiftUI and do it that way, but I'm trying to learn how to do it "The SwifTUI way."
0
0
910
Oct ’23
Trying to load image & identifier from photo library with PhotosPicker
I'm updating an older Mac app written in Objective C and OpenGL to be a mutliplatform app in SwiftUI and Metal. The app loads images and creates kaleidoscope animations from them. It is a document-based application, and saves info about the kaleidoscope into the document. On macOS, it creates a security-scoped bookmark to remember the user's chosen image. On iOS, I use a PhotosPicker to have the user choose an image from their photo library to use. I would like to get the itemIdentifier from the image they choose and save that into my document so I can use it to fetch the image when the user reloads the kaleidoscope document in the future. However, the call to loadTransferable is returning nil for the itemIdentifier. Here is my iOS/iPadOS code: #if os(macOS) // Mac code #else PhotosPicker("Choose image", selection: $selectedItem, matching: .images) .onChange(of: selectedItem) { Task { if let newValue = selectedItem { scopeState.isHEIC = newValue.supportedContentTypes.contains(UTType.heic) let data = try? await newValue.loadTransferable(type: Data.self) print("newValue = \(newValue)") print("newValue.supportedContentTypes = \(newValue.supportedContentTypes)") scopeState.selectedImageID = newValue.itemIdentifier scopeState.selectedImageData = data } } } #endif The debug print statements show: newValue = PhotosPickerItem(_itemIdentifier: "9386762B-C241-4EE2-9942-BC04017E35C1/L0/001", _shouldExposeItemIdentifier: false, _supportedContentTypes: [<_UTCoreType 0x20098cd40> public.png (not dynamic, declared), <UTType 0x11e4ec060> com.apple.private.photos.thumbnail.standard (not dynamic, declared), <UTType 0x11e4ec150> com.apple.private.photos.thumbnail.low (not dynamic, declared)], _content: _PhotosUI_SwiftUI.PhotosPickerItem.(unknown context at $1e75ee3bc).Content.result(PhotosUI.PHPickerResult(itemProvider: <PUPhotosFileProviderItemProvider: 0x11d2bd680> {types = ( "public.png", "com.apple.private.photos.thumbnail.standard", "com.apple.private.photos.thumbnail.low" )}, _objcResult: <PHPickerResult: 0x11b18cff0>))) newValue.supportedContentTypes = [<_UTCoreType 0x20098cd40> public.png (not dynamic, declared), <UTType 0x11e4ec060> com.apple.private.photos.thumbnail.standard (not dynamic, declared), <UTType 0x11e4ec150> com.apple.private.photos.thumbnail.low (not dynamic, declared)] And the returned item has a nil itemIdentifier. (note the _shouldExposeItemIdentifier=false in the log of the selected item). How do I get the itemIdentifier for the user's chosen image? And is that valid to then fetch the asset when the user reloads their document? Is it like a security-scoped bookmark on macOS, where the itemIdentifier is like a key that gives me permission to reload the image? If not, what do I need to do in order to reload the image the next time the user opens a saved kaleidoscope document?
Replies
1
Boosts
0
Views
403
Activity
2w
How to load and draw texture with opacity in Metal
The background I'm finally working to convert my very old Mac kaleidoscope application, ScopeWorks, which was written in OpenGL and Objective-C, to a Multiplatform app in SwiftUI and Metal. I'm using the MetalKit MTKView class, wrapped for SwiftUI as an NSViewRepresentable or UIViewRepresentable. I then provide an MTKViewDelegate that provides a draw method. The draw method fetches the current render pass descriptor, creates a command buffer, sets up a render pipeline, and does its drawing. My renderer's makePipeline method looks like this: func makePipeline() { let library = device.makeDefaultLibrary() let pipelineDesc = MTLRenderPipelineDescriptor() pipelineDesc.vertexFunction = library?.makeFunction(name: "vertex_main") pipelineDesc.fragmentFunction = library?.makeFunction(name: "fragment_main") pipelineDesc.colorAttachments[0].pixelFormat = .bgra8Unorm pipeline = try! device.makeRenderPipelineState(descriptor: pipelineDesc) } And my shaders look like this: struct VertexOut { float4 position [[position]]; float2 texCoord; }; vertex VertexOut vertex_main(const device float2* position [[buffer(0)]], uint vid [[vertex_id]]) { VertexOut out; float2 pos = position[vid]; out.position = float4(pos, 0, 1); out.texCoord = pos * 0.5 + 0.5; // basic mapping return out; } fragment float4 fragment_main(VertexOut in [[stage_in]], texture2d<float> tex [[texture(0)]], constant float4& color [[buffer(1)]]) { constexpr sampler s(address::repeat, filter::linear); // float4 texColor = tex.sample(s, in.texCoord); // return texColor * color; float4 textureColor = {1, 2, 3, 4}; if (all(color == textureColor)) { return tex.sample(s, in.texCoord); } else { return color; } // Sample the texture directly — no color tint applied return tex.sample(s, in.texCoord); } The first part of my MTKViewDelegate's draw method looks like this: func draw(in view: MTKView) { guard let drawable = view.currentDrawable, let descriptor = view.currentRenderPassDescriptor, let pipeline = pipeline, let texture = texture else { return } let commandBuffer = commandQueue.makeCommandBuffer()! let encoder = commandBuffer.makeRenderCommandEncoder(descriptor: descriptor)! encoder.setRenderPipelineState(pipeline) encoder.setFragmentTexture(texture, index: 0) descriptor.colorAttachments[0].clearColor = MTLClearColor(red: 0.0, green: 0, blue: 0, alpha: 1.0) // Draw six equilateral triangles forming the hexagon let radius: Float = 0.6 for i in 0..<6 { let angle = Float(i) * (.pi / 3) let cosA = cos(angle) let sinA = sin(angle) let nextA = Float(i+1) * (.pi / 3) let cosB = cos(nextA) let sinB = sin(nextA) let verts: [simd_float2] = [ simd_float2(0, 0), simd_float2(radius * cosA, radius * sinA), simd_float2(radius * cosB, radius * sinB) ] encoder.setVertexBytes(verts, length: MemoryLayout<simd_float2>.stride * 3, index: 0) // Tell the fragment shader to use the texture color. var textureColor: simd_float4 = simd_float4(1, 2, 3, 4) encoder.setFragmentBytes(&textureColor, length: MemoryLayout<SIMD4<Float>>.stride, index: 1) encoder.drawPrimitives(type: .triangle, vertexStart: 0, vertexCount: 3) One of the things the existing app does is load PNG or TIFF images with an alpha channel, and then overlay parts of the image on top of themselves flipped, so you get interesting Moiré patterns in the lines in the resulting kaleidoscope. For now I'm working on a single sample image, loading it into a texture in Metal, and just rendering it as a hexagon and drawing lines for the triangles that make up the hexagon. (For now I'm using the vertex coordinates as the texture coordinates, so I get a hexagonal part of my texture rather than a single triangular part tessellated into a hexagon. I'll fix that later.) In both iOS and OS I set the clear color to black at the beginning of the draw function. The issue: The source image is mostly transparent, but with a lot of partly transparent pixels. Here's what it looks like in Photoshop, where you can see the transparent parts as a checkerboard pattern: (I tried to crop the original image to show the approximate part that I'm rendering in a hexagon, but it's not exact. Look for the same shapes in the different images to compare them.) When I render my hexagon in the Metal view in the iOS version of the app, it looks like it's forcing each pixel to fully opaque or fully transparent: And in the macOS version of the app, it seems to force ALL the pixels to opaque: I haven't shown all the setup code, because it's' a lot. Is there some rendering mode setup I'm missing in order to get it to draw the pixels into the output based on their opacity, including partial opacity?
Replies
2
Boosts
0
Views
894
Activity
Mar ’26
Xcode 26 won't connect to new M5 iPad
I took delivery of a new 11 inch M5 iPad Pro yesterday, and have been unable to get it to connect to Xcode so I can build to it. The iPad is running iPadOS version 26.0.1, and I am using Xcode Version 26.0.1 as well. My MacBook Pro is running MacOS 26.0 I enabled developer mode. When I connected the cable I was asked (twice) to trust the computer, and said yes. I get errors saying: "The developer disk image could not be mounted on this device.; Error mounting image: 0xe800010f (kAMDMobileImageMounterPersonalizedBundleMissingVariantError" I've tried disconnecting and reconnecting the cable, quitting and relaunching Xcode, and rebooting both the iPad and the Mac. I've also tried "Clear Trusted Computers" in the developer menu. That triggers the same sequence of having to trust the computer again when I connect it (the dialog appears twice.) Then I go back to the error message above in the devices and simulators screen. I've also tried the command sudo installer -pkg /Applications/Xcode.app/Contents/Resources/Packages/XcodeSystemResources.pkg -target / Nothing works. It's maddening. Does anybody know how I can can get this working? I'm eager to start developing on my new iPad, but I can't get started.
Replies
3
Boosts
0
Views
250
Activity
Oct ’25
FKA Accessibility focus seems broken in SwiftUI
There are several ways we are supposed to be able to control a11y (accessibility) focus in FKA (Full Keyboard Access) mode. We should be able to set up an @AccessibilityFocusState variable that contains an enum for the different views that we want to receive a11y focus. That works from VO (VoiceOver) but not from FKA mode. See this sample project on Github: https://stackoverflow.com/questions/79067665/how-to-manage-accessibilityfocusstate-for-swiftui-accessibility-keyboard Similarly, we are supposed to be able to use accessibilitySortPriority to control the order that views are selected when a user using FKA tabs between views. That also works from VO but not from FKA mode. In the sample code below, the `.accessibilitySortPriority() ViewModifiers cause VO to change to a non-standard order when you swipe between views, but it has no effect in FKA mode. Is there a way to either set the a11y focus or change the order in which the views are selected that actually works in SwiftUI when the user is in FKA mode? Code that should cause FKA to tab between text fields in a custom order: struct ContentView: View { @State private var val1: String = "val 1" @State private var val2: String = "val 2" @State private var val3: String = "val 3" @State private var val4: String = "val 4" var body: some View { VStack { TextField("Value 1", text: $val1) .accessibilitySortPriority(3) VStack { TextField("Value 2", text: $val2) .accessibilitySortPriority(1) } HStack { TextField("Value 3", text: $val3) .accessibilitySortPriority(2) TextField("Value 4", text: $val4) .accessibilitySortPriority(4) } } .padding() } }```
Replies
4
Boosts
0
Views
314
Activity
Jul ’25
How to animate arbitrary changes to a SwiftUI Path?
In UIKit/Core Animation, I can create a CABasicAnimation that lets me animate changes to the Path in a CAShapeLayer. As long as the new path has the same number of control points as the previous path, Core Animation creates a smooth animation of the changes. It's also possible to animate things like the start and end of the stroke, but I'm talking about arbitrary changes to the path. In SwiftUI, it's pretty easy to animate the stroke so that it looks like it's being drawn by a pen. I'm not talking about that. Say I have a closed path with N vertexes and some of the vertexes are connected with straight lines, while others are connected by quadratic or cubic Bézier curves. I want to move the control points around in arbitrary ways, and change the control points of the Bézier curves. I have a simple Storyboard based project on Github that creates closed N-sided polygons with either rounded or sharp corners, it manages an array of PolygonPoint structs that look like this: public struct PolygonPoint { let point: CGPoint let isRounded: Bool let customCornerRadius: CGFloat? init(point: CGPoint, isRounded: Bool, customCornerRadius: CGFloat? = nil) { self.point = point self.isRounded = isRounded self.customCornerRadius = customCornerRadius } init(previousPoint: PolygonPoint, isRounded: Bool) { self.init(point: previousPoint.point, isRounded: isRounded, customCornerRadius: previousPoint.customCornerRadius) } } The sample app builds a square out of an array of PolygonPoints, and then presents 4 swtiches that controls whether each vertex is rounded or not. It builds a polygon using the CGPath addArc(tangent1End:tangent2End:radius:transform:) function, with a 0 radius for sharp corners and a non-zero corner radius for rounded corners. It wraps changes to the path in a CABasicAnimation, and the result is a simple animation. The project can be found on Github here: RoundedConerPolygon project As a learning exercise, I'd like to convert this project to SwiftUI. The Swift/UIKit project creates CGPaths, and there is an initializer for the Swift Path object that takes a CGPath, so that part is easy. However, SwiftUI wants to observe changes to a simple scalar, or to some sort of animatableData. I've tried to make my PolygonPoint struct conform to VectorArithmetic, but no joy. My attempt is here: RoundedCornerPolygonSwiftUI This seems like it should be easy, but I can't figure out how to make it work. Is there a way to have SwiftUI animate changes to a Path's underlying CGPath like you can in UIKit? I could probably wrap a UIKIt custom view in SwiftUI and do it that way, but I'm trying to learn how to do it "The SwifTUI way."
Replies
0
Boosts
0
Views
910
Activity
Oct ’23