[譯]Swift 2:可以使用 @NSManage 標(biāo)記自動(dòng)生成方法

2018-06-19 15:06 更新

猛戳鏈接查看最終版

原文鏈接
作者:Tomasz Szulc
原文日期:2015/08/06
譯者:mmoaay;校對(duì):numbbbbb;定稿:shanks

Xcode 7 beta 5 中的 Swift 2 擁有另外一個(gè)特性:當(dāng)使用一對(duì)多關(guān)系時(shí)我們可以用 @NSManaged 來(lái)聲明自動(dòng)生成方法。

這個(gè)技巧非常有用。假設(shè)你有一個(gè) Library 和多個(gè) Book 實(shí)體對(duì)象。且 Librarybooks 是一對(duì)多的關(guān)系。那么使用最新的 Xcode 和 @NSManaged 就可以在 Library 實(shí)體對(duì)象內(nèi)(手動(dòng))聲明自動(dòng)生成方法。

就像下面這樣:

class Library: NSManagedObject {

 
    @NSManaged func addBooksObject(book: Book)
    @NSManaged func removeBooksObject(book: Book)
    @NSManaged func addBooks(books: Set<Book>)
    @NSManaged func removeBooks(books: Set<Book>)
}

天哪,這種實(shí)現(xiàn)方式竟然如此優(yōu)雅!就在幾天前我還不得不從零開(kāi)始寫(xiě)這些方法。

但我發(fā)現(xiàn)一個(gè)問(wèn)題。我們確實(shí)可以像這樣聲明方法,但是問(wèn)題的關(guān)鍵是如何在任意位置生成它們并放入到 Entity+CoreDataProperties.swift 文件中?生成 Objective-C 子類時(shí)這些方法都會(huì)繼承,甚至在 Swift 項(xiàng)目中也是如此。然而,生成 Swift 語(yǔ)言時(shí)——這些方法竟然不見(jiàn)了!詳情參見(jiàn) rdar://22177139 。

下面的代碼是 Objective-C 生成的實(shí)體類



@interface Library (CoreDataGeneratedAccessors)

 
- (void)addBooksObject:(Book *)value;
- (void)removeBooksObject:(Book *)value;
- (void)addBooks:(NSSet<Book *> *)values;
- (void)removeBooks:(NSSet<Book *> *)values;

 
@end

如果你將關(guān)系標(biāo)記為有序,就需要手動(dòng)聲明更多方法

- (void)insertObject:(Book *)value inBooksAtIndex:(NSUInteger)idx;
- (void)removeObjectFromBooksAtIndex:(NSUInteger)idx;
- (void)insertBooks:(NSArray<Book *> *)value atIndexes:(NSIndexSet *)indexes;
- (void)removeBooksAtIndexes:(NSIndexSet *)indexes;
- (void)replaceObjectInBooksAtIndex:(NSUInteger)idx withObject:(Book *)value;
- (void)replaceBooksAtIndexes:(NSIndexSet *)indexes withBooks:(NSArray<Book *> *)values;
- (void)addBooksObject:(Book *)value;
- (void)removeBooksObject:(Book *)value;
- (void)addBooks:(NSOrderedSet<Book *> *)values;
- (void)removeBooks:(NSOrderedSet<Book *> *)values;

這樣寫(xiě)好麻煩啊……希望他們盡快修復(fù)這個(gè)問(wèn)題 :)

另一個(gè)等待 Apple 修復(fù)的問(wèn)題是:有序的一對(duì)多關(guān)系及其自動(dòng)生成的方法。這個(gè)問(wèn)題存在已久。但不知道是否有對(duì)應(yīng)的錯(cuò)誤報(bào)告。我認(rèn)為這個(gè)問(wèn)題發(fā)生在 Core Data 和下面這個(gè)方法第一次被釋放時(shí)。假設(shè)我們想給 Library 添加一些 Book

