iOS小知识杂集(二)

文章中的内容大多数来源于南峰子的iOS知识小集微博或GitHub

  1. 为什么要缓存NSDateFormatter
    Creating a date formatter is not a cheap operation. If you are likely to use a formatter frequently, it is typically more efficient to cache a single instance than to create and dispose of multiple instances. One approach is to use a static variable.网页链接
    采用方案:网页链接
  2. 音量获取: [[AVAudioSession sharedInstance] outputVolume];
  3. 是谁调了我的底层库
    调试的时候,往往底层库会埋一些 NSLog 来调试,使用下面这种方式打印出来的函数名称 __PRETTY_FUNCTION__ 是底层库的函数名。
#define LEFLog(fmt, ...) NSLog((@"%s (%d) => " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)

打印是这样的:+[Network post] 中打印了 I am a log,而不清楚是谁调用了。
+[Network post] (22) => I am a log
但是,我想要的是我在最顶层调用时的函数名,这样我可以很容易的看到是那个方法调用了底层库。
不太理解?举个例子吧: 每个APP都会有一个网络层,业务层会直接与网络层进行交互。调试的时候,我想知道 A 请求是在哪个页面中的哪个函数被调用了,咋么办?前提是 NSLog 在底层库。我们可以这样实现:

@implementation LEFLog
+ (NSString *)lastCallMethod
{
    NSArray *symbols = [NSThread callStackSymbols];
    NSInteger maxCount = symbols.count;
    NSString *secondSymbol = maxCount > 2 ? symbols[2] : (maxCount > 1 ? symbols[1] : [symbols firstObject]);
    if (secondSymbol.length == 0) {
        return @"";
    }
    
    NSString *pattern = @"[+-]\\[.{0,}\\]";
    NSError *error;
    NSRegularExpression *express = [NSRegularExpression regularExpressionWithPattern:pattern options:kNilOptions error:&error];
    if (error) {
        NSLog(@"Error: %@", error);
        return @"";
    }
    
    NSTextCheckingResult *checkResult = [[express matchesInString:secondSymbol options:NSMatchingReportCompletion range:NSMakeRange(0, secondSymbol.length)] lastObject];
    NSString *findStr = [secondSymbol substringWithRange:checkResult.range];
    return findStr ?: @"";
}

@end

然后定义一个宏:

#define LEFLog(fmt, ...) NSLog((@"%@, %s (%d) => " fmt), [LEFLog lastCallMethod], __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__ 

打印结果是这样的:在 LefexViewController 中的 viewDidLoad 调用了 Networkpost 方法,并打印 I am a log.

-[LefexViewController viewDidLoad], +[Network post] (22) => I am a log
  1. Cocoapodspod installpod update区别
    install 命令不仅在初始时使用,在新增或删除 repo 时也需要运行。update 仅仅在只需更新某一个 repo 或所有时才使用。每次执行 install 时,会将每个repo的版本信息写入到 podfile.lock,已存在于 podfile.lockrepo 不会被更新只会下载指定版本,不在 podfile.lock 中的 repo 将会搜索与 podfile 里面对应 repo 匹配的版本。即使某个 repo 指定了版本,如 pod 'A', '1.0.0',最好也是不要使用 update,因为 repo A 可能有依赖,如果此时使用 update 会更新其依赖。
    5.static方法与class方法的区别
    class修饰的类方法可以被子类重写
    static修饰的类方法不能被子类重写
    6.attribute((objc_requires_super)) 要求子类调用父类方法
    7.CGRectInset它是以rect为中心,根据dx,dy的值来扩大或者缩小,负值为扩大,正值为缩小
    CGRectOffset,它是以rect左上角为基点,向X轴和Y轴偏移dxdy像素

你可能感兴趣的:(iOS小知识杂集(二))