Cannot use "description" keyword with NSObject - ios

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.

Related

Problems with class initialization

I think it's a simple problem but a head scratcher.
I'm getting a ....has no initializers error when there actually are initializers.
Here is my code:
(Edit: I've updated the PatientData class to include all the additional variables. I didn't think they made a difference in figuring out the problem, so for the sake of brevity I left them out.)
Data Structures
class PatientData: Identifiable, ObservableObject
{
let id = UUID()
#Published var patientName: String = "Name"
#Published var patientAge: String = "Age"
#Published var patientDOB: String = "DOB"
#Published var patientPhone: String = "Phone"
#Published var patientAddress: PatientAddress
struct PatientAddress
{
var patientStreetAddress: String = "Street"
var patientCity: String = "City"
var patientState: String = "State"
var patientZip: String = "Zip"
init(patientStreetAddress: String, patientCity: String, patientState: String, patientZip: String)
{
self.patientStreetAddress = patientStreetAddress
self.patientCity = patientCity
self.patientState = patientState
self.patientZip = patientZip
}
}
#Published var facilityName: String = "Facility"
#Published var facilityRoom: String = "Room Number"
#Published var facilityFloor: String = "Floor"
#Published var facilityPhoneNumber: String = "Phone Number"
init(patientName: String, patientAge: String, patientDOB: String, patientPhone: String, patientAddress: PatientAddress, facilityName: String, facilityRoom: String, facilityFloor: String, facilityPhoneNumber: String)
{
self.patientName = patientName
self.patientAge = patientAge
self.patientDOB = patientDOB
self.patientPhone = patientPhone
self.patientAddress = patientAddress
self.facilityName = facilityName
self.facilityRoom = facilityRoom
self.facilityFloor = facilityFloor
self.facilityPhoneNumber = facilityPhoneNumber
}
init() {}
}
Content View
struct ContentView: View
{
#ObservedObject var patient = PatientData()
...
}
Note that:
PatientData()
is an equivalent of:
PatientData.init()
Which means that if you want to create your PatientData this way:
#ObservedObject var patient = PatientData()
you need to provide a matching init method (it can be empty as all your #Published properties have already a default value):
init() { }
EDIT
Looking at your full code, it seems like one of your properties has no initial value:
#Published var patientAddress: PatientAddress
An empty init will work only when all your properties are already initialised, which means you need to assign some value to your patientAddress:
#Published var patientAddress = PatientAddress()
However, for this to work, you'd need to add an empty init in PatientAddress as well:
struct PatientAddress {
...
init() {}
}
NOTE
All your code could be much simpler without all these initialisers. If you only use empty init methods you don't have to declare them (they are auto-generated for structs if there are no other initialisers):
class PatientData: Identifiable, ObservableObject {
let id = UUID()
#Published var patientName: String = "Name"
#Published var patientAge: String = "Age"
#Published var patientDOB: String = "DOB"
#Published var patientPhone: String = "Phone"
#Published var patientAddress: PatientAddress = PatientAddress()
#Published var facilityName: String = "Facility"
#Published var facilityRoom: String = "Room Number"
#Published var facilityFloor: String = "Floor"
#Published var facilityPhoneNumber: String = "Phone Number"
}
extension PatientData {
struct PatientAddress {
var patientStreetAddress: String = "Street"
var patientCity: String = "City"
var patientState: String = "State"
var patientZip: String = "Zip"
}
}
Also, Swift can infer types automatically. You don't usually have to declare types explicitly:
#Published var patientPhone = "Phone"
#Published var patientAddress = PatientAddress()

Writing models in separate files or in one file?

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?
}

How to construct struct based on json

I have list Json result based on that I created struct but while parsing getting an error typeMismatch. I am not able to find what's wrong going while create structs in code
I have created struct based on json which is not working for me
["status": "1",
"error": false,
"data": [
{
"order_id": "11",
"order_unique_id": "ORDR-1001",
"store_name": "24X7",
"otp_store": "781103",
"product": [
"Product One",
"Product Two"
],
"qty": [
"1",
"3"
],
"user_details": {
"name": "test",
"number": "98145314586",
"landmark": "test",
"area": "Bow East",
"pincode": "E3 9EG",
"place": "Home"
},
"status": "2",
"date": "2018-12-13",
"time": "14:37:57"
}]
struct RunnerStatus: Decodable {
var status: String
var error: Bool
var data: [Runner]
}
struct Runner: Decodable {
var order_id: String
var order_unique_id: String
var store_name: String
var otp_store: String
var product: [Product]
var qty: [Quantity]
var user_details: [UserDetails]
var status: String
var date: String
var time: String
}
struct Product: Decodable {
var ProductName: String
}
struct Quantity: Decodable {
var qty: String
}
struct UserDetails: Decodable {
var name: String
var number: String
var landmark: String
var area: String
var pincode: String
var place: String
}
all struct should bind with there associated value/Data
I think you structure should be as follows:
// 1
struct RootClass : Codable {
let data : [RunnerData]?
let error : Bool?
let status : String?
}
// 2
struct RunnerData : Codable {
let date : String?
let orderId : String?
let orderUniqueId : String?
let otpStore : String?
let product : [String]?
let qty : [String]?
let status : String?
let storeName : String?
let time : String?
let userDetails : UserDetail?
enum CodingKeys: String, CodingKey {
case date
case orderId = "order_id"
case orderUniqueId = "order_unique_id"
case otpStore = "otp_store"
case product
case qty
case status
case storeName = "store_name"
case time
case userDetails = "user_details"
}
}
// 3
struct UserDetail : Codable {
let area : String?
let landmark : String?
let name : String?
let number : String?
let pincode : String?
let place : String?
}
I hope this will help you. Let me know still you have any query.
If you create JSON structure manually than before you should have proper knowledge of making structure. Otherwise it's effect on JSONDecoding. There are lots of website available to make your json codable classes online, one of them is: http://www.jsoncafe.com/
Use this website to create your swift codable classes.

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