Writing models in separate files or in one file? - ios

I used to write Models in swift projects in separate files and that what I usually see in others projects, but wouldn't be easier to put them in one file? I want to know which is the best practice and why we supposed to follow? here an example of separating them:
User.swift
import Foundation
class User: NSObject {
var name: String?
var email: String?
var id: String?
}
Post.swift
class Post: NSObject {
var id: String?
var type: String?
var imageUrl: String?
var caption: String?
}

Related

How to set default value in core data array ? How to override the default value ? How to customize category?

I'm trying to make a Storage Expiration Notification APP.
I create a class called Product, here are the properties.
#NSManaged public var productName: String?
#NSManaged public var quantity: String?
#NSManaged public var category = ["", "Food", "Daily", "Makeup"]
#NSManaged public var chooseCategory: Int16
#NSManaged public var purchaseDate: String?
#NSManaged public var expiredDate: String?
#NSManaged public var productID: String?
But there's an Error showed that #NSManaged property cannot have an initial value
Hence, I only can move the Category array(use picker controller to choose the values) to ViewContorller.swift. But I want to create a Customize Category array that users can change the value. For instance, the default category is ["Food", "Daily", "Makeup"], users can change the value to ["Drink", "Wine", "Battery"]. Should I use archiving, or create a new class? I have no idea how to implement it.
The Core Data way to do this is by overriding awakeFromInsert. That function is inherited from NSManagedObject and is called once when the object is first inserted into a managed object context. For this case it would look something like
func awakeFromInsert() {
category = ["", "Food", "Daily", "Makeup"]
}
It doesn't work in exactly the same way as a Swift initial value but it has the same effect since it happens when you create a new instance.
The error is right, an #NSManaged property cannot have an initial value.
A lightweight Swift solution is a JSON string attribute and a computed property for the conversion.
#NSManaged public var category : String
and
var categoryArray : [String] {
get { (try? JSONDecoder().decode([String].self, from: Data(category.utf8))) ?? [] }
set {
let data = try! JSONEncoder().encode(newValue)
category = String(data: data, encoding: .utf8)!
}
}
Set the default value
"[\"\",\"Food\",\"Daily\",\"Makeup\"]
either in awakeFromInsert or in Interface Builder in the model

Nested Firestore Data Model

I am working on a classified ads app (something like craigslist) I am looking at how best to structure the data model using Firestore (NoSQL Database).
The issue I'm facing is structuring items that have additional fields. For instance, electronic items will have additional fields such as RAM, Storage, etc.
I currently have the following model
enum Category: Codable {
case standard
case phone(Phone)
case tv(TV)
}
struct Item: Codable {
var document_ID: String? = nil
var title: String
var created_at: Int
var category: Category
}
struct Phone: Codable {
var brand: String
var model: String
var RAM: String
var storage: String
}
struct TV: Codable {
var size: Int
var screen_technology: String
}
Although I am not sure this is the best way as the category object is being mapped too many times.

Cannot use "description" keyword with NSObject

I am parsing a json and use this NSObject class to access values, but I cant use "description" keyword to match the key "description" in json data. The compiler says "description is a inner property in NSObject".
class JsonDetails: NSObject {
var id: NSNumber?
var title: String?
var description: String?
var address: String?
var postcode: String?
var phoneNumber: String?
var latitude: String?
var longitude: String?
var image: [Img]?
class Img: NSObject {
var small: String?
var medium: String?
var large: String?
}
}
Because "description" is already an inherited method of NSObject you cannot have a var of the same name. Renaming your var to 'desc' is an option though.

How to filter optional NSMutableSet in core data many to many relationship?

