2014-07-08 16 views
5

Używam Swift na Xcode 6 z CoreData.Problemy z rzutowaniem Swift i CoreData w teście vs bez testu

Przeczytałem informacje o wersji i widziałem ten numer issue o konieczności oznaczenia podstawowego modelu danych nazwą modułu (nazwą aplikacji), aby można było przesyłać do modelu w czasie wykonywania model NSManagedObject.

Kiedy to zrobię, mogę uruchomić aplikację poprawnie (dobrze!). Jednakże, mój problem jest, gdy próbuję testu że sam kod, test będzie zawsze upaść, gdy obsada dzieje z Swift dynamic cast failed błąd (źle :(). To sprawia, że ​​trudno przetestować aplikację.

Czy ? jakiś wpływ na nazwę modułu używamy, gdy aplikacja jest zbudowany do badania w porównaniu z systemem

Dzięki z góry za wszelkie wskazówki ...

Kontynuacja:

to nie jest idealny: Jak wspomniano powyżej, Aby Swift mógł używać Core D model ata, musisz udekorować nazwę klasy nazwą swojej aplikacji. To działa znaleźć do budowania aplikacji, ale testy działają pod inną nazwą aplikacji! Oznacza to, że musisz przejść do programisty modeli danych i zmienić nazwę tej klasy z myAppname.myEntity na myAppnameTests.myEntity, zanim będziesz mógł używać tych encji według nazwy, gdy są używane lub wywoływane z testu.

+0

Spróbuj udekorować nazwę klasy za pomocą @objc (MyClassName). Spowoduje to ominięcie zwykłego mangerowania nazwy. Wtedy nie powinieneś martwić się o nazwę modułu w modelu danych. –

+0

Jeśli napiszę moje klasy jednostek w szybkim tempie, a następnie udekoruj je za pomocą 'objc (xxx)' - otrzymuję błąd rzutu dynamicznego za każdym razem, gdy spróbuję użyć encji o tej nazwie w innym szybkim kodzie ... Frustrowanie ... –

+0

Spróbuj this: http://stackoverflow.com/a/26568813/438063 – Lucien

Odpowiedz

1

Trzeba dodać jedną linię do Entity.swift złożyć, aby to również klasa Objective-C tak:

@objc(YourEntity) 
class YourEntity: NSManagedObject { 
    ... 
} 

myślę to jako błąd, jeśli projekt nie zawiera dowolny objective- kod c. Jednak musisz dodać tę linię, dopóki to nie zostanie naprawione.

Nauczyłem się tego stąd.

Youtube video at 11:45

+0

Mój projekt ma obiektywny kod c - ale problemy, które mam, to te, w których szybki kod wywołuje (lub próbuje wywołać) Swift Core Data Code ... :( –

+0

Możesz więc wypróbować moją metodę, która działa dla mnie. w mojej metodzie nie trzeba dodawać żadnych pracowników nazw aplikacji do encji. Po prostu pozostaw to samo z nazwą klasy. –

4

Twoje są całkowicie w porządku, problem jest podczas uruchamiania aplikacji go szuka myAppname.myEntity i po uruchomieniu go jako test wygląda jak myAppnameTests.myEntity. Rozwiązaniem, którego używam w tym momencie (Xcode 6.1), jest NIE wypełnianie pola Class w interfejsie CoreData i wykonywanie go w kodzie zamiast tego.

Ten kod wykrywa, czy używasz aplikacji jako testu i używasz poprawnej nazwy modułu i aktualizujesz managedObjectClassName.

lazy var managedObjectModel: NSManagedObjectModel = { 
    // The managed object model for the application. This property is not optional... 
    let modelURL = NSBundle.mainBundle().URLForResource("Streak", withExtension: "momd")! 
    let managedObjectModel = NSManagedObjectModel(contentsOfURL: modelURL)! 

    // Check if we are running as test or not 
    let environment = NSProcessInfo.processInfo().environment as [String : AnyObject] 
    let isTest = (environment["XCInjectBundle"] as? String)?.pathExtension == "xctest" 

    // Create the module name 
    let moduleName = (isTest) ? "StreakTests" : "Streak" 

    // Create a new managed object model with updated entity class names 
    var newEntities = [] as [NSEntityDescription] 
    for (_, entity) in enumerate(managedObjectModel.entities) { 
     let newEntity = entity.copy() as NSEntityDescription 
     newEntity.managedObjectClassName = "\(moduleName).\(entity.name)" 
     newEntities.append(newEntity) 
    } 
    let newManagedObjectModel = NSManagedObjectModel() 
    newManagedObjectModel.entities = newEntities 

    return newManagedObjectModel 
}() 
+1

Jeśli chcesz, aby nazwa twojego modułu była dynamiczna (zamiast kodowania twardego), użyj 'NSBundle.mainBundle(). InfoDictionary? [" CFBundleName "]!'. Powinno zwrócić "Streak" –

Powiązane problemy