iOS 工程 相容64位 容易遇到的問題
tips:
相信目前大部分APP的工程框架已經是支援64bit,但是就在幾天前,遇到一個公司幾年前的框架,SQLCipher資料庫加密,AES加密,ASI網路請求,JSONKit,ZipArchive。。全是32bit,全打包成了.a靜態庫,我曹,如果讓工程支援64bit,那我豈不是要重新引入這些三方 /嚇?但在廢棄這個框架之前,確實需要這麼幹。
正文:
好在大部分用來打包.a檔案的原始檔都在gitlab上,我還能找到,這算是不幸中的萬幸
1、AES替換,無問題
2、ASI替換,在”Target”->”Build Phases”->”Compile Source”中所有ASI 檔案的compile Flags 設定”-fno-objc-arc” 相容ARC
3、JSONKit替換,同2、
4、ZipArchive替換,同2、
error1:
當到這裡的時候,編譯發現一個錯誤”Implicit declaration of function ‘NSFileTypeForHFSTypeCode’ is invalid in C99”,
這是FMDB的問題,FMDatabaseAdditions.m中存在如下一段程式碼:我們需要在程式碼的外面做預編譯處理
#if TARGET_OS_MAC && !TARGET_OS_IPHONE // 新增預編譯處理
- (NSString*)applicationIDString {
NSString *s = NSFileTypeForHFSTypeCode([self applicationID]);
assert([s length] == 6);
s = [s substringWithRange:NSMakeRange(1, 4)];
return s;
}
- (void)setApplicationID:(uint32_t)appID {
NSString *query = [NSString stringWithFormat:@"PRAGMA application_id=%d", appID];
FMResultSet *rs = [self executeQuery:query];
[rs next];
[rs close];
}
- (void)setApplicationIDString:(NSString*)s {
if ([s length] != 4) {
NSLog(@"setApplicationIDString: string passed is not exactly 4 chars long. (was %ld)", [s length]);
}
[self setApplicationID:NSHFSTypeCodeFromFileType([NSString stringWithFormat:@"'%@'", s])];
}
#endif // 結束
5、SQLCipher替換,重新配置了一個,詳情見https://www.zetetic.net/sqlcipher/ios-tutorial/
error 2:
這個時候又出現了另一個問題crash:
NSInvalidArgumentException -[__NSTaggedPointerString unsignedLongLongValue]: unrecognized selector sent to instance
定位到實體中的字典轉模型方法中:
- (instancetype)initWithDictionary:(NSDictionary *)dictionary
{
self = [super init];
if (self) {
_undefinedProperties = [NSMutableDictionary dictionary];
[dictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
DCProperty *property = [[self class] propertyDictionary][key];
Class class = NSClassFromString(property.type);
if ([class isSubclassOfClass:[DCObject class]]) {
DCObject *object = [[class alloc] initWithDictionary:obj];
[self setValue:object forKey:key];
}
else if (![obj isEqual:[NSNull null]]) {
[self setValue:obj forKey:key]; ---------crash的地方
}
}];
}
return self;
}
這個問題,是因為64bit中,NSString 中沒有unsignedLongLongValue這個方法了, 而當字典中obj的型別是NSString型別,實體中的key對應的屬性是NSUinteger型別,setValue:obj forKey:key 會自動做如下處理:
[obj unsignedLongLongValue] 將value轉為對應的屬性型別,這就導致64bit中找不到該方法而crash。我的解決是,對NSString寫一個category,重新寫一個unsignedLongLongValue的方法:
-(NSUinteger)unsignedLongLongValue {
return [self integerValue];
}
或者 避免 讓系統做NSString->NSUInteger的型別裝換