Массив AnyObject, возвращаемый ошибками NSFetchRequest с "Сбой динамического приведения Swift" при приведении в Swift XCode 6 Beta 4 в XCTestCase

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

Я настраиваю свои Entities как на скриншоте: Entity setup image

У меня был XCode генерировать подкласс NSManagedObject:

import Foundation
import CoreData

class Goal: NSManagedObject {
    @NSManaged var displayDesc: String
    @NSManaged var motivation: String
    @NSManaged var cratedDate: NSDate
    @NSManaged var goalType: NSNumber
}

Он также создал заголовочный файл с именем LifeList-Bridging-Header.h, который является пустым.

Наконец я настроил тестовый пример:

import UIKit
import XCTest
import CoreData

class CastExceptionTest: XCTestCase {
    var _managedObjectContext: NSManagedObjectContext? = nil
    var _persistentStoreCoordinator: NSPersistentStoreCoordinator? = nil
    var _managedObjectModel: NSManagedObjectModel? = nil

    var applicationDocumentsDirectory: NSURL {
        let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
        return urls[urls.count-1] as NSURL
    }

    var managedObjectContext: NSManagedObjectContext {
        if !_managedObjectContext {
            let coordinator = self.persistentStoreCoordinator
            if coordinator != nil {
                _managedObjectContext = NSManagedObjectContext()
                _managedObjectContext!.persistentStoreCoordinator = coordinator
            }
        }
        return _managedObjectContext!
    }

    var managedObjectModel: NSManagedObjectModel {
        if !_managedObjectModel {
            //The data model is just an Entity named Goal with 4 attributes one named displayDesc.
            let modelURL = NSBundle.mainBundle().URLForResource("LifeList", withExtension: "momd")
            _managedObjectModel = NSManagedObjectModel(contentsOfURL: modelURL)
        }
        return _managedObjectModel!
    }

    var persistentStoreCoordinator: NSPersistentStoreCoordinator {
        if !_persistentStoreCoordinator {
            let storeURL = self.applicationDocumentsDirectory.URLByAppendingPathComponent("CastExceptionTest.sqlite")
            var error: NSError? = nil
            _persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
            if _persistentStoreCoordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: storeURL, options: nil, error: &error) == nil {
                abort()
            }
        }
        return _persistentStoreCoordinator!
    }

    func testCase() {
        //Create and save a new Goal
        let entityDescription = NSEntityDescription.entityForName("Goal", inManagedObjectContext: managedObjectContext)
        let goal = Goal(entity: entityDescription, insertIntoManagedObjectContext: managedObjectContext)
        goal.displayDesc = "Test text"
        var error:NSError?
        managedObjectContext.save(&error)

        //Load the entities
        let fetch = NSFetchRequest(entityName: "Goal")
        let objectArray: [AnyObject]? = managedObjectContext.executeFetchRequest(fetch, error: &error)
        for object in objectArray! {
            let goal = object as Goal
            print(goal.displayDesc)
        }
    }
}

Ниже приведен результат выполнения теста:

libswift_stdlib_core.dylib`swift_dynamicCastClassUnconditional:
0x105b147c0:  pushq  %rbp
0x105b147c1:  movq   %rsp, %rbp
0x105b147c4:  pushq  %r14
0x105b147c6:  pushq  %rbx
0x105b147c7:  movq   %rsi, %rbx
0x105b147ca:  movq   %rdi, %r14
0x105b147cd:  testq  %r14, %r14
0x105b147d0:  je     0x105b147fe               ; swift_dynamicCastClassUnconditional + 62
0x105b147d2:  movabsq $-0x7fffffffffffffff, %rax
0x105b147dc:  andq   %r14, %rax
0x105b147df:  jne    0x105b147fe               ; swift_dynamicCastClassUnconditional + 62
0x105b147e1:  movq   %r14, %rdi
0x105b147e4:  callq  0x105b29764               ; symbol stub for: object_getClass
0x105b147e9:  nopl   (%rax)
0x105b147f0:  cmpq   %rbx, %rax
0x105b147f3:  je     0x105b1480d               ; swift_dynamicCastClassUnconditional + 77
0x105b147f5:  movq   0x8(%rax), %rax
0x105b147f9:  testq  %rax, %rax
0x105b147fc:  jne    0x105b147f0               ; swift_dynamicCastClassUnconditional + 48
0x105b147fe:  leaq   0x1da7d(%rip), %rax       ; "Swift dynamic cast failed"
0x105b14805:  movq   %rax, 0x88da4(%rip)       ; gCRAnnotations + 8
0x105b1480c:  int3   
0x105b1480d:  movq   %r14, %rax
0x105b14810:  popq   %rbx
0x105b14811:  popq   %r14
0x105b14813:  popq   %rbp
0x105b14814:  retq   
0x105b14815:  nopw   %cs:(%rax,%rax)

2 ответа

Решение

Вся заслуга в этом принадлежит Jrtuton. Есть ли способ приписать ему ответ?

Вот внесенные изменения:

  1. Удален класс Goal из списка компиляции для цели теста.

  2. Добавлены правильные модификаторы доступа в класс Goal:

    public class Goal: NSManagedObject {
    
        @NSManaged public var displayDesc: String
        @NSManaged public var motivation: String
        @NSManaged public var cratedDate: NSDate
        @NSManaged public var goalType: NSNumber
    
  3. Добавлен публичный метод init:

    public init(entity: NSEntityDescription, insertIntoManagedObjectContext:   NSManagedObjectContext) {
        super.init(entity: entity, insertIntoManagedObjectContext:   insertIntoManagedObjectContext)
    }
    
  4. Импортировал модуль LifeList в мой тестовый класс:

    import LifeList
    

Попробуй это:

@objc(CastExceptionTest)    // add this line
class CastExceptionTest: XCTestCase {
    ...
}
Другие вопросы по тегам