ошибка: EXC_BAD_ACCESS (код = 1, адрес = 0x6f697483). Процесс был возвращен в состояние до оценки выражения - PullRequest
0 голосов
/ 08 мая 2018

После получения ответа об успешном выполнении API я сохраняю, обновляю и извлекаю данные из основной базы данных.

import Foundation
import SwiftyJSON

protocol WKQuizInformationVMDelegate {
  func success(details: QuizDetails?, isSuccess: Bool, quizID: String)
  func detailsFailure(error: String, quizID: String)
}

class WKQuizInformation: NSObject {

 var quizDetails: QuizDetails?
 var delegate: WKQuizInformationVMDelegate?

 //Retrieve Particular Quiz Information from server
 func retrieveParticularQuizInfo(quizID : String, quizVersion : String, summary: String) {

     WKNetworkManager.sharedInstance.getParticularQuizDetail(clientUserID: WKQuizConstant.kClientUserIdValue, quizID: quizID, quizVersion: quizVersion, summary: summary, onSuccess: { (json) in

        self.saveUpdateQuizInfoDB(json: json)
        self.perform(#selector(self.fetchQuiz(quizID:)), with: quizID, afterDelay: 0.2) 

    }) { (error) in

        print(quizID)
        print(error)
        self.delegate?.detailsFailure(error: error, quizID: quizID)
    }
}

//MARK:- Save and Update Quiz Information in Data base
fileprivate func saveUpdateQuizInfoDB(json: JSON) {

    let quizInfo = FetchDataBaseService.sharedInstance.fetchQuizInformation(quizID: json[WKQuizConstant.Id].rawString() ?? "")

    var quizInfoDB: DBQuizInformation!

    if quizInfo.count > 0 {
        quizInfoDB = quizInfo[0]
    }

    else {
        quizInfoDB = DBQuizInformation.init(context : FetchDataBaseService.sharedInstance.mngdCntxt)
    }

    quizInfoDB.id = json[WKQuizConstant.Id].rawString() ?? ""
    quizInfoDB.quizVersion = json[WKQuizConstant.kQuizVersion].rawString() ?? ""
    quizInfoDB.newQuestions = json[WKQuizConstant.kNewQuestions].rawString() ?? ""
    quizInfoDB.navigationType = json[WKQuizConstant.kNavigationType].rawString() ?? ""
    quizInfoDB.testMode = json[WKQuizConstant.kTestMode].rawString() ?? ""
    quizInfoDB.questionTime = json[WKQuizConstant.kQuestionTime].rawString() ?? ""
    quizInfoDB.metadataAssoc = json[WKQuizConstant.kMetadataAssoc].rawString() ?? ""
    quizInfoDB.randomizeQuestion = json[WKQuizConstant.kRandomizeQuestion].rawString() ?? ""
    quizInfoDB.metadataTitle = json[WKQuizConstant.kMetadataTitle].rawString() ?? ""
    quizInfoDB.gotWrong = json[WKQuizConstant.kGotWrong].rawString() ?? ""
    quizInfoDB.quizTime = json[WKQuizConstant.kQuizTime].rawString() ?? ""
    quizInfoDB.title = json[WKQuizConstant.kTitle].rawString() ?? ""
    quizInfoDB.numberOfQuestions = json[WKQuizConstant.kNumberOfQuestions].rawString() ?? ""
    quizInfoDB.quizType = json[WKQuizConstant.kQuizType].rawString() ?? ""
    quizInfoDB.randomizeAnswer = json[WKQuizConstant.kRandomizeQuestion].rawString() ?? ""
    quizInfoDB.numberOfAvailableMetadataQuestions = json[WKQuizConstant.kNumberOfAvailableMetadataQuestions].rawString() ?? ""
    quizInfoDB.totalTestQuestions = json[WKQuizConstant.kTestProgress][WKQuizConstant.kTotalTestQuestions].rawString() ?? ""
    quizInfoDB.totalCorrectAnswers = json[WKQuizConstant.kTestProgress][WKQuizConstant.kTotalCorrectAnswers].rawString() ?? ""
    quizInfoDB.totalWrongAnswers = json[WKQuizConstant.kTestProgress][WKQuizConstant.kTotalWrongAnswers].rawString() ?? ""
    quizInfoDB.totalUnAttempted = json[WKQuizConstant.kTestProgress]["totalUnattempted"].rawString() ?? ""
    quizInfoDB.numberOfMetadataQuestions = Int64(json[WKQuizConstant.kNumberOfMetadataQuestions].rawValue as? Int ?? 0)

    FetchDataBaseService.sharedInstance.saveContext()
}

//Fetch Quiz Information from DB and Save it to models
@objc func fetchQuiz (quizID: String) {

    let fetchQuizInfo = FetchDataBaseService.sharedInstance.fetchQuizInformation(quizID: quizID)

    if fetchQuizInfo.count > 0 {

        let value = fetchQuizInfo[0]

        quizDetails = QuizDetails(quizVersion: value.quizVersion!,
                                       newQuestions: value.newQuestions!,
                                       navigationType: value.navigationType!,
                                       testMode: value.testMode!,
                                       questionTime: value.questionTime!,
                                       metadataAssoc: value.metadataAssoc!,
                                       randomizeQuestion: value.randomizeQuestion!,
                                       id: value.id!,
                                       metadataTitle: value.metadataTitle!,
                                       gotWrong: value.gotWrong!,
                                       quizTime: value.quizTime!,
                                       title: value.title!,
                                       numberOfQuestions: value.numberOfQuestions!,
                                       quizType: value.quizType!,
                                       randomizeAnswer: value.randomizeAnswer!,
                                       numberOfAvailableMetadataQuestions: value.numberOfAvailableMetadataQuestions!,
                                       totalTestQuestions: value.totalTestQuestions!,
                                       totalCorrectAnswers: value.totalCorrectAnswers!,
                                       totalWrongAnswers: value.totalWrongAnswers!,
                                       totalUnAttempted: value.totalUnAttempted!,
                                       numberOfMetadataQuestions: Int(value.numberOfMetadataQuestions))


        self.delegate?.success(details: quizDetails, isSuccess: true, quizID: quizID)
    }

    else {
        self.delegate?.success(details: nil, isSuccess: false, quizID: quizID)
    }
  }
}

WKQuizInformationVMDelegate - мой протокол. QuizDetails - моя модельная структура.

Я создал структуру (модель), при извлечении данных из базовых данных я создаю модель и передаю ей класс контроллера через делегата.

Не знаю, иногда он работает нормально, но иногда происходит внезапный сбой.

Тема 1: EXC_BAD_ACCESS (код = 1, адрес = 0x50000010)

Я тоже пробовал разные способы, но неожиданно получал сбой.

Что-нибудь связано с базой данных, которую я должен изменить? Или любая другая концепция?

'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x9180952e)
frame #0: 0x00dc7b4c libswiftCore.dylib`swift_unknownRelease + 8
frame #1: 0x000caa00 WKQuiz`WKQuizInformation.quizDetails.setter(value=WKQuiz.QuizDetails @ 0x0064e6c8, self=0x1805d290) at WKQuizInfoVM.swift:0
* frame #2: 0x000d59a8 WKQuiz`WKQuizInformation.fetchQuiz(quizID="307", self=0x1805d290) at WKQuizInfoVM.swift:90
frame #3: 0x000d8fe0 WKQuiz`@objc WKQuizInformation.fetchQuiz(quizID:) at WKQuizInfoVM.swift:0
frame #4: 0x1d04602e Foundation`__NSFireDelayedPerform + 458
frame #5: 0x1c6d0636 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 14
frame #6: 0x1c6d0338 CoreFoundation`__CFRunLoopDoTimer + 832
frame #7: 0x1c6cfd36 CoreFoundation`__CFRunLoopDoTimers + 188
frame #8: 0x1c6cddd4 CoreFoundation`__CFRunLoopRun + 780
frame #9: 0x1c6211ae CoreFoundation`CFRunLoopRunSpecific + 470
frame #10: 0x1c620fd0 CoreFoundation`CFRunLoopRunInMode + 104
frame #11: 0x1ddcbb40 GraphicsServices`GSEventRunModal + 80
frame #12: 0x219a91d2 UIKit`UIApplicationMain + 150
frame #13: 0x001d6114 WKQuiz`main at AppDelegate.swift:15
frame #14: 0x1be0e4ea libdyld.dylib`start + 2

1 Ответ

0 голосов
/ 14 мая 2018

С вашим кодом много ошибок.

