Царство - Доступ к царству из неправильного потока Swift

Я новичок в Realm и получаю сообщение об ошибке «Доступ к Realm из неправильного потока». Я читал, что нужно получить доступ к данным в той же области, из которой они были получены. Однако я получаю эту ошибку после успешного доступа к объекту. Вот код:

func retrieveApplicationData(completionBlock: (Results<Application>, NSError?) -> Void) {
        let realm = try! Realm()
        let applications = realm.objects(Application)

        if applications.count > 0 {
            completionBlock(applications, nil)
        }   
}

Этот метод вызывает метод, который создает массив приложений, используя: let array = Array(results)

Затем я передаю это методу, который устанавливает массив:

func setApplicationItems(items: [Application]) {
    applications = items

    print(applications)
}

В приведенном выше методе я распечатываю массив, и он отлично работает. Однако позже в цикле вызывается метод tableViewDatasource cellForRowAtIndexPath. Здесь я пытаюсь использовать массив приложений, но приложение вылетает с ошибкой «неправильный поток». Вот метод:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    print("\(applications)")

    let cell = ApplicationTableViewCell(style: .Subtitle, reuseIdentifier: nil)
    let application = applications[indexPath.row]
    cell.configureCell(application)

    return cell
}

Как видите, я добавил оператор печати в вышеприведенный метод. Когда я пытаюсь распечатать массив приложений здесь, я получаю сбой.

Почему я могу распечатать его в методе, который его устанавливает, а здесь он сбой? Это потому, что cellForRowAtIndexPath вызывается в основном потоке? И если да, то как я могу обновить свой tableView в этом случае? Ваше здоровье.

========

Изменить:

Когда я делаю следующее в cellForRowAtIndexPath, я получаю пустой результат:

let realm = try! Realm()
let applicationsB = realm.objects(Application)

Редактировать 2:

Я обрабатываю сохранение в закрытии. Я попытался передать его обратно в основной поток, используя dispatch_async, когда данные вернулись, но он все еще давал сбой. Однако я переместил это dispatch_async непосредственно перед вызовом self.tableView.reloadData(). Теперь он не падает, что хорошо, но данные не всегда доступны. Если я замедляю его с помощью точек останова, я возвращаю данные. Однако данных нет, если я просто позволю им работать. Есть ли способ узнать, когда данные, сохраненные в фоновом потоке, доступны в основном потоке?

Вот код, который я использую:

 dispatch_async(dispatch_get_main_queue()) {               
            let realm = try! Realm()
            realm.refresh()
            let applicationsB = realm.objects(Application)
            let array = Array(applicationsB)
            self.tableViewDataSource.setApplicationItems(array as! [Application])
            self.tableView.reloadData()
        }

Данные не всегда есть.

Редактировать 3:

Теперь я завернул метод сохранения в dispath_async(dispath_get_main_queue()), и он отлично работает:

    dispatch_async(dispatch_get_main_queue()) {

            let realm = try! Realm()
            try! realm.write() {

            let applications = data.map({ (object) -> Application in
                return Application(applicationID: object.applicationID, contact: "", state: "", jobBoard: object.jobBoard, salary: object.salary, title: object.title, location: "")
            })

            for application in applications {
                print(application)
                realm.add(application)
            }

            //try! realm.commitWrite()

            completionBlock(true, nil)

        }

person pls    schedule 27.06.2016    source источник
comment
Внимательно прочитайте, что https://realm.io/docs/swift/latest/#threading говорит о нескольких потоках.   -  person Mike Robinson    schedule 27.06.2016
comment
Привет, Майк, после прочтения документации я попробовал код в моем предыдущем редактировании, где я создаю новую область с помощью: let realm = try! Realm(), а затем использовать его, чтобы попытаться получить мои объекты. Но результат пустой. Я перечитал присланный вами раздел и до сих пор не уверен, как мне получить объекты. Я до сих пор понимаю это как: пусть царство = попробуй! Область(). Я что-то упускаю?   -  person pls    schedule 27.06.2016
comment
Используя точку останова исключения, вы можете увидеть, какая строка вашего кода вызывает исключение, которое Realm выдает в ответ на нарушение его ограничений потоковой передачи. Это должно точно определить объект, доступ к которому осуществляется из неправильного потока. Затем вы можете посмотреть, в каком потоке создан этот объект и в каком потоке вы пытаетесь получить к нему доступ.   -  person bdash    schedule 27.06.2016
comment
Ваш код до сих пор не показывал каких-либо отправок по потокам или мест, где вы добавляете свои объекты в Realm. Как вы видели ранее, ошибка «неправильный поток», я предполагаю, что это происходит, но было бы полезно узнать, как и где вам помочь. Не могли бы вы поделиться дополнительной информацией?   -  person marius    schedule 27.06.2016
comment
Спасибо bdash и marius за ваши комментарии, я добавил обновление к моему вопросу в разделе «Редактировать 2».   -  person pls    schedule 28.06.2016


Ответы (1)


Изменить:

Пожалуйста, прочитайте комментарий от bdash ниже. Хотя это работает, на самом деле это происходит случайно. Оставьте ответ здесь, чтобы другие не пробовали то же самое.

Следующий код работал, но некорректен!!!:

Так что мне удалось заставить его работать. Сначала я остановил приложение, и в поле зрения появится добавленный код, который извлекает данные. Это сработало нормально. Так что я знал, что данные были в базе данных. Однако я хотел сохранить данные, а затем сразу же использовать их.

Чтобы добиться этого, мне нужно было добавить следующий try! realm.commitWrite() внутри моего блока realm.write() { }. Полный метод ниже:

try realm.write() {

       let applications = data.map({ (object) -> Application in
                return Application(applicationID: object.applicationID, contact: "", state: "", jobBoard: object.jobBoard, salary: object.salary, title: object.title, location: "")
        })

        for application in applications {
            print(application)
            realm.add(application)
        }

        try! realm.commitWrite() // *NOTE* Here is the code I added.

        completionBlock(true, nil)

    }

Как только я добавил commitWrite(), я смог выполнить выборку позже в основном потоке следующим образом:

 dispatch_async(dispatch_get_main_queue()) {

            let realm = try! Realm()
            realm.refresh()
            let applicationsB = realm.objects(Application)
            let array = Array(applicationsB)

            self.tableViewDataSource.setApplicationItems(array as! [Application])


            self.tableView.reloadData()
        }
person pls    schedule 27.06.2016
comment
Вызов commitWrite() в блоке, переданном write(), неверен. Если это работает, это потому, что у вас есть проблемы в другом месте, симптомы которых это скрывает. - person bdash; 27.06.2016