iOS陷阱--NSDateFormatter的线程安全性

来源:互联网 发布:手机阿里云邮箱注册 编辑:程序博客网 时间:2024/06/10 12:43

apple官网文档:

Thread Safety

On iOS 7 and later NSDateFormatter is thread safe.

In macOS 10.9 and later NSDateFormatter is thread safe so long as you are using the modern behavior in a 64-bit app.

On earlier versions of the operating system, or when using the legacy formatter behavior or running in 32-bit in macOS, NSDateFormatter is not thread safe, and you therefore must not mutate a date formatter simultaneously from multiple threads.


说明:ios7及以上版本 NSDateFormatter是线程安全的!之前的版本确定不是线程安全的!所以以后不要管它的线程安全问题了!


========================================================转载=====================================================================

经常需要将NSDate和NSString进行互转,一般我们会这么写:

  1. NSDate转NSString
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@”yyyy-MM-dd’T’HH:mm:ss”];

    [dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:@”Asia/Shanghai”]];
    return [dateFormatter dateFromString:dateString];
  2. NSString转NSDate
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    NSTimeZone *timeZone = [NSTimeZone defaultTimeZone];
    [dateFormatter setTimeZone:timeZone];
    [dateFormatter setDateFormat:@”yyyy-MM-dd HH:mm:ss Z”];
    return [dateFormatter stringFromDate:date];
    上面运行起来好像很顺畅,可是有一天,老大跑过来问:“hey,小张,有用户反应我们的App滑动很卡啊”。于是你打开Profile工具查了一下性能,你会发现上述两个转换函数占CPU比例非常高。怎么优化呢?
  1. 延迟转换并Cache
    即只有在UI需要使用转换结果时再执行转换,并将结果缓存起来。
  2. NSDateFormatter对象只生成1次
   方法1很好容易实现, 下面我们实现方法2:
static NSDateFormatter *dateFormatter = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    dateFormatter = [[NSDateFormatter alloc] init];
});
[dateFormatter setDateFormat:@”yyyy-MM-dd’T’HH:mm:ss”];
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:@”Asia/Shanghai”]];
return [dateFormatter dateFromString:dateString];

    貌似也挺容易的,哈哈经过上面的改造后,你会发现性能得到了显著提升,非常高兴的给老大发布新版本,很快老大又过来把你劈头盖脸地训了一顿:“怎么老是Crash,这么不稳定?赶紧fix”。
    一查CrashReport,发现在[dateFormatter dateFromString:dateString]这里出了问题。这就奇怪了?系统函数库也有bug么?
    当然不是了,这是因为NSDateFormatter不是线程安全的,请查看https://developer.apple.com/library/mac/documentation/cocoa/conceptual/Multithreading/ThreadSafetySummary/ThreadSafetySummary.html,里面列出了线程安全和不安全的类。当多个线程同时访问1个NSDateFormatter对象时,有可能会Crash。
那怎么办?不要泄气,咱们给每个线程准备1个NSDateFormatter,大家就不会打得头破血流了。
解决方案:
NSMutableDictionary *threadDictionary = [[NSThread currentThread] threadDictionary];
NSDateFormatter *dateFormatter = threadDictionary[@”mydateformatter”];

if(!dateFormatter){
    @synchronized(self){
        if(!dateFormatter){
            dateFormatter = [[NSDateFormatter alloc] init];
           [dateFormatter setDateFormat:@”yyyy-MM-dd HH:mm:ss”];
           [dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:@”Asia/Shanghai”]];
          threadDictionary[@”mydateformatter”] = dateFormatter;
         }
    }
}
发现没有,上面使用了double-check技术哦,哈哈,这里千万不要再用dispatch_once哈。
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 裤子穿着往上跑怎么办 伤囗发炎了怎么办 玩派派背包食物不足怎么办 80岁老人植物人怎么办 steam账户创不起怎么办 小孩读书没有居住证怎么办 小孩上学没有准生证怎么办 小学在外地初中怎么办 小孩上学没准生证怎么办 没结婚出生证明怎么办 异地上高中高考怎么办 高中去外地上学怎么办 农村在城里上学怎么办? 父母没钱不工作怎么办 qq被家长偷看怎么办 孩子考差了怎么办 父母翻看qq记录怎么办 孩子qq屏蔽父母怎么办 杜鹃花老叶脱落怎么办 父母对孩子不好怎么办 家长看孩子手机怎么办 六年级打四年级学生怎么办 儿童被家长打怎么办 老师打孩子耳光怎么办 孩子动手打母亲怎么办 小孩被老师体罚怎么办 儿子跟父母对打怎么办 两个孩子争东西怎么办 大人吵架小孩该怎么办 小孩老爱顶嘴怎么办 孩子老爱顶嘴怎么办 孩子不愿分房睡怎么办 孩子不愿意去补课怎么办 高中孩子不愿意补课怎么办 孩子协调性不好怎么办 孩子暑假不愿意补课怎么办 话唠的孩子怎么办 孩孑不做作业怎么办 孩子有消极情绪怎么办 孩子太依赖奶奶怎么办 缺少母爱的孩子怎么办