let ctx = self.managedObjectContext
let library = NSEntityDescription.insertNewObjectForEntityForName("Library", inManagedObjectContext: ctx) as! Library
let book1 = NSEntityDescription.insertNewObjectForEntityForName("Book", inManagedObjectContext: ctx) as! Book
library.addBooksObject(book1)

結(jié)果是根本運(yùn)行不起來(lái)。

2015-08-06 23:14:18.541 NewNSManagedExample[54727:3677632] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSSet intersectsSet:]: set argument is not an NSSet'
*** First throw call stack:
(
    0   CoreFoundation                      0x00ea83b4 __exceptionPreprocess + 180
    1   libobjc.A.dylib                     0x005cde02 objc_exception_throw + 50
    2   CoreFoundation                      0x00dfc574 -[NSSet intersectsSet:] + 260
    3   Foundation                          0x00214756 NSKeyValueWillChangeBySetMutation + 153
    4   Foundation                          0x0017c4c7 NSKeyValueWillChange + 394
    5   Foundation                          0x0021466a -[NSObject(NSKeyValueObserverNotification) willChangeValueForKey:withSetMutation:usingObjects:] + 630
    6   CoreData                            0x00a981c6 _sharedIMPL_addObjectToSet_core + 182
    7   CoreData                            0x00a99189 __generateAccessor_block_invoke_2 + 41
    8   NewNSManagedExample                 0x000f0e80 _TFC19NewNSManagedExample11AppDelegate11applicationfS0_FTCSo13UIApplication29didFinishLaunchingWithOptionsGSqGVSs10DictionaryCSo8NSObjectPSs9AnyObject____Sb + 720
    9   NewNSManagedExample                 0x000f10c7 _TToFC19NewNSManagedExample11AppDelegate11applicationfS0_FTCSo13UIApplication29didFinishLaunchingWithOptionsGSqGVSs10DictionaryCSo8NSObjectPSs9AnyObject____Sb + 199
    10  UIKit                               0x0122e1c6 -[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] + 337
    11  UIKit                               0x0122f56c -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 3727
    12  UIKit                               0x01236929 -[UIApplication _runWithMainScene:transitionContext:completion:] + 1976
    13  UIKit                               0x01259af6 __84-[UIApplication _handleApplicationActivationWithScene:transitionContext:completion:]_block_invoke3142 + 68
    14  UIKit                               0x012336a6 -[UIApplication workspaceDidEndTransaction:] + 163
    15  FrontBoardServices                  0x03ff9ccc __37-[FBSWorkspace clientEndTransaction:]_block_invoke_2 + 71
    16  FrontBoardServices                  0x03ff97a3 __40-[FBSWorkspace _performDelegateCallOut:]_block_invoke + 54
    17  FrontBoardServices                  0x040171cb -[FBSSerialQueue _performNext] + 184
    18  FrontBoardServices                  0x04017602 -[FBSSerialQueue _performNextFromRunLoopSource] + 52
    19  FrontBoardServices                  0x040168fe FBSSerialQueueRunLoopSourceHandler + 33
    20  CoreFoundation                      0x00dc27af __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
    21  CoreFoundation                      0x00db843b __CFRunLoopDoSources0 + 523
    22  CoreFoundation                      0x00db7858 __CFRunLoopRun + 1032
    23  CoreFoundation                      0x00db7196 CFRunLoopRunSpecific + 470
    24  CoreFoundation                      0x00db6fab CFRunLoopRunInMode + 123
    25  UIKit                               0x01232f8f -[UIApplication _run] + 540
    26  UIKit                               0x01238724 UIApplicationMain + 160
    27  NewNSManagedExample                 0x000f24dc main + 140
    28  libdyld.dylib                       0x039afa21 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

這個(gè)問(wèn)題唯一的解決辦法就是重新實(shí)現(xiàn)那些方法。 詳情參見(jiàn)rdar://22177512——希望他們?cè)缛招迯?fù)這個(gè)問(wèn)題。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)