三年经验之你忽略的小知识点

三年经验之你忽略的小知识点_第1张图片

1、不自定义Cell,利用UITableView的几个属性 做出系统样式的编辑选中

三年经验之你忽略的小知识点_第2张图片
pic-1.jpeg
    //1.允许在编辑模式中进行多选操作
    self.tableView.allowsSelectionDuringEditing = YES;

    //2.改变tableView的当前编辑状态
    [self.tableView setEditing:!self.tableView.isEditing animated:YES];

    //3.获取在编辑状态下被选中的cell
     NSArray *indexPaths = [self.tableView indexPathsForSelectedRows];
    

2、UITableView容易混淆模糊的属性(驼峰语法看起也头痛^ ~^ !!)

  • allowsSelectionDuringEditing : 默认NO,编辑模式下是否可以选中

  • allowsSelection 默认YES,控制在,非编辑模式下row是否可以被选中

  • allowsMultipleSelection 默认NO,控制tableview是否能同时多行选中

  • allowsMultipleSelectionDuringEditing 默认NO,控制编辑模式下是否能同时多行选中

3、iOS图片拉伸技巧 代码及storyboard方式

原理: 配置保护哪部分内容,拉伸哪部分
  • 1、传入left和top保护宽度(iOS5之前),系统帮你拉伸1X1
//leftCapWidth代表左端盖宽度,topCapHeight代表顶端盖高度
- (UIImage *)stretchableImageWithLeftCapWidth:(NSInteger)leftCapWidth topCapHeight:(NSInteger)topCapHeight;  

  • 2、传入上下左右四个方向需要保护的区域,拉伸不需要保护的地方(iOS)
//UIEdgeInsets类型的参数 内边距
- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets  

PS:不知道拉伸区域为负数会如何,晚上实验一下

  • 3、iOS6之后的方法。 在上个方法基础上加了伸缩模式:平铺/拉伸
//UIEdgeInsets类型的参数 内边距
//UIImageResizingMode 通过拉伸UIEdgeInsets指定的矩形区域来填充图片
- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets resizingMode:(UIImageResizingMode)resizingMode  
三种代码方式原理详细见解请看这位作者 iOS图片拉伸原理介绍
  • 4、storyboard在Asset中设置,一劳永逸。配置好就不用代码了
    参数配置参考第三条。


    三年经验之你忽略的小知识点_第3张图片
    storyboard.png

4、iOS图片缩小方法 (show code)

//img:为传入的图片;   size:为放置图片区域的大小;  scaledImage:为返回压缩后的图片
+ (UIImage *)scaleToSize:(UIImage *)img size:(CGSize)size{
    // 创建一个bitmap的context
    // 并把它设置成为当前正在使用的context
    UIGraphicsBeginImageContext(size);
    // 绘制改变大小的图片
    [img drawInRect:CGRectMake(0,0, size.width, size.height)];
    // 从当前context中创建一个改变大小后的图片
    UIImage* scaledImage =UIGraphicsGetImageFromCurrentImageContext();
    // 使当前的context出堆栈
    UIGraphicsEndImageContext();
    //返回新的改变大小后的图片
    return scaledImage;
}

5、KVC将字典赋值到模型中

  • KVC :Key Value Coding 即键值编码,通常是用来给某一个对象的属性进行赋值
    [obj setValuesForKeysWithDictionary:(NSDictionary *)];

6、修饰block为什么要用copy delegate要用weak

Block
  • block是一个对象, 所以block理论上是可以retain/release的. 但是block在创建的时候它的内存是默认是分配在栈(stack)上, 而不是堆(heap)上的. 所以它的作用域仅限创建时候的当前上下文(函数, 方法...), 当你在该作用域外调用该block时, 程序就会崩溃.
  • 在方法中的block创建在栈区, 使用copy就能把他放到堆区, 这样在作用域外调用该block程序就不会崩溃.
Delegate

