我可以使用类别和运行时向 UIScrollView 添加 BOOL 类型属性“isScrolling”吗?

Posted

技术标签:

【中文标题】我可以使用类别和运行时向 UIScrollView 添加 BOOL 类型属性“isScrolling”吗?【英文标题】:Can I use category and runtime to add a BOOL type property "isScrolling" to UIScrollView? 【发布时间】:2017-06-20 04:32:48 【问题描述】:

我以前在UIButton 中添加了一个NSString *type 属性,但是今天我想在UIScrollView 中添加一个BOOL 类型属性isScrolling 来指示scrollView 是否以相同的方式滚动,但是显示有问题,这是我的代码:

#import <UIKit/UIKit.h>

@interface UIScrollView (Util)

@property (nonatomic,assign) BOOL isScrolling;

@end




#import <objc/objc-runtime.h>

@interface UIScrollView ()<UIScrollViewDelegate>

@end

@implementation UIScrollView (Util)

static void *strKey = &strKey;

- (void)setIsScrolling:(BOOL)isScrolling 
objc_setAssociatedObject(self, & strKey, isScrolling,    OBJC_ASSOCIATION_ASSIGN);


- (BOOL)isScrolling
    return objc_getAssociatedObject(self, &strKey);


- (void)scrollViewDidScroll:(UIScrollView *)scrollView
    self.isScrolling = YES;


- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
    self.isScrolling = NO;


@end

错误是:

有没有办法处理这些错误,我们可以使用类别和运行时来实现在UIScrollView 中添加BOOL 属性以指示scrollView 是否正在滚动的目标?

希望有人能给我一些建议,非常感谢。

【问题讨论】:

邮政编码原样。请不要截图。 objc_getAssociatedObject 用于对象类型。 BOOL 不是对象类型。这就是你得到错误的原因 @LalKrishna 是的,我已经编辑过了。 【参考方案1】:

关联对象 必须就是这样一个对象,因此非对象 BOOL 类型的值将不起作用,除非包装为对象。幸运的是,这很容易:

在对objc_setAssociatedObject 的调用中,将isScrolling 更改为@(isScrolling),并将OBJC_ASSOCIATION_ASSIGN 更改为OBJC_ASSOCIATION_RETAIN_NONATOMIC。这将创建并传递一个 NSNumber 对象,第二个更改请求将此对象的生命周期绑定到第一个参数 self 的生命周期。 在isScrolling 中将objc_getAssociatedObject(self, &amp;strKey) 更改为[objc_getAssociatedObject(self, &amp;strKey) boolValue]。这将从存储的NSNumber 对象中提取BOOL 值。

HTH

【讨论】:

【参考方案2】:

试试这个:

尝试将布尔值转换为 nsnumber。

  -(void)setIsScrolling:(BOOL)isScrolling
        objc_setAssociatedObject(self, & strkey), [NSNumber numberWithBool:isScrolling], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    

【讨论】:

【参考方案3】:

由于错误显示 BOOL 到 id 的隐式转换,您需要发送一个对象而不是原始类型。

objc_setAssociatedObject 的方法签名是

/** 
 * Sets an associated value for a given object using a given key and association policy.
 * 
 * @param object The source object for the association.
 * @param key The key for the association.
 * @param value The value to associate with the key key for object. Pass nil to clear an existing association.
 * @param policy The policy for the association. For possible values, see “Associative Object Behaviors.”
 * 
 * @see objc_setAssociatedObject
 * @see objc_removeAssociatedObjects
 */

OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
    OBJC_AVAILABLE(10.6, 3.1, 9.0, 1.0);

上面可以看到value应该是object。

更改您的代码 @property (assign, nonatomic) BOOL isScrolling;@property (strong, nonatomic) NSNumber *scrolling;

在你的情况下将OBJC_ASSOCIATION_ASSIGN 更改为OBJC_ASSOCIATION_RETAIN_NONATOMIC objc_setAssociatedObject(self, &amp;strkey, scrolling, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

并使用[_scrolling boolValue] 进行检查。

【讨论】:

是的,你是对的。但是我们可以处理类别中的 UIScrollView 委托,以便我们可以将值设置为“滚动”属性。我刚刚尝试过,它是无效的。你有任何想法? 您可以覆盖类别中的委托方法。我可以尝试帮助您发布您的代码。【参考方案4】:

您不能将原始数据类型设置为AssociatedObject,它是一个对象。保存数据时将bool 转换为NSNumber。在读取数据时将NSNumber 转换为bool

OBJC_ASSOCIATION_ASSIGN - 指定对关联对象的弱引用。 OBJC_ASSOCIATION_RETAIN_NONATOMIC - 指定对关联对象的强引用,并且关联不是原子的。

.h 文件:

#import <UIKit/UIKit.h>

@interface UIScrollView (ScrollViewCategory)

@property (nonatomic, strong)NSNumber *isScrolling;

@end

.m 文件

@interface UIScrollView ()

@end

#import <objc/runtime.h>

@implementation UIScrollView (ScrollViewCategory)

@dynamic isScrolling;

- (void)setAssociatedObject:(id)object 
    objc_setAssociatedObject(self, @selector(associatedObject), object, OBJC_ASSOCIATION_RETAIN_NONATOMIC);


- (id)associatedObject 
    return objc_getAssociatedObject(self, @selector(associatedObject));

【讨论】:

以上是关于我可以使用类别和运行时向 UIScrollView 添加 BOOL 类型属性“isScrolling”吗?的主要内容,如果未能解决你的问题,请参考以下文章

UIScrollView 内的 UITableViewController 与水平分页

如何在 C# 运行时向类添加属性?

链接 2 UIScrollView 与不同的分页大小

在运行时向兔子侦听器动态添加队列

在运行时向 Gridview 动态添加行

是否可以在处理时向Go频道添加项目?