Realm setup takes longer than query


Hi, I want to use Realm Cloud for our next ios conference app. Writing to realm seems to be ok but I’m stuck in showing all speakers.

Here’s the first screen. I am calling a viewModel. But the viewModel’s getAllSpeakers() returns nil because the init() is slower. This is because on the debug console, I’m getting Speaker: No realm first, and then Realm set

Thanks a lot for your help!

class SpeakersViewController: UITableViewController {
    private let viewModel = SpeakerViewModel()
    private let speakerCellId: String = "speakerCell"
    private var speakers: Results<Speaker>?
    private var speakersToken: NotificationToken?
    override func viewDidLoad() {
//        viewModel.initSampleSpeakers()
        speakers = viewModel.getAllSpeakers()
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: speakerCellId)
    override func viewWillAppear(_ animated: Bool) {
        speakersToken = speakers?.observe({ [weak tableView] (changes) in
            guard let tableView = tableView else { return }
            switch changes {
            case .initial:
            case .update(_, let deletions, let insertion, let updates):
                tableView.applyChanges(deletions: deletions, insertions: insertion, updates: updates)
            case .error(let error):
                #if DEBUG
                print("SpeakersViewController error: \(error.localizedDescription)")
    override func viewWillDisappear(_ animated: Bool) {
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return speakers?.count ?? 0
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let speaker = speakers?[indexPath.row] else {
            return UITableViewCell()
        let cell = tableView.dequeueReusableCell(withIdentifier: speakerCellId, for: indexPath)
        cell.imageView?.image = UIImage(imageLiteralResourceName: speaker.imageFilename)
        cell.textLabel?.text =
        return cell

The viewModel:

class SpeakerViewModel {
    private var realm: Realm? {
        didSet {
            print("Realm set")
    init() { { [weak self] realm, error in
            guard error == nil, let realm = realm else {
                fatalError("Database error: \(error?.localizedDescription ?? "unknown error")")
            self?.realm = realm
    internal func getAllSpeakers() -> Results<Speaker>? {
        guard let realm = self.realm else {
            print("Speaker: No realm")
            return nil

        let speakers = realm.objects(Speaker.self)
        let sortedByName = speakers.sorted(byKeyPath:
        return sortedByName

// I've also tried this
    internal func getAllSpeakers() -> Results<Speaker>? {
        let realm = try! Realm()
        guard realm.isEmpty else {
        print("Speaker: No realm")
        return nil
        return Speaker.all(in: realm)
    internal func initSampleSpeakers() {
        guard let realm = self.realm else {
            print("No realm")
        try! realm.write {
        let subh = Speaker(name: "Subhransu", imageFilename: "subh") = "SPGroup"
        subh.twitter = "@subhransu"
        subh.shortBio = "Some cool guy am I?"
        subh.add(to: realm)
        let tim = Speaker(name: "Tim Oliver", imageFilename: "tim") = "Mercari"
        tim.twitter = "@timoliver"
        tim.shortBio = "I'm that N5 guy"
        tim.add(to: realm)
        let ykm = Speaker(name: "Yeo Kheng Meng", imageFilename: "ykm") = "SPGroup"
        ykm.twitter = "@yeokm1"
        ykm.shortBio = "I am a software engineer and a pilot!"
        ykm.add(to: realm)

And I have a RealmProvider struct

struct RealmProvider {
    let configuration: Realm.Configuration
    private init(config: Realm.Configuration) {
        configuration = config
    func realm(callback: @escaping (Realm?, Error?) -> Void) {
        Realm.asyncOpen(configuration: configuration, callback: callback)
    // MARK: - News realm
    private static let newsConfig: Realm.Configuration = {
        var config = SyncUser.current?.configuration(realmURL: Constants.NEWS_REALM_URL,
                                                             fullSynchronization: true,
                                                             enableSSLValidation: true,
                                                             urlPrefix: nil)       
        return config!
    public static var news: RealmProvider = {
        return RealmProvider(config: newsConfig)


@vinamelody You should use asyncOpen and block the thread until the download is complete - then within that callback you can make calls to render the view.


Ah, okay looks like this is caused by how I tried doing asyncOpen. The solution is to not trying to download the realm in the viewModel but to wait until the asyncOpen finishes. See this for more info