delegate 要用weak,主要是考虑到循环引用的问题。

  • 如果delegate用强引用。A对象持有B对象,A又作为B对象的代理。两者之间就有两条强引用。A想要释放的时候,B强引用释放不了。B想释放,A又强引用着。造成循环引用。

7、id 与 instancetype 使用区别及举例理解 以及初始化方法为什么不用(ClassName *)返回示例对象

  • 首先instancetype、id都是任意对象类型
  • instancetype自动识别当前是哪个类在调用,就会变成相应类的对象
  • id 首先不能使用.语法。
  • id可以作为方法的参数,但instancetype不可以
  • id 可以调用任何对象的方法,这样就不利于编译器检查错误
@interface Shop :NSObject
+(instancetype)shopWithName:(NSString *)name;   ------1 写法
+(id)shopWithName:(NSString *)name;             ------2 写法
@end
- (void)viewDidLoad{
     [super viewDidLoad];
    [[Shop shopWithName] setFrame:CGRectZero];
}

如果shopWithName1写法 ,编译器就会报错,是2写法 ,编译器就不会报错。

  • 初始化方法为什么不用(ClassName *)返回示例对象呢
    原因:比如说一个Animal类,是用+(Animal *)animalWithName:(NSString *)name这种方法书写的便利构造。那么当有一个子类Dog继承于他,没有书写任何东西,像下面这样调用:
