Using lazy variable vs. Initializing - Swift - 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.

Related

Class has No Initializers Error Realm Class 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"
}

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
}

Saving custom object as core data property

I am trying to save a custom class as a property of a core data object.
The Core Data object:
#objc(Safer)
class Safer: NSObject
{
#NSManaged var perakimFiles: [prayer]? //This line gives me an error saying that it cannot save a type that is not Obj. C
#NSManaged var titleEnglish: String?
#NSManaged var titleHebrew: String?
#NSManaged var parshaPerakim: [Int]?
#NSManaged var saferCode: String?
var titles: [[String]]
{
get
{
var ret = [[String]]()
var i = 0
for file in perakimFiles!
{
ret.append([file.title, "\(i+1)"])
i++
}
return ret
}
}
init(_ _saferCode: SefarimCodes)
{
super.init()
self.saferCode = _saferCode.rawValue
}
init(_perakimFiles: [prayer], _titleEnglish: String, _titleHebrew: String)
{
super.init()
self.perakimFiles = _perakimFiles
self.titleEnglish = _titleEnglish
self.titleHebrew = _titleHebrew
}
init(_perakimFiles: [prayer], _titleEnglish: String, _titleHebrew: String, _parshaPerakim: [Int])
{
super.init()
self.perakimFiles = _perakimFiles
self.titleEnglish = _titleEnglish
self.titleHebrew = _titleHebrew
self.parshaPerakim = _parshaPerakim
self.saferCode = setTorahSaferCode()!.rawValue
let config = self.configFromCode()
self.perakimFiles = config.perakimFiles
}
}
Here is the prayer class that I am trying to save in the core data object:
class prayer
{
var url: NSURL
var title: String
var detail: String?
init(initURL: NSURL, initTitle: String)
{
print("1")
print("2")
self.title = initTitle
print("3")
self.url = initURL
print("4")
}
init(initURL: NSURL, initTitle: String, initDetail: String)
{
self.url = initURL
self.title = initTitle
self.detail = initTitle
}
}
So what can I do to the prayer class to make it savable by the core data object? I need to also be able to use instances of the prayer class in other places of the code.
As mentioned, have your prayer class subclass NSObject and conform to NSCoding which requires two methods : -initWithCoder: and encodeWithCoder:
Once those are implemented, you can use NSKeyedArchiver/NSKeyedUnarchiver class methods to transform your objects into NSData objects and back, thus allowing you to store your objects as CoreData properties under the supported NSData type.
Let class prayer conforms to NSObject and NSCoding and see whether that addresses the error.

How do I create global object in swift?

I think my previous question was too vague. Let me try again.
I'm trying to hold user information by creating a singleton.
After a bit of research, this is what I understood.
Class UserInfo {
var userFirstName: String?
var userLastName: String?
/*I'll add all other variables here*/
}
let sharedInfo = UserInfo()
Am I on right path?
EDIT: For Swift 1.2 and higher (Thanks Will M)
class UserInfo {
static let sharedUserInfo = UserInfo()
var firstName: String?
var lastName: String?
}
For Swift earlier than 1.2
Something along the lines of:
class UserInfo
{
// Singleton Setup
private static var info: UserInfo?
class func sharedUserInfo() -> UserInfo
{
if self.info == nil
{
self.info = UserInfo()
}
return self.info!
}
// Class properties
var firstName: String?
var lastName: String?
}
let user = UserInfo.sharedUserInfo()
user.firstName = "Fred"
user.lastName = "Smith"
I would also recommend making sure that a singleton is really what you want, because depending on how you use it, you could run into some race conditions with threading.

How to use Realm Swift Init

I am trying to use the init for Realm in Swift. I have tried the following
override init(value: AnyObject) {
super.init()
println("this is not called")
}
required init() {
super.init()
println("this is called")
}
I want to be able to pass an object into the initializer, however, I can't get the first function to be called.
My solution in Swift 3
Custom initializer:
class Branches: Object {
dynamic var key: String = NSUUID().uuidString
dynamic var formattedAddress: String = ""
dynamic var latitude: Double = 0.0
dynamic var longitude: Double = 0.0
convenience init(formattedAddress: String, latitude: Double, longitude: Double) {
self.init()
self.formattedAddress = formattedAddress
self.latitude = latitude
self.longitude = longitude
}
override static func primaryKey() -> String? {
return "key"
}
}
Overriding Object.init() and Object.init(_:) are not yet supported in Realm Swift, but you can follow https://github.com/realm/realm-cocoa/issues/1849 for updates!
Here's my answer for iOS 13, Swift 5.
Being totally honest with you, I had no idea what I was doing, but I managed it to work by doing so:
class Account: Object {
#objc dynamic var name: String = ""
#objc dynamic var balance: Double = 0.0
#objc dynamic var savings: Double = 0.0
#objc dynamic var available: Double = 0.0
init(name: String, balance: Double){
self.name = name
self.balance = balance
self.savings = 0.0
self.available = balance
}
required init() {
//fatalError("init() has not been implemented")
}
}
Keep in mind that I'm totally new with Swift (about 3 months top), and I don't know the consequences of doing that. But my project is working just fine. Everything is being saved and retrieved perfectly.