multithreading - Realm thread safe object with singleton -
so have singleton class manages current user logged application.
it looks this
class sessionmanager { static let shared = sessionmanager() var loggedinuser: user? }
the problem if want user object background thread, can't following exception:
'rlmexception', reason: 'realm accessed incorrect thread.'
after googling found thread safe reference's. changed class instead:
class sessionmanager { static let shared = sessionmanager() private var threadsafeuser: threadsafereference<user>? var loggedinuser: user? { { if nil === self.threadsafeuser { return nil } else { let realm = try! realm() return realm.resolve(self.threadsafeuser!)! } } set { if nil === newvalue { self.threadsafeuser = nil } else { self.threadsafeuser = threadsafereference(to: newvalue!) } } } }
my thinking internally hold reference thread safe, whenever fetch user object, resolve object. doesn't work because can resolve threadsafereference once:
'rlmexception', reason: 'can resolve thread safe reference once.'
i tried resolving once inside getter, first issue if reference resolved object different thread resolved.
currently can think of 2 options:
i keep reference each thread, , pass correct threaded user object (not 100% sure how that, theory @ moment)
i have set/get dispatch main thread object syncronously. grab main thread. wouldn't able write changes object, maybe read? not sure work honest.
i'm 100% sure problem that's been solved before, given how generic problem is.
so fellow realm users, how should solve one?
edit: issue resolved david below. fellow s.o users, here's did in end.
class sessionmanager { static let shared = sessionmanager() private var loggedinuserid: int? var loggedinuser: user? { { if nil == loggedinuserid { return nil } let realm = try! realm() return realm.object(oftype: user.self, forprimarykey: loggedinuserid) } set { if nil == newvalue { loggedinuserid = nil } else { loggedinuserid = newvalue!.id } } } }
it may need cleaning (the nil checks written better sure), that's basic approach took.
this allows me treat loggedinuser
property normal object, , whenever read it, grabs new reference realm (thread safe), , if want set new user (i.e after login), can loggedinuser = newuser
, setter deals how persist it.
your first option incorrect, since threadsafereference
single use reference explained below. second option might work, easier create new reference realm
instance time trying access it, see explanation below.
you shouldn't store reference singleton realm
instance, since cannot ensure access same thread. realm
documentation states,
instances of
realm
,results
, orlist
, or managed instances ofobject
thread-confined, meaning can used on thread on created, otherwise exception thrown.
meaning should never try use let realm = try! realm()
create singleton realm
instance , try access everywhere app.
you try using threadsafereference
create references realm
objects can safely shared between threads, passing instances across threads part of documentation states, these references can used once, can't reused singleton.
however, there no need such thing, since every time call let realm = try! realm()
, framework automatically creates reference used realm
on thread on enabling safely interact long don't leave thread.
the best way use realm
in thread-safe way create new reference realm
using let realm = try! realm()
every time move between threads , need access realm
. way can ensure never incorrect thread exception.
Comments
Post a Comment