Hi I'm working on an app that is connected to a Web API and contains a local Database (Realm).
I have a User class which is a Realm Object
subclass and keeps the user information such as username
, password
, accessToken
and etc. It has also a static variable and computed property called instance: User?
and current: User?
Please find details below
class User: Object {
/// Properties (Database Columns)
@objc dynamic var username: String = ""
@objc dynamic var password: String = ""
@objc dynamic var accessToken: String = ""
/// Current Logged In User
static var current: User? {
if instance == nil {
let realm = try! Realm()
instance = realm.objects(self).first
}
return instance
}
private static var instance: User?
}
As you can see current
property returns the first User
instance from realm database which is the logged in user information if there is any, otherwise it returns nil
which means the user hasn't logged in the app.
I have also another class called Configs its name can describe what it does, there's a static boolean variable in it called isLogin
. Here is the part of my code which I defined this
static var isLogin: Bool = User.current != nil
as you can see this property refers to User.current
property described above and returns the result.
I call Configs.isLogin
several times in the app whenever I want to check if the user is logged in or not so, I can tell the app to behave properly.
But when I call this property, it seems swift dive into the property and calls User.current
JUST ONCE in an app session, the next times it just keeps the first result and assign it directly to Configs.isLogin
and it will no more check the User.current
property and won't runs query to see if there is any result or not, thus when for example the user fills and submits the registration form and gets a token from API and I save the information in Realm, if I call Configs.isLogin
it still returns false since the first time in this session that it checked the User.current
it was nil, but if I call User.current
directly (after the registration) it's not nil anymore and I can access to the logged in user, also if I relaunch the app and start a new app session Configs.isLogin
returns true which is correct and shows swift dives into the User.current
and checked it and returned the proper result (as I mentioned at first of the article, only the first time it will dive into the class and checks the result).
I debugged my app several times and several parts until I found this problem, How can I make swift to always dive into User.current
from Config.isLogin
property when I call this config? is there something wrong with my code? and if yes what's the proper way? Thank You
Currently isLogin
is a variable initialized at first access. You can move the initialization part into a computed property so it always checks on User.current:
static var isLogin: Bool { return User.current != nil }
Here you can read up on Computed Properties.