BLACK FRIDAY SALE: Save big on all my Swift books and bundles! >>

In ViewModel or in Entity Extension?

Forums > SwiftUI

My app uses CoreData (Cloud). My Entity is game. My ViewModel works with NSFetchedResultsController<Game>, which in turn fuels an Array [Game].

Conseptually, I'm just wondering where to put some things. As of now almost everything goes into my ViewModel, the extension on Game only contains conformance to comparable and computed properties to handle nil coalescence for the core data attributes.

In my ViewModel I have for instance the following:

          /// Returns an UIImage for the Game from Core Data (binary data) or the default Image
        func getGameImageCoreData(for game: Game) -> UIImage {
            if let imageData = game.iconImage {
                return UIImage(data: imageData) ?? AppImages.gameDefaultImage
            } else {
                return AppImages.gameDefaultImage
            }
        }

        /// Returns the saved local UIImage for the game or the default Image!
        func getGameImage(for game: Game) -> UIImage {
            // Every game should always have an id (uuid)!
            if let imageURL = game.iconImageURL, let id = game.id {
                let path = Bundle.getDocumentsDirectoryURL().appendingPathComponent(id.uuidString, isDirectory: true).appendingPathComponent(imageURL)
                return UIImage(contentsOfFile: path.path) ?? UIImage(named: imageURL) ?? AppImages.gameDefaultImage
            } else {
                return AppImages.gameDefaultImage
            }
        }

        /// Returns the saved UIImage from CloudKit for the game or the default Image!
        func getGameImageFromCloud(for game: Game, completion: @escaping (UIImage) -> Void ) {
            var image: UIImage?

            // Every game should always have an id (uuid)!
            if let imageURL = game.iconImageURL {
                let recordID = CKRecord.ID(recordName: imageURL)

                CKContainer.default().privateCloudDatabase.fetch(withRecordID: recordID) { record, error in
                    if let error = error {
                        print(error.getCloudKitError())
                        return
                    } else {
                        if let record = record {
                            if let asset = record["iconimage"] as? CKAsset {
                                let assetURL = asset.fileURL!

                                let imageData: Data
                                do {
                                    imageData = try Data(contentsOf: assetURL)
                                    image = UIImage(data: imageData)
                                } catch {
                                    print(error.getCloudKitError())
                                }

                                DispatchQueue.main.async {
                                    completion(image ?? AppImages.gameDefaultImage)
                                }
                            }
                        }
                    }
                }
            } else {
                completion(AppImages.gameDefaultImage)
            }
        }

I'm now thinking these should be in my extension on Game. What do you think ?

   

I would put them in an extension of Game. These are all abilities which require an instance of Game. Furthermore, you then will be able to use these in different ViewModels where currently you can't.

1      

I came to the same conclusion, the images belong to the game, hence ...

   

Hacking with Swift is sponsored by RevenueCat

SPONSORED In-app subscriptions are a pain to implement, hard to test, and full of edge cases. RevenueCat makes it straightforward and reliable so you can get back to building your app. Oh, and it's free if your app makes less than $10k/mo.

Learn more

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.