- (void)viewDidLoad{
     [super viewDidLoad];
    //子类可以使用父类非privated的属性和方法
     Dog *dog = [[Dog animalWithName];
}

+(Animal *)animalWithName:(NSString *)name返回的是一个Animal对象,你赋值给Dog类实例,系统就会在这儿提出警告说你类型不匹配。

8、KVC系统查找顺序

当调用setValue:属性值 forKey:@”name“的代码时:以@property name为例;

首先查找对象有没有setName,有则调用set方法赋值
没有找到set方法,就查找对象的成员变量有没有_name,有就_name = value
如果没有找到_name,还会去对象中查找name属性
最终没有找到则报错

  • 深入了解KVC更多知识请点击

9、宏及宏定义常见书写介绍

  • 宏里边可变参数:是三个点...
  • 宏定义中的函数的可变参数:__VA_ARGS__
    这句话理解就是:__Value_ Arguments__ value:值 Arguments__:参数

举例:

#ifdef DEBUG
#define NSLog(FORMAT, ...) fprintf(stderr,"%s\n",[[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);
#else
#define NSLog(...)
#endif

10、模拟器 模拟内存警告

操作步骤:
一、实现测试内存警告接收方法

//appdelegate.m文件实现应用程序接收内存警告协议方法
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application{
    
    NSLog(@"%s",__func__);
}

二、模仿内存警告
操作:
1.Debug-》Simulate Memory Warning


三年经验之你忽略的小知识点_第4张图片
samulator.png

11、自定义控制器View

做法:重写控制器的-loadView方法。

- (void)loadView{
    self.view = [[UIView alloc]initWithFrame:[UIScreen mainScreen].bounds];
    self.view.backgroundColor = [UIColor redColor];
}
  • loadView调用时机:第一次使用控制器的View的时候调用。

  • 注意:不要调用[super loadView]方法,你调用了super,还不如不重写

  • 注意:重写方法中如果没有利用自定义view对vc.view重新赋值,那么就不要去获取控制器的view取使用。会造成死循环,原因参照第一条self.view调用时机。如下图:

    三年经验之你忽略的小知识点_第5张图片
    迭代死循环.jpeg

12、iOS系统自带方法渲染图片

    [[UIImage new] imageWithRenderingMode:UIImageRenderingMode];

13、@synchronized互斥锁简介

  • 互斥锁格式:
@synchronized(锁对象){
  //需要锁定的代码
}
  • 注意:锁定1份代码只能用一把锁,即唯一的锁对象。用多把锁是无效的
  • 优点:能有效防止多线程抢夺资源造成的数据安全问题
  • 缺点:需要消耗大量的CPU资源
  • 使用前提:多条线程抢夺同一块资源,请且对资源有读写操作,且每个线程的顺序是对结果有影响的情况下使用互斥锁。

假如在面试过程中,问到线程同步的东西,这个互斥锁就是使用了线程同步技术。线程同步的意思就是多条线程在同一条线上执行(按顺序执行任务)

14、挺全面的atomic nonatomic 注解

  • atomic 的本意是指属性的存取方法是线程安全(thread safe).但不保证整个对象都是线程安全的。比如声明一个atomic修饰的NSMutableArray变量marray,此时self.marrayself.marray = otherarray都是线程安全的。但是使用[self.marray objectAtIndex:index]就不是线程安全的,需要配合其他线程安全技术来保证。
  • Atomic不能保证对象多线程的安全。所以Atomic 不能保证对象多线程的安全。它只是能保证你访问的时候给你返回一个完好无损的Value而已。举个例子:
    如果线程 A 调了 getter,与此同时线程 B 、线程 C 都调了 setter——那最后线程 A get 到的值,有3种可能:可能是 B、C set 之前原始的值,也可能是 B set 的值,也可能是 C set 的值。同时,最终这个属性的值,可能是 B set 的值,也有可能是 C set 的值。所以atomic可并不能保证对象的线程安全。
  • nonatomic:对应的就不考虑线程安全
  • 说明:atomic要比nonatomic性能慢很多。你想嘛,atomic每次访问Set、get方法之前都加一把锁,性能低很多

15、计算执行一段代码所消耗的时间

  • 第一种:
NSDate   *begin  = [NSDate date];
NSData  *data = [NSData dataWithContentsOfURL:url];
NSDate  *end = [NSDate date];
NSLog(@"%f",[end timeIntervalSinceDate:begin]);
  • 第二种
CFTimeInterval begin = CFAbsoluteTimeGetCurrent();
NSData  *data = [NSData dataWithContentsOfURL:url];
CFTimeInterval   end = CFAbsoluteTimeGetCurrent();
NSLog(@"%f",end - begin);

16、分离路径字符串的最后一段元素lastPathComponent

  • 代码示例
    NSString  *urlPath = @"https://www.jianshu.com/u/8bacdb9ecf00";
    NSString *fileName = [urlPath lastPathComponent];
    NSLog(@"%@",fileName); //打印结果:8bacdb9ecf00

解释: (来源于苹果官方文档注释)

  • The last path component of the receiver.
  • Path components are alphanumeric strings delineated by the path separator (slash “/”) or the beginning or end of the path string. Multiple path separators at the end of the string are stripped.
  • Note that this method only works with file paths (not, for example, string representations of URLs).
  • - lastPathComponent 是系统为NSString添加的PathExtensions中的一个方法,目的是获取一段路径字符串的最后一段内容。
  • 路径是一串字母数字、放在字符串的开头或者结尾路径分隔符(/)的组合。放在字符串最后的/大多数情况被省略掉。
    注意:这个方法仅仅对字符串类型的路径和链接,对于NSURL类型的需要先转换成NSString对象类型。
  • 举例说明lastPathComponent对多种字符串的剪裁效果
Receiver’s String Value String Returned
/tmp/scratch.tiff scratch.tiff
/tmp/scratch scratch”
/tmp/ tmp
scratch/// scratch
/ /

17、部分系统宏说明

  • 1、__has_feature:某些特性验证
  • 2、__OBJC__:

#ifdef __OBJC__
#import
#import
#endif

It means the objective C compiler is being used. So you can create hybrid header files that can be used when compiling objective C or C or C++.
或者This would be the case if you were developing an objective-c / cocoa application. In other words, if you were developing a C++ / carbon application, the OBJC symbol would not be defined and those objective-c dependant frameworks would not be imported.

  • 3、 NS_AVAILABLE_IOS(ios)

告诉在ios及以后的版本使用,更老版本不能使用;
类似:NS_AVAILABLE(_mac, _ios) 共用的方法

18、持续更新中....

如果您有什么疑问或者书写歧义,非常感激您能留言~

你可能感兴趣的:(三年经验之你忽略的小知识点)