echo.hu

tips笔记总结

tableViewCell里面图片圆角离屏渲染解决方案

撰写一个UIImageView的分类,分类仿写SDWebImage里面加载图片的方法把图片加载下来后,通过另外一个UIImage分类用贝塞尔曲线切圆角处理,然后根据和SDWebImage的逻辑一样保留圆角图片缓存,清除原有非圆角图片缓存

字典深浅拷贝

1
2
3
4
NSMutableDictionary *myDic=[@{@"22":@"33"} mutableCopy];
NSMutableDictionary *otherDic=myDic;
//NSMutableDictionary *otherDic=[myDic mutableCopy];
[otherDic setValue:@"33" forKey:@"44"];

改变可变字典otherDic时myDic也会同时改变,所以使用可变字典时要让两个字典独立需要注意使用mutableCopy.

NSMutableSet里面尽量少用不可变对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
NSMutableSet *set=[NSMutableSet new];
NSMutableArray *arrayA=[@[@1,@2] mutableCopy];
[set addObject:arrayA];
NSLog(@"set=%@",set);
NSMutableArray *arrayB=[@[@1,@2] mutableCopy];
[set addObject:arrayB];
NSLog(@"set=%@",set);
NSMutableArray *arrayC=[@[@1] mutableCopy];
//[set addObject:[arrayC copy]];
[set addObject:arrayC];
NSLog(@"set=%@",set);
[arrayC addObject:@2];
NSLog(@"set=%@",set);
NSSet *setB=[set copy];
NSLog(@"setB=%@",setB);

如上面代码所示使用可变对象时会出现里面有相同元素的情况,而当重新将其浅拷贝的时候则里面内容会转回不可变对象,所以才会恢复正常.

打印输出黑科技

重写实体类如下方法然后就可以直接通过NSLog(@”cls=%@”,cls)输出定制的内容

1
2
3
4
5
6
7
8
9
- (NSString *)description {
return [NSString stringWithFormat:@"<%@: %p, %@", [self class],self,@{@"youName":_youName, @"myName":_myName}];
}
//debug环境下
- (NSString *)debugDescription {
// return [NSString stringWithFormat:@"<%@: %p, %@", [self class],self,@{@"youName":_youName,
// @"myName":_myName}];
return [self description];
}

基于运行期OC的Get方法和Set方法的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//动态方法解析函数
+(BOOL)resolveInstanceMethod:(SEL)sel{
NSString *selectorString=NSStringFromSelector(sel);
if ([selectorString hasPrefix:@"set"]) {
class_addMethod(self, sel, (IMP)autoDictionarySetter, "v@:@");
}else{
class_addMethod(self, sel, (IMP)autoDictionaryGetter, "@@:");
}
return YES;
}
id autoDictionaryGetter(id self,SEL _cmd){
EOCAutoDictionary *typeSelf=(EOCAutoDictionary *)self;
NSMutableDictionary *backingStore=typeSelf.backingStore;
NSString *key=NSStringFromSelector(_cmd);
return [backingStore objectForKey:key];
}
void autoDictionarySetter(id self,SEL _cmd,id value){
EOCAutoDictionary *typeSelf=(EOCAutoDictionary *)self;
NSMutableDictionary *backingStore=typeSelf.backingStore;
NSString *selectorString=NSStringFromSelector(_cmd);
NSMutableString *key=[selectorString mutableCopy];
[key deleteCharactersInRange:NSMakeRange(key.length - 1, 1)];
[key deleteCharactersInRange:NSMakeRange(0, 3)];
NSString *lowercaseFirstChar=[[key substringToIndex:1] lowercaseString];
[key replaceCharactersInRange:NSMakeRange(0, 1) withString:lowercaseFirstChar];
if (value) {
[backingStore setObject:value forKey:key];
}else{
[backingStore removeObjectForKey:key];
}
}

当对象在收到无法解读的消息后,首先调用其所属类的下列类方法

+(BOOL)resolveInstanceMethod:(SEL)sel

所以可以利用其消息转发机制的这个函数来重新get,set方法,完整代码链接.

valueForKeyPath使用总结

取数组里面数字的最大值