  1. делегаты должны быть установлены как слабые.
  2. fetchQuiz отображается для чтения с использованием основного контекста управляемого объекта. Вы можете запустить этот метод только из основного потока. Добавьте DispatchQueue.main.async {, чтобы обеспечить
  3. Каждый ! требует от кода сбоя и должен быть удален
  4. методы должны возвращать то, что вы просили, или должны вызываться с блоком завершения, чтобы вернуть то, что вы просили. Ваш код возвращает значения с использованием делегата. Что не так.
  5. ManagedObjects (например, QuizDetails) не являются потокобезопасными - ни для чтения, ни для записи. Они должны быть доступны из потока, связанного с их контекстом. Похоже, у вас есть только один контекст, поэтому я предполагаю, что это контекст основного потока.
  6. ManagedObjects, которые удаляются из хранилища, автоматически не устанавливаются в ноль. Если вы удерживаете указатель на них после того, как они будут удалены, у вас произойдет сбой. Лучше использовать NSFetchedResultsController - даже для только одного объекта.
  7. perform afterDelay не имеет значения. Я подозреваю, что это было добавлено, чтобы предотвратить состояние гонки или иначе исправить ошибки.
  8. в fetchQuiz, по-видимому, нет причины, по которой вы создаете QuizDetails, когда у вас уже есть тот, который вы только что получили, сохраненный в переменной value

Все это реальные проблемы, которые должны быть исправлены. наиболее вероятная непосредственная причина вашего сбоя - № 2 - (доступ к данным ядра из неправильного потока). заменить

    self.saveUpdateQuizInfoDB(json: json)
    self.perform(#selector(self.fetchQuiz(quizID:)), with: quizID, afterDelay: 0.2) 

с

    DispatchQueue.main.async {
        self.saveUpdateQuizInfoDB(json: json)
        self.fetchQuiz(quizID:quizID)
    }
...