User Tools

Site Tools


swift

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
swift [2023/10/25 20:45]
admin
swift [2023/11/19 22:16] (current)
admin
Line 76: Line 76:
 [[https://​developer.apple.com/​library/​archive/​documentation/​General/​Conceptual/​iCloudDesignGuide/​Chapters/​Introduction.html#//​apple_ref/​doc/​uid/​TP40012094|Apple:​ iCloud Design Guide]] [[https://​developer.apple.com/​library/​archive/​documentation/​General/​Conceptual/​iCloudDesignGuide/​Chapters/​Introduction.html#//​apple_ref/​doc/​uid/​TP40012094|Apple:​ iCloud Design Guide]]
 [[https://​developer.apple.com/​library/​archive/​documentation/​General/​Conceptual/​iCloudDesignGuide/​Chapters/​DesigningForKey-ValueDataIniCloud.html#//​apple_ref/​doc/​uid/​TP40012094-CH7|Apple:​ Designing for Key-Value Data in iCloud]] [[https://​developer.apple.com/​library/​archive/​documentation/​General/​Conceptual/​iCloudDesignGuide/​Chapters/​DesigningForKey-ValueDataIniCloud.html#//​apple_ref/​doc/​uid/​TP40012094-CH7|Apple:​ Designing for Key-Value Data in iCloud]]
 +
 +### Relationship:​ Connect entities in CoreData
 +ref: https://​www.hackingwithswift.com/​books/​ios-swiftui/​one-to-many-relationships-with-core-data-swiftui-and-fetchrequest
 +
 +1. Create Entities in CoreData
 +2. Select the relationship created, in the right tool panel, change `Type` to `To Many`
 +3. Select the entity, in the right tool panel, change `Codegen` to `Manual/​None`
 +4. Use `Editor>​Create NSManagedObject SubClass...` menu to create `...CoreDataClass` file and `...CoreDataProperties` file for each entity.
 +5. In `...CoreDataProperties` file, you should be able to see code like below for adding transactions to this certain piggy object.
 +
 +```
 +extension Piggy {
 +
 +   ​@nonobjc public class func fetchRequest() -> NSFetchRequest<​Piggy>​ {
 +       ​return NSFetchRequest<​Piggy>​(entityName:​ "​Piggy"​)
 +   }
 +
 +   ​@NSManaged public var capacity: NSDecimalNumber?​
 +   ​@NSManaged public var currentMoney:​ NSDecimalNumber?​
 +   ​@NSManaged public var dailyAllowance:​ NSDecimalNumber?​
 +   ​@NSManaged public var id: UUID?
 +   ​@NSManaged public var lastDepositDay:​ Date?
 +   ​@NSManaged public var name: String?
 +   ​@NSManaged public var totalSaved: NSDecimalNumber?​
 +   ​@NSManaged public var transactions:​ NSSet?
 +}
 +extension Piggy {
 +  @objc(addTransactionsObject:​)
 +  @NSManaged public func addToTransactions(_ value: PurchasedItem)
 +
 +  @objc(removeTransactionsObject:​)
 +  @NSManaged public func removeFromTransactions(_ value: PurchasedItem)
 +
 +  @objc(addTransactions:​)
 +  @NSManaged public func addToTransactions(_ values: NSSet)
 +
 +  @objc(removeTransactions:​)
 +  @NSManaged public func removeFromTransactions(_ values: NSSet)
 +}
 +```
 +
 +1. Edit ` ...CoreDataProperties` file, add code like `public var wrappedCapacity:​ NSDecimalNumber { capacity ?? 0.0 }`
 +2. In  ` ...CoreDataProperties` file, `transactions` is an `NSSet`, perform the following steps to convert it from an `NSSet` to a `Set<​PurchasedItem>​` – a Swift-native type where the types of its contents is specificy to `PurchasedItem` type. Convert that `Set<​PurchasedItem>​` into an array, so that `ForEach` can read individual values from there. Sort that array, so the transactions come in a sensible order.
 +
 +```
 +   ​public var transactionArray:​ [PurchasedItem] {
 +       let set = transactions as? Set<​PurchasedItem>​ ?? []
 +       
 +       ​return set.sorted {
 +           ​$0.wrappedTimestamp < $1.wrappedTimestamp
 +       }
 +   }
 +```
 +
 +1. Use them in your View: To read purchased items connected to a certain piggy in a View. Use the following code:
 +
 +```
 +   ​struct HistoryView:​ View {
 +       ​@Environment(\.managedObjectContext) private var viewContext
 +       ​@EnvironmentObject private var persistenceController:​ PersistenceController
 +       let piggy: Piggy
 +   
 +       ​@FetchRequest private var items: FetchedResults<​PurchasedItem>​
 +   
 +       ​init(piggy:​ Piggy) {
 +           ​_items = FetchRequest<​PurchasedItem>​(
 +               ​sortDescriptors:​ [NSSortDescriptor(keyPath:​ \PurchasedItem.timestamp,​ ascending: false)],
 +               ​predicate:​ NSPredicate(format:​ "​piggyStored == %@", piggy)
 +           )
 +           ​self.piggy = piggy
 +       }
 +       
 +       var body: some View {
 +         ​NavigationView {
 +             if (items.count != 0) {
 +                 List {
 +                     ​ForEach(items) { item in
 +                       // view related code
 +                     }
 +                 }
 +             }
 +          }
 +       }
 +   }
 +```
 +
 +Or use the following code. However with this method the HistoryView won't update if you add new purchasedItem (transaction) because it is only monitoring the object `piggy`. To trigger view update when purchasedItem is added, you need to use the method above to fetch `PurchasedItem` directly.
 +
 +```
 +struct HistoryView:​ View {
 +   ​@Environment(\.managedObjectContext) private var viewContext
 +   ​@EnvironmentObject private var persistenceController:​ PersistenceController
 +   let piggy: Piggy
 +
 +   var body: some View {
 +     ​NavigationView {
 +         if (piggy.transactionArrary.count != 0) {
 +             List {
 +                 ​ForEach(piggy.transactionArray) { item in
 +                   // view related code
 +                 }
 +             }
 +         }
 +      }
 +   }
 +}
 +```
 +
 +1. To write new purchased item and connect it to piggy.
 +
 +```swiftUI
 + let newPurchase = PurchasedItem(context:​ viewContext)
 +   ​newPurchase.id = UUID()
 +   ​newPurchase.type = 0  // 0: purchase
 +   ​newPurchase.name = name
 +   ​newPurchase.price = NSDecimalNumber(decimal:​ Decimal(price))
 +   ​newPurchase.timestamp = Date()
 +   ​newPurchase.piggyStored = piggy
 +   try? viewContext.save()
 +```
 +
 +
  
 ## Icons ## Icons
swift.1698237935.txt.gz · Last modified: 2023/10/25 20:45 by admin