1
2
3
NSArray * array = [NSArray arrayWithObjects:@0,@50,@9, nil];
NSInteger max = [[array valueForKeyPath:@"@max.floatValue"] integerValue];
NSLog(@"%ld",(long)max);

去数组里面数字的平均值

1
2
3
NSArray *arr = @[@0,@10,@40];
CGFloat avg = [[arr valueForKeyPath:@"@avg.floatValue"] floatValue];
NSLog(@"---%f",avg);

剔除重复数据

1
2
NSArray *array1 = @[@"name", @"w", @"aa", @"jimsa", @"aa"];
NSLog(@"%@", [array1 valueForKeyPath:@"@distinctUnionOfObjects.self"]);

同样可以嵌套使用,先剔除name对应值的重复数据再取值

1
2
3
4
5
6
NSArray *array2 = @[@{@"name" : @"cookeee",@"code" : @1},
@{@"name": @"jim",@"code" : @2},
@{@"name": @"jim",@"code" : @1},
@{@"name": @"jbos",@"code" : @1}];
NSLog(@"%@", [array2 valueForKeyPath:@"@distinctUnionOfObjects.name"]);

执行数组里面的特定属性处理完成后返回一个数组

1
2
NSArray *arrayList = @[@"name", @"w", @"aa", @"jimsa"];
NSLog(@"%@", [arrayList valueForKeyPath:@"uppercaseString"]);

求和、求平均值、最大值、最小值

1
2
3
4
NSNumber *sum = [array valueForKeyPath:@"@sum.floatValue"];
NSNumber *avg = [array valueForKeyPath:@"@avg.floatValue"];
NSNumber *max = [array valueForKeyPath:@"@max.floatValue"];
NSNumber *min = [array valueForKeyPath:@"@min.floatValue"];

KVO

添加kvo通知

1
[self.dogName addObserver:self forKeyPath:@"masterName" options:NSKeyValueObservingOptionNew context:nil];

在实体类中设置通知

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
+(BOOL)automaticallyNotifiesObserversForKey:(NSString *)key{
//自动通知
if ([key isEqualToString:@"dogNameStr"]) {
return YES;
}
//手动通知
if ([key isEqualToString:@"masterName"]) {
return NO;
}
return [super automaticallyNotifiesObserversForKey:key];
}
-(void)setMasterName:(NSString *)pmasterName{
//设置手动通知
[self willChangeValueForKey:@"masterName"];
@synchronized(self) {
_masterName=pmasterName;
}
[self didChangeValueForKey:@"masterName"];
}

然后在需要通知的界面接收通知

1
2
3
4
5
6
7
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
if ([object isKindOfClass:[clsDogName class]]) {
if ([keyPath isEqualToString:@"dogNameStr"]) {
self.lbDogName.text=[change objectForKey:NSKeyValueChangeNewKey];
}
}
}

主要用于比如在一个界面修改了用户的资料,按保存同时能实时的同步修改用户的资料这样类似的场景.

NSPredicate谓词筛选器

把时间小于2016-10-04的时候剔除,重复时间也剔除,然后排序,其他用法在这里

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
-(void)loadPredicateTest{
//把DATETIME相同时间合并排序,然后再过滤掉2016-10-04号前的日期
NSArray *list=@[@{@"DATETIME":@"2016-10-01"},
@{@"DATETIME":@"2016-10-06"},
@{@"DATETIME":@"2016-10-05"},
@{@"DATETIME":@"2016-10-04"},
@{@"DATETIME":@"2016-10-05"},
@{@"DATETIME":@"2016-10-03"},
@{@"DATETIME":@"2016-10-02"},
@{@"DATETIME":@"2016-10-02"}];
//把日期过滤
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"DATETIME >= '2016-10-04'"];//创建谓词筛选器
NSArray *filtrationList = [list filteredArrayUsingPredicate:predicate];
//剔除重复数据
filtrationList=[filtrationList valueForKeyPath:@"@distinctUnionOfObjects.DATETIME"];
//排序
NSArray *sortSetArray = [filtrationList sortedArrayUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:nil ascending:NO]]];
NSLog(@"%@",sortSetArray);
}