我可以使用类别和运行时向 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, &strKey)
更改为[objc_getAssociatedObject(self, &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, &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”吗?的主要内容,如果未能解决你的问题,请参考以下文章