Object - C运行时应用(二)—— 使用对象关联为分类增加属性(每个对象的属性互不干扰)

本文介绍了如何利用Objective-C的运行时特性,通过对象关联为分类添加属性,使得每个对象的属性互不干扰。详细讲解了objc_setAssociatedObject和objc_getAssociatedObject的用法,并给出示例代码,展示了如何为NSString添加name和books属性,以及在UIAlertView中使用关联对象存放自定义处理逻辑。

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

一、对象的关联方法有
1、 void objc_setAssociatedObject(id object, const void *key, id value,objc_AssociationPolicy policy) ,关联对象(将值value与对象object关联起来)
参数key:将来可以通过key取出这个存储的值
参数policy:存储策略(assign、copy、retain)
2、 id objc_getAssociatedObject(id object, const void *key) ,利用参数key将对象中存储的对应值取出

二、利用分类为每个对象添加属性(可作为对象的标签或存储信息)
声明代码:
@interface NSObject (CX)
/**
 *  为每一个对象添加一个name属性
 */
@property (nonatomic,copy) NSString *name;
/**
 *  为每个对象添加一个数组属性
 */
@property (nonatomic,strong) NSArray *books;
@end
实现代码:
// 用一个字节来存储key值,设置为静态私有变量,避免外界修改
static char nameKey;
- (void)setName:(NSString *)name
{
    // 将某个值与某个对象关联起来,将某个值存储到某个对象中
    objc_setAssociatedObject(self, &nameKey, name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

- (NSString *)name
{
     return objc_getAssociatedObject(self, &nameKey);
}

static char booksKey;
- (void)setBooks:(NSArray *)books
{
    objc_setAssociatedObject(self, &booksKey, books, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (NSArray *)books
{
    return objc_getAssociatedObject(self, &booksKey);
}

测试:
NSString *str = @"xx";
    str.name = @"oo";
    str.books = @[@"xxoo",@"ooxx"];
    
    NSLog(@"%@,%@",str.name,str.books);

打印如下:



这样连字符串页具备了一个数组属性。

三、对象关联的另一种作用:在既有类中使用关联对象存放自定义数据
     在ios开发时经常会用到UIAlertView类,该类提供了一种视图向用户展示警告信息。该类通过代理协议来处理用户的点击事件,但由于使用了代理就必须把创建警告的视图和处理按钮动作的代码分开,比如说
- (void)showAlertView
{
    UIAlertView *alert =  [[UIAlertView alloc] initWithTitle:@"UIAlertView" message:@"what do you do" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"sure", nil];
    [alert show];
}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (0 == buttonIndex) {
        NSLog(@"%@",@"cancel");
    }
    else if (1 == buttonIndex)
    {
        NSLog(@"%@",@"sure");
    }
}


如果想在同一个类里处理多个警告信息视图,我们必须在代理方法中比较点击按钮的索引,并借此编写相应的逻辑,如果能够在创建警告视图的时候直接把处理逻辑的代码写好那将会很便于阅读,这时可以考虑用关联对象,设定一个与alert对象关联的代码块,等到执行代理方法时再将其读取出来

- (void)viewDidLoad {
    [super viewDidLoad];
    [self showAlertView];
}
static char myAlerViewKey;
- (void)showAlertView
{
    UIAlertView *alert =  [[UIAlertView alloc] initWithTitle:@"UIAlertView" message:@"what do you do" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"sure", nil];
    
    // 将逻辑定义到代码块里面
    void(^block)(NSInteger) = ^(NSInteger buttonIndex) {
        if (buttonIndex == 0)
        {
            NSLog(@"%ld",buttonIndex);
        }
        else
        {
            NSLog(@"%ld",buttonIndex);
        }
    };
    
    // 对象关联
    objc_setAssociatedObject(alert, &myAlerViewKey, block, OBJC_ASSOCIATION_COPY);
    
    [alert show];
}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    void(^block)(NSInteger) = objc_getAssociatedObject(alertView, &myAlerViewKey);
    block(buttonIndex);
}

执行效果如下:




### 锁条带化的概念 锁条带化(Lock Striping)是一种通过减少竞争来提高并发性能的技术。其基本思想是将单个全局锁拆分为多个独立的锁,从而允许多个线程在同一间内操作不同的数据部分而不发生冲突。这种方法可以显著降低因争用单一锁而导致的瓶颈问题。 在多线程环境中,当多个线程试图访问共享资源使用单一锁可能会导致严重的性能下降,因为只有一个线程能够持有锁并执行操作,而其他线程则被迫等待。为了缓解这一问题,可以通过引入多个互不干扰的锁来保护不同分区的数据结构[^1]。 例如,在Java中的`ConcurrentHashMap`实现了类似的机制:它不是简单地在整个哈希表上加一把大锁,而是采用了分段锁技术——即把整个哈希表划分为若干个小的部分(称为桶),每个桶都有自己的锁。这样做的好处是可以让多个线程同修改属于不同桶的内容,而不会相互影响[^4]。 ### 实现方式 以下是实现锁条带化的一种常见模式: #### 使用数组存储多个锁 定义一个固定大小的锁数组,其中每一个元素代表一个单独的对象锁。对于任何给定的操作请求,计算出应该关联到哪个具体的锁实例上去控制对该子集资源的访问权限。 ```java class LockStripedExample { private final Object[] locks; public LockStripedExample(int numLocks) { locks = new Object[numLocks]; for (int i=0; i<numLocks; ++i){ locks[i]=new Object(); } } // 假设key是我们要锁定的目标键值 public void performOperation(Object key, Runnable operation) { int lockIndex = Math.abs(key.hashCode()) % locks.length; synchronized(locks[lockIndex]) { operation.run(); // 执行具体业务逻辑 } } } ``` 上述代码展示了如何创建一定数量的锁,并依据输入参数决定哪一个锁会被用来同步特定的任务处理过程。这里的关键在于选取合适的散列函数以及合理的锁数目设置,以便均匀分布负载并最小化碰撞几率[^3]。 另外需要注意的是,虽然增加了更多的细粒度锁能提升吞吐量,但如果划分得过细,则可能带来额外开销甚至适得其反;因此实际应用过程中需权衡利弊做出最佳决策[^2]。 ### 总结 综上所述,锁条带化提供了一种有效手段去优化高并发场景下的程序表现,特别是在那些存在大量读写需求的应用场合尤为适用。然而,设计良好的锁策略还需要考虑诸如假阳性率、上下文切换成本等因素的影响。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值