解决iPhone5等32位设备,13位时间戳转换异常

32-bit 64-bit

2015年初,所有提交审核的App需要适配64位,目的是充分利用ARM处理器的高性能支持,让应用能够有更为极致的体验。在iPhone5S以后的设备都是支持64位的。

一、时间显示引发的问题

问题页面

由于32位处理器的NSInteger是int类型的,导致溢出,下面我们来具体看一下。

1、服务端返回JSON数据

服务端返回日期数据为13位时间戳。

{
    "count": 0,
    "data": {
        "nowDate": 1508470153576,       //13位时间戳
        "skuCommission": {
            "actPrice": 89,
            "commissionRate": 0.1,
            "endTime": 1508547599000,   //13位时间戳
            "isDelete": 0,
            "limitCommissionRate": 0,
            "limitInventory": 0,
            "limitUseCoupon": false,
            "skuId": 0,
            "specialSell": true,
            "startTime": 1508461200000, //13位时间戳
            "type": 1
        },
        "saleInfo": {
            "endTime": 1508547599000,   //13位时间戳
            "price": 89,
            "startTime": 1508461200000  //13位时间戳
        },
    },
    "isRedirect": 0,
    "isSuccess": 1,
    "login": 0
}
2、iOS客户端Model数据模型

客户端通过MJExtension(数据转模型开源库),解析为Model模型。
修改前:时间戳使用NSInteger类型
修改后:时间戳使用double类型(或者 long long类型)

@interface ProductDetailModel : NSObject
#@property (nonatomic, assign) NSInteger nowDate;               //修改前
@property (nonatomic, assign) double nowDate;                   //修改后
@end

@interface ProductSkuCommission : NSObject
@property (nonatomic, assign) CGFloat actPrice;
@property (nonatomic, assign) CGFloat commissionRate;
#@property (nonatomic, assign) NSInteger endTime;               //修改前
@property (nonatomic, assign) double endTime;                   //修改后
@property (nonatomic, assign) NSInteger gmtCreate;
@property (nonatomic, assign) NSInteger gmtModified;
@property (nonatomic, assign) NSInteger isDelete;
@property (nonatomic, assign) NSInteger limitCommissionRate;
@property (nonatomic, assign) NSInteger limitInventory;
@property (nonatomic, assign) NSInteger skuId;
@property (nonatomic, assign) BOOL specialSell;
#@property (nonatomic, assign) NSInteger startTime;             //修改前
@property (nonatomic, assign) double startTime;                 //修改后
@property (nonatomic, assign) NSInteger type;
@end

@interface ProductSaleInfo : NSObject
#@property (nonatomic, assign) NSInteger endTime;               //修改前
@property (nonatomic, assign) double endTime;                   //修改后
@property (nonatomic, assign) CGFloat price;
#@property (nonatomic, assign) NSInteger startTime;             //修改前
@property (nonatomic, assign) double startTime;                 //修改后
@end
3、出现溢出问题

❌时间戳转换成时间后,显示异常❌,如下:

// 原始数据
1508547599000

// 64位架构,使用NSInteger
1508461200000 10月20日09点

// 32位架构,使用NSInteger
927679104     01月12日01点

二、排查问题

排查了网络返回数据,用户设备时区,使用设备机型,使用设备系统,是否越狱,转换时间方法等等,后来发现在iPhone5,iPhone5C设备中存在该问题(目前App兼容iOS8以上,暂时不考虑iPhone5以下机型),其他设备是OK的,考虑问题出在机型之间存在的差异。

1、通过XCode,按住「Command」点击「NSInteger」查看NSInteger的定义如下:

32位CPU上,将NSInteger定义为了int类型
64位CPU上,将NSInteger定义为了long类型

2、通过Dash,查看Apple官网API文档,查看NSInteger的定义如下:

构建32位应用,NSInteger32位整型
构建64位应用,NSInteger64位整型

注意:由于long和NSInteger的字节数变了,所以在兼容的时候可能会导致溢出

相同类型在不同处理器中的差异:
类型 32位 处理器 64位 处理器
NSInteger int long
NSUInteger unsigned int unsigned long
~ ~ ~
int 32bit(4字节) 32bit(4字节)
long 32bit(4字节) 64bit(8字节)
long long 64bit(8字节) 64bit(8字节)
变量范围:
整型 有符号 范围 无符号 范围
4字节 -2147483648 ~ 2147483647 0 ~ 4294967295
8字节 -9223372036854775808 ~ 9223372036854775807 0 ~ 18446744073709551615

三、为什么用NSInteger,不直接用int或long呢?

现在,Xcode可以支持开发32位和64位的应用,为了让开发者写出在其他系统上也能够运行的代码,苹果公司引入了NSInteger类型以及NSUInteger类型。这两种类型无论在32位系统还是64位系统上都能够通用。

NSInteger以及NSUInteger类型在苹果的类库中被广泛使用,所以写Objective-C的时候,会经常使用它们。

用NSInteger 声明的整型变量,你不用关心是32位还是64位不用关心是声明int还是longiOS编译器会自动分配完成

四、总结:

一个10位以上的整数。
64位系统中,使用NSInteger或者long类型,是可以正常存储的 。
32位系统中,由于字节数变了,导致溢出了。
兼容32位64位系统,使用intlong long(或者int32_tint64_t)这样的数据类型,比使用NSInteger要更加可靠,具体问题具体分析。

最后,使用了double代替NSInteger来解决该问题

参考

About 64-Bit Cocoa Touch Apps
64-bit Tips

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容