【iOS - 月总结】开发中遇到的小知识点(2020.04)
1.实时监听数组的变化
前几天有一个需求在列表编辑界面需要实时根据选择的数据进行下面各种按钮不同状态的切换,这就需要我们实时监听数组的变化。
// 第一步 添加监听
//监听selectDataArray数量是否发生变化
[self addObserver:self forKeyPath:@"selectDataArray" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
// 第二步 在观察者方法中监听
#pragma mark - 观察者监听 选中数组变化
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:@"selectDataArray"]) {
// 做你想做的操作
}
}
// 做到这里你会发现直接addObject或者removeObject不起作用。所以我们应该这样添加和修改数组中的数据
[[self mutableArrayValueForKey:@"selectDataArray"] addObject:indexPathM];
[[self mutableArrayValueForKey:@"selectDataArray"] removeAllObjects];
2.NSArray和NSMutableArray的赋值
在开发中,我们也经常遇到这样的问题,在别的类中声明了一个可变数组的属性,然后在赋值的时候我们把不可变数组赋值过去。一般来说这样会有警告,我们很有可能就忽略了。但是这样会有一个问题,NSArray赋值给NSMutableArray那么数组就会变成不可变数组,我们对数组进行操作的时候就会崩溃。同理NSMutableArray赋值给NSArray那么数组就会变成可变数组。这个问题也是面试中会问到的一个问题,应该多多注意
3.去除警告
已有详细博客,请参考
4.oc中参数可为空或不可为空的方法和block作为参数可为空获不可为空
//参数可为空
- (void)testMethod2:(NSString *_nullable)str;
//参数不可为空
- (void)testMethod2:(NSString *_Nonnull)str;
//调用该方法时block可赋值为空[self testMethod:nil];
- (void)testMethod:(void(^ _nullable)(void))handle;
//调用该方法时block不可以可赋值为空[self testMethod:nil];
- (void)testMethod:(void(^ _Nonnull)(void))handle;
5.xib创建的Controller的View初始值就是(600,600)
xib创建的Controller的View初始值就是(600,600), 你可以在viewWillAppear方法中添加创建的HUD, 或者是在viewDidLoad中设置
// View的Frame:
self.view.frame = [UIScreen mainScreen].bounds;
6.取模型数组内属性组成新的数组
NSArray *array = @[@{
@"name":@"zhang",
@"idStr":@"11"
},
@{
@"name":@"li",
@"idStr":@"12"
},
@{
@"name":@"wang",
@"idStr":@"13"
},
@{
@"name":@"zhao",
@"idStr":@"14"
}
];
NSArray *newArray = [array mutableArrayValueForKeyPath:@"name"];
// 结果
/*
Printing description of newArray:
<NSKeyValueSlowMutableArray 0x600002a415c0>(
zhang,
li,
wang,
zhao
)
*/
这样会得到name字段属性值组成的数组
类似的还有MJExtension里面的方法,这里面更加完善。他可以设置一些忽略值,在大数据字典中我们可以直接忽略一些然后取数组,不必一个个输入所有的选值
/**
* 通过模型数组来创建一个字典数组
* @param objectArray 模型数组
* @return 字典数组
*/
+ (NSMutableArray*)mj_keyValuesArrayWithObjectArray:(NSArray *)objectArray;
+ (NSMutableArray*)mj_keyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys;
+ (NSMutableArray*)mj_keyValuesArrayWithObjectArray:(NSArray *)objectArray ignoredKeys:(NSArray *)ignoredKeys;
7.解决Collection <__NSArrayM: 0xb550c30> was mutated while being enumerated.-
*** Terminating app due to uncaught exception ‘NSGenericException’, reason: ‘*** Collection <__NSArrayM: 0xb550c30> was mutated while being enumerated.’
当程序出现这个提示的时候,是因为你一边便利数组,又同时修改这个数组里面的内容,导致崩溃,网上常见的方法如下:
NSMutableArray * arrayTemp = xxx;
NSArray * array = [NSArray arrayWithArray: arrayTemp];
for (NSDictionary * dic in array) {
if (condition){
[arrayTemp removeObject:dic];
}
}
这种方法就是在定义一个一模一样的数组,便利数组A然后操作数组B。
NSMutableArray *tempArray = [[NSMutableArray alloc]initWithObjects:@"12",@"23",@"34",@"45",@"56", nil];
[tempArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if ([obj isEqualToString:@"34"]) {
*stop = YES;
if (*stop == YES) {
[tempArray replaceObjectAtIndex:idx withObject:@"3333333"];
}
}
if (*stop) {
NSLog(@"array is %@",tempArray);
}
}];
利用block来操作,根据查阅资料,发现block便利比for便利快20%左右,这个的原理是这样的:
找到符合的条件之后,暂停遍历,然后修改数组的内容