Post

Replies

Boosts

Views

Activity

Reply to How to turn On/Off iCloudKitSync on a SwiftUI application
Not really a lot of data, about 10-50 objects with 10 properties each. So you think the most appropriate thing to do is use the local container if sync is off and switch to cloudKit container if it's on? My main struggle is not knowing how to structure my code in a way that I can turn On/Off sync on runtime from other views to test it and see if it will work.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jan ’22
Reply to How to update the CloudKit schema after the app has been released to the AppStore
CloudKit Limitations: Mirroring a Core Data Store with CloudKit | Apple Developer Documentation Determine If Your App Is Eligible for Core Data with CloudKit Apps adopting Core Data can use Core Data with CloudKit as long as the persistent store is an NSSQLiteStoreType store, and the data model is compatible with CloudKit limitations. For example, CloudKit does not support unique constraints, undefined attributes, or required relationships.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jun ’22
Reply to Throwing paper/ball animation effect in SwiftUI
I gave up after spending a lot of time trying to do the animation in SwfitUI and ended up reusing the existing UIKit animation using a UIViewRepresentable as suggested in the following thread. http://stackoverflow.com/questions/70553786/animating-a-swiftui-view-with-uiview-animate/70645853#70645853/ import SwiftUI struct WrapUIKitAnimationInSwiftUI: View { @State private var isAnimating = false var body: some View { HStack{ Image(systemName: "circle.fill") .font(.system(size: 65)) .foregroundColor(.blue) .throwAnimation(isAnimating: $isAnimating) .onTapGesture { isAnimating.toggle() } } } } struct ThrowAnimationWrapper<Content: View>: UIViewRepresentable{ @ViewBuilder let content: () -> Content @Binding var isAnimating: Bool func makeUIView(context: Context) -> UIView { UIHostingController(rootView: content()).view } func updateUIView(_ uiView: UIView, context: Context) { if isAnimating{ UIView.animateKeyframes(withDuration: 1.5, delay: 0.0, options: [.calculationModeCubic], animations: { UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0.2, animations: { uiView.center = CGPoint(x: 250, y: 300) }) UIView.addKeyframe(withRelativeStartTime: 0.0, relativeDuration: 0.9, animations: { uiView.center = CGPoint(x: 100 + 75, y: 100 - 50 ) uiView.transform = CGAffineTransform(scaleX: 0.75, y: 0.75) }) UIView.addKeyframe(withRelativeStartTime: 0.1, relativeDuration: 0.7, animations: { uiView.center = CGPoint(x: 100, y: 100) uiView.transform = CGAffineTransform(scaleX: 0.2, y: 0.2) }) }, completion: { _ in uiView.transform = CGAffineTransform(scaleX: 1.0, y: 1.0) }) } } } extension View { func throwAnimation( isAnimating: Binding<Bool>) -> some View { modifier(ThrowAnimationViewModifier(isAnimating: isAnimating)) } } struct ThrowAnimationViewModifier: ViewModifier { @Binding var isAnimating: Bool func body(content: Content) -> some View { ThrowAnimationWrapper(content: { content }, isAnimating: $isAnimating) } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Sep ’22
Reply to What would be the best logic for updating a file periodically after an app has been released
Thanks a lot for the good ideas. The one thing I don't think I was clear on, was the fact that the update will always be triggered manually and will be followed by a new AppStore submission. I'll basically decide in what app version/release I want to run the update. In other words, the update could happen sooner than a year. What I was thinking is something like my first example but with the ability to be able to manually forece-change the shouldLoad variable to true for all users, existing and new at any point. Again, the update would need to happen to all users, and new users do not need to know about the original content in the file as long as the latest is loaded.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jan ’23
Reply to What would be the best logic for updating a file periodically after an app has been released
Yes, the file is included in the app update, it's not in the server. The user doesn't need to know as long as they get the latest file released in the latest app version. I have a JSON that is included in the app. At the first app launch, it will be read and load all of its content to Core Data. Now, if later on the JSON file gets new info and needs to update Core Data I would like to reload the entire JSON file. And again, this will be done in a new app release. I can do it the way I showed it in my original post or use new variables to check against every time there is an update, but I don't really like it. I was wondering if there is a way to overwrite the shouldLoad variable to true to make it look as if it was the first app launch even for existing users. I hope it starts making sense. Thanks a lot for following along.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jan ’23
Reply to What would be the best logic for updating a file periodically after an app has been released
Yes, everything occurs in the app. The user doesn't have to do anything except update the app to the new version, otherwise, he can continue using the app with the old file. I really like the idea of having a flag in the JSON file. Something like, if flagInJSONFile != lastSavedInUserDefaultsVariable{ updateFile()} In the JSON file I could name the flag, update2023 then overwrite it next year or the next update to something like update2024. if update2023 != update2024{updateFile()} Thanks a lot for the good ideas.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jan ’23
Reply to Understanding Dependency Injection - Swift
I guess my issue is that I'm not seeing the whole picture and it feels like I'm writing a lot more code and making things more complicated for little benefit; at least I don't see the benefit since I don't unitest and I'm a single developer writing small applications. For instance, if we use Example 1 and Example 2 in a SwiftUI view and compare the code, with and without Dependency Injection, Example 2 uses a lot more code and looks more complicated. Again, I guess I still don't see the benefit of the extra complexity. Example 1: Without Dependency Injection class Stereo{ func volume(){ print("Adjusting volume...") } } class Car{ var stereo = Stereo() func adjustVolume(){ stereo.volume() } } struct ContentView: View { var car = Car() var body: some View { Button("Adjust Volume"){ car.adjustVolume() } } } Calling the CarView in other views CarView() Example 2: With Dependency Injection class Stereo{ func volume(){ print("Adjusting volume...") } } class Car{ var stereo: Stereo init(stereo: Stereo){ self.stereo = stereo } func adjustVolume(){ stereo.volume() } } struct CarView: View { var car: Car init(car: Car){ self.car = car } var body: some View { Button("Adjust Volume"){ car.adjustVolume() } } } ####Calling the CarView in other views. CarView(car: Car(stereo: Stereo()))
Topic: Programming Languages SubTopic: Swift Tags:
Jan ’23
Reply to CloudKit Stopped Syncing after adding new Entities
Your issue sounds more like a schema issue. Did you recently add or removed Entities or attributes to your Core Data model? If you did, you must deploy schema changes in the CloudKit console, by going to CloudKit Console -> Development Database -> Deploy Schema Changes. If you haven't made any changes to your Core Data model, make sure that all of your Entities and attributes are present in the Development database under Schema -> Record Types. If you're missing Entities or attributes, go to your app and enter some data for the missing entities or attributes, this will create them in the development database; make sure to have CloudKit on in your app when you enter the data. I hope it makes sense.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
May ’23
Reply to How does the Reminders app implement manual sort order?
It's hard to tell if Apple uses Core Data and CloudKit, but my guess is that they do. I'm not really sure what you mean by "reordering items" but I can tell you that using Core Data and CloudKit is very straightforward, just search for NSPersistentCloudKitContainer for using CloudKit and for Core Data I highly recommend you to watch the following tutorials; they're great. Swiftful Thinking: https://www.youtube.com/watch?v=BPQkpxtgalY
Aug ’23
Reply to Group Core Data items by category in List in SwiftUI
Here what worked for me. It basically returns and displays all categories and their respective items from the specified list. CategoryServiceModel func loadCategories(for list: List) -> ([Category], [Item]) { let request = NSFetchRequest<Category>(entityName: "Category") let predicate = NSPredicate(format: "ANY items IN %@", list.items ?? []) request.predicate = predicate let sort = NSSortDescriptor(keyPath: \Category.name, ascending: true) request.sortDescriptors = [sort] do { let categories = try manager.context.fetch(request) var categories: [Category] = [] var items: [Item] = [] for category in categories { categories.append(category) if let items = category.items?.allObjects as? [Item] { let filteredItems = items.filter { $0.list == list } items.append(contentsOf: filteredItems) } } return (categories, items) } catch let error { print("Error fetching categories. \(error.localizedDescription)") return ([], []) } } SwiftUI List { ForEach(categorySM.categories) { category in Section(header:Text(category.name ?? "")){ ForEach(category.items?.allObjects as? [Item] ?? []) { item in Text("\(item.name ?? "")") } } } } .onAppear{ categorySM.loadCategories(for: selectedList) }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Sep ’23
Reply to How to resize the image displayed when selecting an item in a Picker view
@Claude31 - Thank you very much for your reply. For some reason resizing the UIImage directly solves the issue. if let inputImage = UIImage(data: category.image ?? Data()) { let resizeImage = inputImage.scalePreservingAspectRatio(targetSize: CGSize(width: 25, height: 25)) Image(uiImage: resizeImage) .resizable() .scaledToFit() } Code for resizing the UIImage extension UIImage { func scalePreservingAspectRatio(targetSize: CGSize) -> UIImage { // Determine the scale factor that preserves aspect ratio let widthRatio = targetSize.width / size.width let heightRatio = targetSize.height / size.height let scaleFactor = min(widthRatio, heightRatio) // Compute the new image size that preserves aspect ratio let scaledImageSize = CGSize( width: size.width * scaleFactor, height: size.height * scaleFactor ) // Draw and return the resized UIImage let renderer = UIGraphicsImageRenderer( size: scaledImageSize ) let scaledImage = renderer.image { _ in self.draw(in: CGRect( origin: .zero, size: scaledImageSize )) } return scaledImage } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Sep ’23
Reply to Restart sync when using NSPersistentCloudKitContainer
With the following code I'm successfully turning On or Off sync between CoreData and CloudKit. I have iCloudSync saved in UserDefault / @AppStorage and controlled with a toggle switch in my app settings. This line is what turn it off description.cloudKitContainerOptions = nil, I hope it helps. class CoreDataManager: ObservableObject{ // Singleton static let instance = CoreDataManager() private let queue = DispatchQueue(label: "CoreDataManagerQueue") @AppStorage(UserDefaults.Keys.iCloudSyncKey) private var iCloudSync = false lazy var context: NSManagedObjectContext = { return container.viewContext }() lazy var container: NSPersistentContainer = { return setupContainer() }() func updateCloudKitContainer() { queue.sync { container = setupContainer() } } func setupContainer()->NSPersistentContainer{ let container = NSPersistentCloudKitContainer(name: "YourCoreDataContainerName") guard let description = container.persistentStoreDescriptions.first else{ fatalError("###\(#function): Failed to retrieve a persistent store description.") } description.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey) description.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey) if iCloudSync{ let cloudKitContainerIdentifier = "iCloud.com.example.DatabaseName" if description.cloudKitContainerOptions == nil { let options = NSPersistentCloudKitContainerOptions(containerIdentifier: cloudKitContainerIdentifier) description.cloudKitContainerOptions = options } }else{ description.cloudKitContainerOptions = nil } container.loadPersistentStores { (description, error) in if let error = error{ print("Error loading Core Data. \(error)") } } container.viewContext.automaticallyMergesChangesFromParent = true container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy return container } func save(){ do{ try context.save() }catch let error{ print("Error saving Core Data. \(error.localizedDescription)") } } }
Jun ’24