写在前面
最近遇到一个新的需求,要求在某个页面中添加一个collectionView,collectionView的高度随着数据源的长度来改变,从而达到改变父View的高度,如下图红框部分则为collectionView,整个视图布局在scrollview上,由collectionView的高度去撑父视图的高度。楼主试图通过监听collectionView的数据源长度来改变视图高度。
但我们知道,KVO监听的是指针变化,可变数组里加了个元素,这个数组的内容变了,但是指针没有变,所以不会调用KVO
首先,数组不能直接使用KVO使用监听。当我们想要使用KVO监听数组的状态时改变然后尽心操作时,我们需要进行一下几部。
1.KVO不能监听UIViewController中的数组。我们需要先创建一个模型,将数组添加值模型中。
@interface SelectedsArr : NSObject
@property (nonatomic, strong) NSMutableArray *selecteds;///<选中的选项集合
@end
2.建立观察者以及观察者对象
[self.selectedsArr addObserver:self forKeyPath:@"selecteds" options:NSKeyValueObservingOptionNew context:nil];
3.处理Key的变化
这里,很重要,当向模型中的可变数组添加新成员时,不能直接用[self.selectedsArr.selecteds addObject:]方法。而使用该用下面的方法
[self.selectedsArr mutableArrayValueForKey:@"selecteds"] addObject:]];
4.在下面的方法添加监听到变化后要执行的语句
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void *)context{
}
5.移除监听
[self removeObserver:self forKeyPath:@"selecteds"];
改进一下
我们只要每次都变更我们要监听数据的地址就好了。因此简化版操作如下,mediaUploadView是包含了collectionView的直接父视图,seleteImagesArray为collectionView的数据源
//1.建立观察者以及观察者对象
[self.mediaUploadView addObserver:self forKeyPath:@"seleteImagesArray" options:NSKeyValueObservingOptionNew context:nil];
//2.数组的增删方法(注意这里的写法,用mutableArrayValueForKey,这个不仅把元素加进去了, 而且还重新生成了一个可变数组来赋值给控制器属性的那个数组,这样就能被KVO检测到指针变化)
[[weakself mutableArrayValueForKey:@"seleteImagesArray"] addObject:weakself.addImageModel];
[[weakself mutableArrayValueForKey:@"seleteImagesArray"] removeLastObject];
[[weakself mutableArrayValueForKey:@"seleteImagesArray"] addObjectsFromArray:tempArray];
//3.处理Key的变化
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
NSInteger rows = ceilf(self.mediaUploadView.seleteImagesArray.count/3.0);
self.meadiaUploadViewHeight.constant = (ITEM_WIDTH_HEIGHT+20)*rows;
}
//4.最后一步也很重要,否则引起崩溃
- (void)dealloc {
[self.mediaUploadView removeObserver:self forKeyPath:@"seleteImagesArray" context:nil];
}