OC中 子控件 传递方法几种方案

本文详细介绍了iOS开发中数据传递的常见方法,包括一对一方案的代理、Block和Runtime转发,一对多方案的NSNotification和KVO,以及全局方法的单例模式。在实际项目中,根据需求选择合适的方案能确保程序的稳定性和灵活性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:最近刚刚结束一个项目,身心疲惫,还是得写写项目中用到的一些常见数据传递方案。

一、一对一方案

001 代理

通过一个子控件定义几个协议函数在父控件的 @interface ()<协议> 继承该代理,在父控件中实现这些函数,最经典就是UITableView的实现方式。要注意某些代理是否是required关键词声明了required关键词就得必须实现否则会报错

002 block

子控件声明block函数,在父控件中,子控件通过setBlock方法可以将子控件的参数传给父控件来进行使用,但是block使用特别要注意循环引用的风险,解决方案就是使用weakSelf关键字,这样就可以避免循环引用。子控件可以通过判断该block方法是否为空再执行该block方法。如果block中要进行UI刷新操作就得在主线程中进行操作,否则数据不会及时在UI中刷新出来。

#define WS(weakSelf)  __weak __typeof(&*self)weakSelf = self;

003 runtime 设置forward关键字 将子控件执行的某方法通过runtime的动态解析将方法具体执行的对象只想父控件。

- (id)forwarder{
    return objc_getAssociatedObject(self, @selector(forwarder));
}

- (void)setForwarder:(id)forwarder{
    objc_setAssociatedObject(self, @selector(forwarder), forwarder, OBJC_ASSOCIATION_ASSIGN);
}

- (id)forwardingTargetForSelector:(SEL)aSelector{
    
    return self.forwarder;
}

二、一对多方案

001 NSNotification通知 

可以举个场景:一个父控件中有几个子控件。子控件1操作会让子控件2进行数据刷新操作,具体的场景就是购物车 待付款栏目的商品付款完成之后,会在待收货栏目显示出来,

 [[NSNotificationCenter defaultCenter] postNotificationName:HomeListRefreshNotificationName object:nil];

- (void)registerNotifications{
    
    [[NSNotificationCenter  defaultCenter] addObserver:self selector:@selector(homeVCDidAppear) name:HomeListRefreshNotificationName object:nil];
}

- (void)removeNotifications{
    [[NSNotificationCenter  defaultCenter] removeObserver:self name:HomeListRefreshNotificationName object:nil];
}

002 KVO 监听某个控件状态变化


#pragma mark - KVO
- (void)zy_addObserver
{
    [self addObserver:self forKeyPath:@"attributedText" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) context:nil];
}
- (void)zy_removeObserver
{
    id info = self.observationInfo;
    NSString * key = @"attributedText";
    NSArray *array = [info valueForKey:@"_observances"];
    for (id objc in array) {
        id Properties = [objc valueForKeyPath:@"_property"];
        NSString *keyPath = [Properties valueForKeyPath:@"_keyPath"];
        if ([key isEqualToString:keyPath]) {
            [self removeObserver:self forKeyPath:@"attributedText" context:nil];
        }
    }
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"attributedText"]) {
        if (self.isTapAction) {
            if (![change[NSKeyValueChangeNewKey] isEqual: change[NSKeyValueChangeOldKey]]) {
            }
        }
    }
}

三、全局方法

001 单例模式

例如商品筛选页面提交的参数和具体刷新的页面不在同一个模块,这样就得用单例模式将筛选的参数,保留起来在该刷新的页面拿到该筛选的参数进行网络接口请求

#define SingletonH(name)    + (instancetype)shared##name

#if __has_feature(objc_arc)

#define SingletonM(name)                            \
\
static id instance;                                 \
\
+ (instancetype)shared##name                        \
{                                                   \
static dispatch_once_t onceToken;               \
dispatch_once(&onceToken, ^{                    \
instance = [[self alloc] init];             \
});                                             \
\
return instance;                                \
}                                                   \
\
+ (instancetype)allocWithZone:(NSZone *)zone        \
{                                                   \
static dispatch_once_t onceToken;               \
dispatch_once(&onceToken, ^{                    \
instance = [super allocWithZone:zone];      \
});                                             \
return instance;                                \
}                                                   \
\
- (id)copyWithZone:(NSZone *)zone                   \
{                                                   \
return self;                                    \
}

#else
#define SingletonM(name)                            \
\
static id instance;                                 \
\
+ (instancetype)shared##name                        \
{                                                   \
static dispatch_once_t onceToken;               \
dispatch_once(&onceToken, ^{                    \
instance = [[self alloc] init];             \
});                                             \
\
return instance;                                \
}                                                   \
\
+ (instancetype)allocWithZone:(NSZone *)zone        \
{                                                   \
static dispatch_once_t onceToken;               \
dispatch_once(&onceToken, ^{                    \
instance = [super allocWithZone:zone];      \
});                                             \
return instance;                                \
}                                                   \
\
- (id)copyWithZone:(NSZone *)zone                   \
{                                                   \
return self;                                    \
}                                                   \
\
- (instancetype)autorelease                         \
{                                                   \
return self;                                    \
}                                                   \
\
- (instancetype)retain                              \
{                                                   \
return self;                                    \
}                                                   \
\
- (NSUInteger)retainCount                           \
{                                                   \
return 1;                                       \
}                                                   \
\
- (oneway void)release                              \
{                                                   \
\
}
#endif

四、总结

在项目中上述方案适用不同的需求场景,具体问题具体分析,多样化操作实现需求,可以让程序更加健壮。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值