I have two core data entity that has many to many relationship, lets say user and project entity with the following attributes.
extension Project {
#NSManaged var project: String?
#NSManaged var projectId: String?
#NSManaged var user: NSMutableSet?
}
extension User {
#NSManaged var address: String?
#NSManaged var dateOfBirth: String?
#NSManaged var email: String?
#NSManaged var firstName: String?
#NSManaged var lastName: String?
#NSManaged var phoneNumber: String?
#NSManaged var userId: String?
#NSManaged var username: String?
#NSManaged var projects: NSMutableSet?
}
Now, i have table view which show all list of project and have a function to filter the project by user.
Here is my filter function.
func getFilteredProjects() {
//projectArray holds all project data
//loggedInUser is an user instance
filteredProjectArray = projectArray.filter({ $0.user!.containsObject(loggedInUser) })
projectTableView.reloadData()
}
In above code, i had to force unwrap optional user set.
i am afraid that using that piece of code will break my application if the user set is nil (which could happen depends on deletion rule).
My question is, is there any way to filter optional NSMutableSet without force unwrapping it?
You can use optional chaining (not compiler tested):
projectArray.filter { $0.user?.containsObject(loggedInUser) == true }
But the "Core Data way" would be to execute a fetch request
on the "Project" entity with a predicate
NSPredicate(format: "ANY user = %#", loggedInUser)

swift core data relationship one to many for own entity

Hi I'm building a newspaper database which have item relationship to itself (item can have many other item as child)
here is my NSmanageObjectSubclass
import Foundation
import CoreData
extension Item {
#NSManaged var by: String?
#NSManaged var dead: NSNumber?
#NSManaged var descendants: NSNumber?
#NSManaged var id: NSNumber?
#NSManaged var isdeleted: NSNumber?
#NSManaged var score: NSNumber?
#NSManaged var text: String?
#NSManaged var time: NSDate?
#NSManaged var title: String?
#NSManaged var type: String?
#NSManaged var url: String?
#NSManaged var kids: NSSet?
#NSManaged var parent: Item?
#NSManaged var parts: NSSet?
}
Problem is that how can i add item to property kids: NSSet
the relationship define is one to many to its own with reverse. Any help is much appreciate. Thanks.
my coredata xcmodel
First update your class Managed Object class to use Sets instead of NSSet
import Foundation
import CoreData
extension Item {
#NSManaged var by: String?
#NSManaged var dead: NSNumber?
#NSManaged var descendants: NSNumber?
#NSManaged var id: NSNumber?
#NSManaged var isdeleted: NSNumber?
#NSManaged var score: NSNumber?
#NSManaged var text: String?
#NSManaged var time: NSDate?
#NSManaged var title: String?
#NSManaged var type: String?
#NSManaged var url: String?
#NSManaged var kids: Set<Item>
#NSManaged var parent: Item?
#NSManaged var parts: NSSet?
}
Secondly create a fetchRequest named getItemByID with expression
id == $ID
Third create a function to get item by id
func getItemById(ID:String) -> Item?
{
let fetchRequest : NSFetchRequest = self.managedObjectModel.fetchRequestFromTemplateWithName("getItemByID", substitutionVariables: ["ID": ID])!
do {
let fetchedResult = try managedObjectContext!.executeFetchRequest(fetchRequest) as! [Item]
if fetchedResult.count > 0 {
let result = fetchedResult[0]
return result
}
}
catch {
print("Could not fetch \(error)")
}
return nil
}
After that you have many options to set relations
a) you create relation after adding parent & child to coreData
func addChildToParent(childID:String,parentID:String)
{
if let childItem = getItemById(childID)
{
if let parentItem = getItemById(parentID)
{
parentItem.kids.insert(menuItemCatering)
childItem.parent = parentItem
}
}
saveContext()
}
Try this to automatically create relationships and properties.
Generating Swift models from Core Data entities
i.e.
Edit: I found the solution to generate a Swift model from Core Data entity:
On Xcode:
Editor > Create NSManagedOjbect > Click button "Next" > Click button
"Next" > Select "Swift" Langage > Click button "Create"
Here is the link on how to create a relationship from scratch. This is a very well explained and awesome tutorial. Go through this and you'll be able to understand all the things.
http://code.tutsplus.com/tutorials/core-data-from-scratch-relationships-and-more-fetching--cms-21505

Resources