Post

Replies

Boosts

Views

Activity

Why doesn't PKStroke conform to Hashable?
I want to work directly with PKStrokes in my app. To transform and change them individually. By one or by grouping them. I thought a perfect way of keeping track of them is to put them in a Set<PKStroke>. By doing this I receive an error: "Type 'PKStroke' does not conform to protocol 'Hashable'". Correct me if I'm wrong, but aren't all PKStrokes unique? Thus they should be eligible to be kept in a Set? What is a correct way of accessing/grouping/storing PKStrokes then? Manually searching for them in canvasView.drawing.strokes? Thank you very much!
0
1
771
Dec ’22
How to increase the width of PencilKit .pen stroke?
The default PKInkingTool with inkType .pen seems to be limited in its stroke width. With a maximum width of around 25.66. Why is that? How can I increase it? Example code: canvasView.tool = PKInkingTool(.pen, color: .black, width: 10) print(canvasView.tool) //Prints: PKInkingTool(tool: <PKInkingTool: 0x2837ba140 com.apple.ink.pen color=UIExtendedSRGBColorSpace 0 0 0 1 width=10.000000>) canvasView.tool = PKInkingTool(.pen, color: .black, width: 20) //Prints: PKInkingTool(tool: <PKInkingTool: 0x282730140 com.apple.ink.pen color=UIExtendedSRGBColorSpace 0 0 0 1 width=20.000000>) //Problem starts here: canvasView.tool = PKInkingTool(.pen, color: .black, width: 30) //Prints: PKInkingTool(tool: <PKInkingTool: 0x28077a0c0 com.apple.ink.pen color=UIExtendedSRGBColorSpace 0 0 0 1 width=25.659260>) canvasView.tool = PKInkingTool(.pen, color: .black, width: 100) //Prints: PKInkingTool(tool: <PKInkingTool: 0x2824e08e0 com.apple.ink.pen color=UIExtendedSRGBColorSpace 0 0 0 1 width=25.659260>) How can I increase the stroke width? 🤔
2
0
1k
Feb ’23
What is a proper way to scale PKCanvasView (UIScrollView)?
I have PKCanvasView in my iPad app. When the user rotates the iPad - I need to scale the Canvas and all the strokes accordingly. So far I've found two ways to scale a PKCanvasView, first with a .zoomScale: GeometryReader { geo in // Canvas View goes here... } .onChange(of: geo.size) { newSize in let canvasScale = newSize.width / myDefaultCanvasWidth canvasView.minimumZoomScale = canvasScale canvasView.maximumZoomScale = canvasScale canvasView.zoomScale = canvasScale } Second with CGAffineTransform: //For short: let transform = CGAffineTransform(scaleX: scaleWidth, y: scaleHeight) canvasView.drawing = canvasView.drawing.transformed(using: transform) Please help me understand the difference between those two methods and which one is correct and preferable? Thank you.
0
0
823
Apr ’23
StateObject doesn't deinit if I use its @Published vars in View's .alert in iOS15
The StateObject doesn't deinit, if I use it's @Published var in an .alert() in iOS15. Here is the minimal code to reproduce the problem: @main struct MyApp: App { var body: some Scene { WindowGroup { MainUIView() } } } struct MainUIView: View { var body: some View { NavigationView { NavigationLink("Go to Child View", destination: ChildView()) } .navigationViewStyle(.stack) } } struct ChildView: View { @StateObject var vm = ChildViewModel() var body: some View { Text("Hello, World!") //HERE. I have to use $vm.showingAlert from the StateObject: .alert("Alert Title", isPresented: $vm.showingAlert, actions: { Button("OK") { } }, message: { Text("Alert Message") }) } } @MainActor final class ChildViewModel: ObservableObject { @Published var showingAlert = false init() { print("INIT") } deinit { print("DE-INIT") } } If you go to ChildView and back - you won't see "DE-INIT" printed in the console on iOS15. Is it a bug or is my code wrong? PS Yes I need the showingAlert var to be in the ChildViewModel as it has business logic which shows an Alert in the View.
0
0
582
Jun ’23
Potential problem with synching users' private CloudKit with NSPersistentCloudKitContainer
Imagine I have a game with new levels every day. Users play my game and their progress is saved in Core Data, which is then synchronized with CloudKit via NSPersistentCloudKitContainer. Users' progress is about 500Kb for each level/day. That's 5 Mb in 10 days. Or 182 Mb in a year. If the user plays my game for a year, gets a new iPhone, and installs my app again — will the NSPersistentCloudKitContainer eventually download all 182 Mb of users' data!?
1
0
544
Jul ’23
Can I access CloudKit's metadata fields with NSPersistentCloudKitContainer?
I've got a simple Core Data Entity that is synchronized with CloudKit via NSPersistentCloudKitContainer. I can read my local fields, but how can I read fields like "Created" & "Modified" from CloudKit? Do I have to add them to my Core Data model and populate them myself? P.S. In his fantastic WWDC talk "Using Core Data with CloudKit", at around 21:40, Nick Gillet talks about how Core Data entities in the CloudKit store are prefixed with "CD_" to separate the things that it manages from the ones CloudKit implements. Then he says: "You wouldn't believe how many people add modify date to their CKRecord". Like it's something redundant.
0
0
515
Aug ’23
Which offer type to use for seasonal discounts?
Hi, I would like to run a seasonal discount on my app and offer -30% off for subscribing for the first year to all new and lapsed users. I can achieve that in two ways: Create a new Subscription with an Introductory offer (for the new users). And add a Promotional offer to existing subscription (for the lapsed users). or Add Offer Code to existing subscription. Make it available for new users and previous subscribers. It seems that both ways produce the same result, which one should I prefer? Are there any caveats to them? Thank you!
1
0
510
May ’24
What is the current proper way to load an image from local filesystem?
I'm just trying to display an image that is stored in the local filesystem, but the more I dig into this the more confused I get. So previously I used this code (it's simplified): func findImage(name: String) -&gt; UIImage? { do { let url = try FileManager.default.url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: false) .appendingPathComponent("MyFolder") .appendingPathComponent("\(name).png") guard let image = UIImage(contentsOfFile: url.path) else { return nil } return image } catch { print(error.localizedDescription) } return nil } Notice I create the URL with just .appendingPathComponent() and turning URL to path via url.path. It works! So what's the question? In Improving performance and stability when accessing the file system I've read that you better use the new appendingPathComponent(_:isDirectory:), that's good, will do. Also url.path is deprecated in iOS18. Should I use url.path(percentEncoded:) instead? What should be the value of percentEncoded when accessing the local filesystem? In this adjacent thread I've read: Don't use UIImage(contentsOfFile:) either, because it's a path-based API. There's no URL-based equivalent, which is an Apple clue that should be doing something else. Is this true? Then how should I store and load my images? Just FYI, I create images like this: private func generateThumbnail(name: String) { guard let drawingWidth = canvasGeo?.size.width, let drawingHeight = canvasGeo?.size.height else { return } let thumbnailRect = CGRect(x: 0, y: 0, width: drawingWidth, height: drawingHeight) Task { UITraitCollection(userInterfaceStyle: .light).performAsCurrent { let image = self.canvasView.drawing.image(from: thumbnailRect, scale: UIScreen.main.scale) guard let data = image.pngData() else { return } // -- HERE do { try FileManager.default.createDirectory(at: try FileManager.default.url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true) .appendingPathComponent("MyFolder"), withIntermediateDirectories: true, attributes: nil) let filename = "\(name).png" let url = try FileManager.default.url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true) .appendingPathComponent("MyFolder") .appendingPathComponent(filename) try data.write(to: url, options: .atomic) // -- and HERE } catch { print(error.localizedDescription) } } } } My usecase — just save the user's PencilKit Canvas as an image and display it back to him on a different View. I'm on SwiftUI and iOS 16+. Would be happy to learn the correct way, thanks!
3
0
573
Jul ’24
What is the aps-connection-initiate entitlement?
I use Core Data and CloudKit in my iOS app, and everything has worked flawlessly so far. I just got a new Mac with an M-chip and now have to run my app in a Rosetta Simulator. iOS17 Rosetta Simulator works great. But iOS16 Rosetta Simulator crashes as soon as I run any CloudKit code, console prints: [CK] BUG IN CLIENT OF CLOUDKIT: Not entitled to listen to push notifications. Please add the 'aps-connection-initiate' entitlement. Although I have "Push Notifications" capability enabled in "Signing and Capabilities" of the project. OK, I open the .entitlements file as a source code and add: <key>aps-connection-initiate</key> <true/> Can confirm, that it started working in the iOS16 Rosetta Simulator. But now I have an error in the Signing and Capabilities: Provisioning profile "iOS Team Provisioning Profile: com.###" doesn't include the aps-connection-initiate entitlement. What exactly is this aps-connection-initiate entitlement? And why haven't I needed it ever before? Should I upload it to App Store ASAP or remove it (since my current version works on iOS16 without this entitlement) Tried searching the web, couldn't find anything about this 'aps-connection-initiate' :'(
0
0
262
Aug ’24