源码

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

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

123.JPEG

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中设置,一劳永逸。配置好就不用代码了
参数配置参考第三条。

1.png

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];
}

如果shopWithName是1写法 ,编译器就会报错,是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属性
最终没有找到则报错

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、模拟器 模拟内存警告

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

//leftCapWidth代表左端盖宽度,topCapHeight代表顶端盖高度
- (UIImage *)stretchableImageWithLeftCapWidth:(NSInteger)leftCapWidth topCapHeight:(NSInteger)topCapHeight;

0

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

1.png

samulator.png

11、自定义控制器View

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

//leftCapWidth代表左端盖宽度,topCapHeight代表顶端盖高度
- (UIImage *)stretchableImageWithLeftCapWidth:(NSInteger)leftCapWidth topCapHeight:(NSInteger)topCapHeight;

1

  • loadView调用时机:第一次使用控制器的View的时候调用。

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

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

123.JPEG

迭代死循环.jpeg

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

//leftCapWidth代表左端盖宽度,topCapHeight代表顶端盖高度
- (UIImage *)stretchableImageWithLeftCapWidth:(NSInteger)leftCapWidth topCapHeight:(NSInteger)topCapHeight;

2

13、@synchronized互斥锁简介

  • 互斥锁格式:

//leftCapWidth代表左端盖宽度,topCapHeight代表顶端盖高度
- (UIImage *)stretchableImageWithLeftCapWidth:(NSInteger)leftCapWidth topCapHeight:(NSInteger)topCapHeight;

3

  • 注意:锁定1份代码只能用一把锁,即唯一的锁对象。用多把锁是无效的

  • 优点:能有效防止多线程抢夺资源造成的数据安全问题

  • 缺点:需要消耗大量的CPU资源

  • 使用前提:多条线程抢夺同一块资源,请且对资源有读写操作,且每个线程的顺序是对结果有影响的情况下使用互斥锁。

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

14、挺全面的atomic    nonatomic 注解

  • atomic 的本意是指属性的存取方法是线程安全(thread safe).但不保证整个对象都是线程安全的。比如声明一个atomic修饰的NSMutableArray变量marray,此时self.marray和self.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、计算执行一段代码所消耗的时间

  • 第一种:

//leftCapWidth代表左端盖宽度,topCapHeight代表顶端盖高度
- (UIImage *)stretchableImageWithLeftCapWidth:(NSInteger)leftCapWidth topCapHeight:(NSInteger)topCapHeight;

4

  • 第二种

//leftCapWidth代表左端盖宽度,topCapHeight代表顶端盖高度
- (UIImage *)stretchableImageWithLeftCapWidth:(NSInteger)leftCapWidth topCapHeight:(NSInteger)topCapHeight;

5

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

  • 代码示例

//leftCapWidth代表左端盖宽度,topCapHeight代表顶端盖高度
- (UIImage *)stretchableImageWithLeftCapWidth:(NSInteger)leftCapWidth topCapHeight:(NSInteger)topCapHeight;

6

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

  • 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 ValueString Returned
/tmp/scratch.tiffscratch.tiff
/tmp/scratchscratch”
/tmp/tmp
scratch///scratch
//

作者:SmallWhiteMouse

链接:https://www.jianshu.com/p/3f66835bb8b1

(0)

本文由 投稿者 创作,文章地址:https://blog.isoyu.com/archives/sannianjingyanzhinihuluedexiaozhishidian.html
采用知识共享署名4.0 国际许可协议进行许可。除注明转载/出处外,均为本站原创或翻译,转载前请务必署名。最后编辑时间为:5 月 24, 2018 at 01:31 上午

热评文章

发表回复

[必填]

我是人?

提交后请等待三秒以免造成未提交成功和重复