iOS在framework中使用CoreData出現崩潰問題及解決方法

公司項目中有一個功能,保存受權令牌數據。最開始只有一條數據,因此就直接保存在了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文件拖入原工程中。swift

編譯運行,崩潰並提示app

CoreData: warning: Unable to load class named 'AToken' for entity 'AToken'. Class not found, using default NSManagedObject instead.ide

搜索以後發現這個回答性能

https://stackoverflow.com/questions/26613971/coredata-warning-unable-to-load-class-named測試

不過這是使用swift時遇到的問題,可是我用的oc,問題沒有解決。ui

又通過一段時間的搜索,發現有一個問題和我遇到的很是類似spa

https://stackoverflow.com/questions/27465485/coredata-warning-unable-to-load-class-named-weereadings-for-entity-readings.net

按照上面的方法在build setting-other linker flags中加入-ObjC,運行,若是能夠的話就不用繼續往下看了。code

可是個人程序運行以後仍是崩潰,可是沒有崩潰提示,因此我就把-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,並放到測試項目中,運行,終於沒有崩潰了。

困擾了好幾天的問題就這樣解決了,記錄下來,但願能夠幫助遇到一樣問題的人。

相關文章
相關標籤/搜索