现在一般的App都有很多底部弹出框,比如下面这样的
或者这样的
上面两个截图中的控件是我在工程中使用频率较高的两个自定义控件,一个用来展示多选框的sheetView
,一个用来展示分享面板的shareView
,都是可以全局使用的
sheetView
使用方法为
NSArray *passports = @[@"无",@"有",@"过期"];
ZGQActionSheetView *sheetView = [[ZGQActionSheetView alloc] initWithOptions:passports Completion:^(ZGQActionSheetView *sheetView, NSInteger index) {
//doSomething
} cancel:^{
}];
[sheetView show];
其实是将一个tableView
放到了[UIApplication sharedApplication].keyWindow
上,在init
方法里实现
由外部调用,每次都可以传入不同的数组,来改变选项的内容
而shareView
是自定义的分享面板,底层封装了友盟的分享模块,起初是创建了一个shareManager
来统一管理所有页面的分享动作
+ (instancetype) manager {
static ZCQShareManager *manager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
manager = [[ZCQShareManager alloc] init];
});
return manager;
}
shareManager
持有shareView
并在单例初始化时将shareView
add 到[UIApplication sharedApplication].keyWindow
上
分享操作是这样
ZCQShareUrlModel *model = [[ZCQShareUrlModel alloc]initWithTitle:shareName description:shareDescription image:shareLogoUrl];
model.shareUrl = shareUrl;
[[ZCQShareManager manager] openShareViewWithModel:model completion:^(ZCQShareType type) {
//分享回调
} result:^(NSError *error, ZCQShareType type) {
//分享结果回调
} cancelBlock:^{
//取消分享回调
}];
起初分享面板默认展示的是所有的分享渠道,后来接到产品的需求,要求某些页面自定义分享渠道(比如某些页面不允许分享到App内部的消息),但是shareManager
是一个单例,分享面板被单例持有,我如果修改了面板上的UI(比如去掉了消息按钮),所有的地方调用都会没有,这时候我就想到能不能像想sheetView
一样,每次都生成一个新对象,不用单例,于是我为了方便(不修改调用的方法)将代码改成了这样
+ (instancetype) manager {
ZCQShareManager *manager = [[ZCQShareManager alloc] init];;
return manager;
}
我以为每次生成一个新的对象,不就可以每次在调用之前自定义都分享给哪几个渠道了?
但是我将代码修改之后分享面板却怎么也调不出来了
其实这里就犯了一个错误,因为对内存管理还是不理解,sheetView
之所以可以每次生成一个新对象并调出来是因为它生成后是直接添加到keyWindow
上的,由于keyWindow
是全局存在的 所以keyWindow
持有了sheetVie
它就能显示出来。
而shareView
虽然是添加到了keyWindow
上,但他是被shareManager
持有的,shareManager
如果是一个单例的话,没有问题,但如果它不是一个单例而是变成了一个局部变量,在调用[ZCQShareManager manager]
的地方 这个对象一旦了作用域就销毁了,shareManager
销毁了,那么它持有的shareView
也自然就没了,就无法调出来
当然解决的办法很简单,就是直接让keyWindow
持有shareView
,不再通过shareManager
去持有它,不过这样改动的代码就比较多了。
网友评论