公司項目中有一個功能,保存授權令牌數據。最開始只有一條數據,所以就直接保存在了userdefaults中。後來需要兩條數據,還是保存在userdefaults中,其中一條為固定的,另一條不固定可以進行替換或刪除。最近又需要保存多條數據,那麼usedefaults就不適合了,就考慮使用資料庫。iOS中 ...
公司項目中有一個功能,保存授權令牌數據。最開始只有一條數據,所以就直接保存在了userdefaults中。後來需要兩條數據,還是保存在userdefaults中,其中一條為固定的,另一條不固定可以進行替換或刪除。最近又需要保存多條數據,那麼usedefaults就不適合了,就考慮使用資料庫。iOS中可以選擇FMDB或CoreData,兩者都是基於SQLite資料庫的封裝,其中CoreData是蘋果開發的ORM類型的資料庫,在數據量比較少時,兩者性能差別不是很大。因為需要在framework中使用,所以儘量不要多引用第三方庫,防止和原項目中的庫衝突。並且之前項目中用到過在framework中使用CoreData,比較熟悉,所以決定這次也用CoreData。
在framework工程中,新建data model,添加entity和attributes,生成對應的NSManagedObject子類,在CoreDataProperties擴展中添加一些自定義方法,然後打包framework,並將xcdatamodel文件打包到bundle文件中(為mom格式),最後把.framework和.bundle文件拖入原工程中。
編譯運行,崩潰並提示
CoreData: warning: Unable to load class named 'AToken' for entity 'AToken'. Class not found, using default NSManagedObject instead.
搜索之後發現這個回答
https://stackoverflow.com/questions/26613971/coredata-warning-unable-to-load-class-named
不過這是使用swift時遇到的問題,但是我用的oc,問題沒有解決。
又經過一段時間的搜索,發現有一個問題和我遇到的非常相似
按照上面的方法在build setting-other linker flags中加入-ObjC,運行,如果可以的話就不用繼續往下看了。
但是我的程式運行之後還是崩潰,但是沒有崩潰提示,所以我就把-ObjC去掉了。
過了兩天,經過各種搜索嘗試後,還是沒有解決。今天來的時候,我想是不是原有工程中的一些項有影響。然後就新建一個測試項目,把之前生成的framework放進來,但還是提示上面那個錯誤。我想既然提示沒有找到這個類,就在崩潰的地方手動調用initialize方法來載入這個類,這樣改過後,錯誤提示變成這樣的
unrecongized selector send to instance
找不到對應的方法,很奇怪怎麼會沒有呢,百度怎麼輸出類中的所有方法,結果是這樣的
#import <objc/runtime.h> #import <objc/message.h> -(void)getAllMethods { unsigned int count; Method *methods = class_copyMethodList([AToken class], &count); for (int i = 0; i < count; i++) { Method method = methods[i]; SEL selector = method_getName(method); NSString *name = NSStringFromSelector(selector); NSLog(@"方法名字 ==== %@",name); } }
在測試項目中調用這個方法,沒有輸出一個方法,這些方法明明就有,在自動生成的CoreDataProperties擴展中,難道是擴展的問題。我就在網上搜索了這個問題,發現了這個答案
https://blog.csdn.net/qq_28865297/article/details/78227537
按照上面的方法在build setting-other linker flags中加入-ObjC,再次運行,發現可以輸出類中所有的方法了,但還是崩潰在向CoreData中插入數據的時候,不過好在這次有錯誤提示
2019-01-25 13:26:02.833971+0800 FrameworkTest[61131:21155913] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Class 'AToken' for entity 'AToken' has an illegal override of NSManagedObject -isEqual:'
原來是重寫isEqual方法導致的,想起之前為了比較自定義類的對象是否相等重寫了這個方法,是這樣寫的
- (BOOL)isEqual:(id)object { if (self == object) { return YES; } if (![object isKindOfClass:[self class]]) { return NO; } return [self isEqualToToken:object]; } - (BOOL)isEqualToToken:(AToken *)token { if (!token) { return NO; } BOOL haveEqualToken = (!self.token && !token.token) || [self.token isEqualToData:token.token]; BOOL haveEqualDefault = self.isDefault == token.isDefault; BOOL haveEqualSaveTime = (!self.saveTime && !token.saveTime) || [self.saveTime isEqualToDate:token.saveTime]; BOOL haveEqualReadCOunt = self.readCount == token.readCount; return haveEqualToken && haveEqualDefault && haveEqualSaveTime && haveEqualReadCOunt; } - (NSUInteger)hash { NSUInteger hash = [super hash]; hash = [self.token hash] ^ self.isDefault ^ self.readCount; return hash; }
所以就把isEqual和hash方法註釋掉,再重新生成framework,並放到測試項目中,運行,終於沒有崩潰了。
困擾了好幾天的問題就這樣解決了,記錄下來,希望可以幫助遇到同樣問題的人。