1. 程式人生 > >iOS 工程 相容64位 容易遇到的問題

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的型別裝換