Class has No Initializers Error Realm Class Swift - swift

I'm getting a Class has no initializers Error. Is this not how I would set up the class. This is for a Realm OBject Database, the Properties I want to store. I'm new to swift and realm, but I figured this is how it would be done. If I take out the init() function and just assign everything values it works, however properties like justTook and all that I don't want start with a value, I need to set it later in the program.
Here is my code:
class MedInfo: Object {
// Info To Be Stored
#objc dynamic var keyID = UUID().uuidString
#objc dynamic var medName: String
#objc dynamic var medDose: String
#objc dynamic var currentDate: Date
#objc dynamic var timeTook: Date
#objc dynamic var lastTook: Date
#objc dynamic var durationOfTime: Date
#objc dynamic var doctorName: String
#objc dynamic var rxDate: Date
#objc dynamic var medInfo: String
#objc dynamic var pictureOfMed: UIImage
override static func primaryKey() -> String? {
return "keyID"
}
convenience init(medName: String, medDose: String, currentDate: Date, timeTook: Date, lastTook: Date, durationOfTime: Date, doctorName: String,rxDate: Date, medInfo: String, pictureOfMed: UIImage) {
self.medName = medName
self.medDose = medDose
self.currentDate = currentDate
self.timeTook = timeTook
self.lastTook = lastTook
self.durationOfTime = durationOfTime
self.doctorName = doctorName
self.rxDate = rxDate
self.medInfo = medInfo
self.pictureOfMed = pictureOfMed
}

You need to set default values for all parameters, as vaguely described in the docs. From here:
When using Realm from Swift, the Swift.reflect(_:) function is used to
determine information about your models, which requires that calling
init() succeed. This means that all non-optional properties must have
a default value.
All the examples show this, so follow them. Your class should thus be declared:
class MedInfo: Object {
// Info To Be Stored
#objc dynamic var keyID = UUID().uuidString
#objc dynamic var medName: String = ""
#objc dynamic var medDose: String = ""
#objc dynamic var currentDate: Date = Date()
#objc dynamic var timeTook: Date = Date()
#objc dynamic var lastTook: Date = Date()
#objc dynamic var durationOfTime: Date = Date()
#objc dynamic var doctorName: String = ""
#objc dynamic var rxDate: Date = Date()
#objc dynamic var medInfo: String = ""
// UIImage not supported, you'll need to store a URL/filename or something else
#objc dynamic var pictureOfMed: UIImage

You must call the init to create the instance.
convenience init(medName: String, medDose: String, currentDate: Date, timeTook: Date, lastTook: Date, durationOfTime: Date, doctorName: String,rxDate: Date, medInfo: String, pictureOfMed: UIImage) {
self.init()
self.medName = medName
self.medDose = medDose
self.currentDate = currentDate
self.timeTook = timeTook
self.lastTook = lastTook
self.durationOfTime = durationOfTime
self.doctorName = doctorName
self.rxDate = rxDate
self.medInfo = medInfo
self.pictureOfMed = pictureOfMed
}

As #ces already correctly quoted from the Realm documentation: "This means that all non-optional properties must have a default value."
This is why I think the best way for you to create your Realm object is to declare your variables as optionals.
This way you will not have to call init. This is the way I create my own Realm objects and the way I've seen most people create them.
So your object would look like this:
class MedInfo: Object {
// Info To Be Stored
#objc dynamic var keyID = UUID().uuidString
#objc dynamic var medName: String?
#objc dynamic var medDose: String?
#objc dynamic var currentDate: Date?
#objc dynamic var timeTook: Date?
#objc dynamic var lastTook: Date?
#objc dynamic var durationOfTime: Date?
#objc dynamic var doctorName: String?
#objc dynamic var rxDate: Date?
#objc dynamic var medInfo: String?
#objc dynamic var pictureOfMed: UIImage?
override static func primaryKey() -> String? {
return "keyID"
}

Related

Swift Realm filter all object with a null value

I have two objects as follow:
class NextAction: Object {
#objc dynamic var title: String = ""
#objc dynamic var notes: String? = ""
#objc dynamic var deadline: Date?
#objc dynamic var deadlineID: String = ""
#objc dynamic var reminder: Date?
#objc dynamic var reminderID: String = ""
#objc dynamic var finished: Bool = false
#objc dynamic var favorite: Bool = false
#objc dynamic var priority: Int = 0
var duration = RealmOptional<Int>()
#objc dynamic var tag: String?
let tags = List<Tag>()
}
class Tag: Object {
#objc dynamic var title: String = ""
let owners = LinkingObjects(fromType: NextAction.self, property: "tags")
}
Not all NextAction objects has a tag, but I want to filter out and show all who are missing one, I have tried
var test = realm.objects(NextAction.self).filter("ANY tags == nil")
But I get this error
'Invalid value', reason: 'Expected object of type Tag for property 'tags' on object of type 'NextAction', but received: (null)'
Your tags cannot be nil.
If you want to find objects whose tags is empty, you can do that this way.
var test = realm.objects(NextAction.self).filter("ANY tags.#count == 0")

Using lazy variable vs. Initializing - Swift

I'm making an app with thousands of inputs.
I have a model class like this
class Waterz {
var id: String = ""
var entitle: String? = nil
var artitle: String? = nil
var date: [String]? = nil
var frequency: [daysOfWeek]? = nil
var subMenus: Array<Waterz>? = nil
var location: String? = nil
var audio: [reciterNames]? = nil
var menuIcon: String? = nil
init() {
}
convenience init(id: String, entitle: String, artitle: String, date: [String]?, frequency: [daysOfWeek]?, location: String?, audio: [reciterNames]?) {
self.init()
self.id = id
self.entitle = entitle
self.artitle = artitle
self.date = date
self.frequency = frequency
self.location = location
self.audio = audio
}
}
And then I have my filling-up class. My filling up class has thousands of variables, so I wanted to see if I should use lazy vars or declare each variable, then initialize it in the init() like this
class Database {
var duaKumayl: Waterz
init() {
duaKumayl = .init(...)
}
}
Or should I use lazy vars? Using my current method of declaring then initializing will take forever because I have thousands of variables.
Try to do pagination within app , if you have thousands of variables . This will reduce the show up time for the data you are presenting in UI.
In such cases as i mentioned above , you should use initialization . But if your evaluation of data takes too long use lazy variables.

saving array into realm database swift

I have an application which uses realm database to persist data and everything works fine but the issue I have now is I want to save photo: Data array to the database and I tried using the standard swift array format but got an error at build time. below is my code
class TodoListModel: Object {
#objc dynamic var id = UUID().uuidString
#objc dynamic var photo: Data? = nil
#objc dynamic var createdDate: Date?
override static func primaryKey() -> String? {
return "id"
}
let parentCategory = LinkingObjects(fromType: CategoryModel.self, property: "items")
}
how do I now make the photo into an array
this is the way I create my List
func createTodoList(createdDate: Date, photo: Data) -> Void {
let todoList = TodoListModel()
todoList.createdDate = createdDate
todoList.photo = photo
TodoListFunctions.instance.addData(object: todoList)
}
update model
func updateTodoList(update: TodoListModel, createdDate: Date, photo: Array<Data>) -> Void {
update.createdDate = createdDate
update.photo.append(objectsIn: photo)
}
To be able to store several objects of type Data in a single property of an Object subclass, you need to use List.
class TodoListModel: Object {
#objc dynamic var id = UUID().uuidString
#objc dynamic var createdDate: Date?
let photos = List<Data>()
let parentCategory = LinkingObjects(fromType: CategoryModel.self, property: "items")
override static func primaryKey() -> String? {
return "id"
}
}
Then you can create a TodoListModel instance like this:
func createTodoList(createdDate: Date, photos: Array<Data>? = nil) -> Void {
let todoList = TodoListModel()
todoList.createdDate = createdDate
if let photos = photos {
todoList.photos.append(objectsIn: photos)
}
TodoListFunctions.instance.addData(object: todoList)
}

Get notified when value in List is updated using realm

I am trying to write an application in OS X using a Realm database. I want to trigger notification when where there is change in value of List which is inside another object
Below is the Class
final class Profile: Object {
#objc dynamic var gradient1 = ""
#objc dynamic var gradient2 = ""
#objc dynamic var fontColor = ""
#objc dynamic var selectedFont = ""
#objc dynamic var selectedTitleFont = ""
#objc dynamic var fontFamily = ""
#objc dynamic var name = ""
#objc dynamic var shortbio = ""
#objc dynamic var avatarSource = ""
#objc dynamic var userid = ""
#objc dynamic var email = ""
var features = List<Features>()
var socialLinkButtons = List<SocialLinkButtons>()
#objc dynamic var appSelectedMetaData : AppMetaData? = nil
override static func primaryKey() -> String?{
return "userid"
}
}
final class Features: Object {
#objc dynamic var uuid = ""
#objc dynamic var id = ""
#objc dynamic var label = ""
#objc dynamic var screen = ""
#objc dynamic var active = false
override static func primaryKey() -> String?{
return "id"
}
convenience init(id: String, uuid: String, label: String, screen: String, active: Bool) {
self.init()
self.id = id
self.uuid = uuid
self.label = label
self.screen = screen
self.active = active
}
}
I want to trigger notifications whenever value inside feature is updated.
You can use Realm Collection Notifications to achieve your goals. You just need to make sure that you store the returned NotificationToken in a variable that doesn't get deallocated until you don't actually need to receive the notifications anymore and that you call .invalidate() on the token when you no longer want to receive notifications.
func observeFeatureChanges(in profile:Profile) -> NotificationToken {
let notificationToken = profile.features.observe { changes in
switch changes {
case .update(_, deletions: let deletionIndices, insertions: let insertionIndices, modifications: let modIndices):
print("Objects deleted from indices: \(deletionIndices)")
print("Objects inserted to indices: \(insertionIndices)")
print("Objects modified at indices: \(modIndices)")
case .error(let error):
print(error)
case .initial(let type):
print(type)
}
}
return notificationToken
}

Realm database callbacks

I'm looking at implementing callbacks for some objects in my code. So far the object I have is the following:
class Contact: Object {
#objc dynamic var uid: String? = nil
#objc dynamic var fullName: String? = nil
#objc dynamic var givenName: String? = nil
#objc dynamic var familyName: String? = nil
}
Ideally, I would like to fill fullName once givenName and familyName have a value.
I noticed that Realm has events, but they seem to be pretty broad and I'm not sure that implementing such mechanism will not create more issues than good in my app as I only need to trigger it when the Contact object is being manipulated.
Any suggestion or best practice to share?
What you are looking for are computed properties. However, Realm currently doesn't support storing computed properties, but you don't really need to persist fullName in Realm, since as long as givenName and familyName are persisted, you can always compute fullName.
class Contact: Object {
#objc dynamic var uid: String? = nil
#objc dynamic var givenName: String? = nil
#objc dynamic var familyName: String? = nil
var fullName: String? {
if let givenName = givenName, let familyName = familyName {
return "\(givenName) \(familyName)"
}
return nil
}
}