繁体   English   中英

Objective-C运行时更改初始化对象的只读属性

[英]Objective-C Runtime changing readonly property of initialized object

我有一个问题,我不能改变第三方库中的frame.size.width。 找不到任何改变宽度的正常解决方案,所以我决定执行objc / runtime

我有ViewController及其属性DTAttributedTextView * v。

@interface DTAttributedTextView : UIScrollView
{
 // ivars needed by subclasses
 DTAttributedTextContentView *_attributedTextContentView;
}

 @property (nonatomic, strong) NSAttributedString *attributedString;
 @property (nonatomic, DT_WEAK_PROPERTY) IBOutlet 
 id<DTAttributedTextContentViewDelegate> textDelegate;
 @property (nonatomic, strong) IBOutlet UIView *backgroundView;
 ....
@end

v得到@property (..,readonly) DTAttributedTextContentView * attributedTextContentView

 @interface DTAttributedTextContentView : UIView
 {
      NSAttributedString *_attributedString;
      DTCoreTextLayoutFrame *_layoutFrame;

      UIEdgeInsets _edgeInsets;

      NSMutableDictionary *customViewsForAttachmentsIndex;

      BOOL _flexibleHeight;

      // for layoutFrame
      NSInteger _numberOfLines;
      NSLineBreakMode _lineBreakMode;
      NSAttributedString *_truncationString;
}

attributedTextContentView得到了@property DTCoreTextLayoutFrame * layoutFrame

 @interface DTCoreTextLayoutFrame : NSObject 
 {
   CGRect _frame;

   NSArray *_lines;
   NSArray *_paragraphRanges;

   NSArray *_textAttachments;
   NSAttributedString *_attributedStringFragment;
 }

所以基本上我需要改变

self.v.attributedTextContentView.layoutFrame.frame.size.width

因为我不能使用

objc_setAssociatedObject(self.v.attributedTextContentView.layoutFrame,@"frame.size.width",@200,OBJC_ASSOCIATION_ASSIGN);

也不

objc_setAssociatedObject(self.v.attributedTextContentView.layoutFrame,@"frame",CGRectMake(0,0,200,1000),OBJC_ASSOCIATION_ASSIGN);

因为我不能通过点符号访问ivars,也不能发送CGStruct作为CGFloat所需的事件,如果&。

作为这种情况的另一种解决方案,我看到使用运行时按对象创建对象,然后更改指针。 也许可以使用副本完成一些步骤。 我的问题是,我在objc / runtime和文档中的新手总是很差。 我努力学习这项重要的技术,所以我故意不使用其他选项解决确切的问题。

任何帮助将受到高度赞赏。 Thanx提前。

看起来你做错了什么,但如果你真的需要将值设置为另一个实例ivar(这可能导致不可预测的行为),这就是你需要知道的:

1)关联对象不是实例的一部分,因此如果使用等于property / ivar name的键添加关联对象,则不会更改property / ivar的值

2)如果此结构是对象的属性, 则无法更改结构的部分

3)您可以通过调用valueForKey:来访问ivars valueForKey: / setValue:forKey:如果accessInstanceVariablesDirectly属性未被覆盖。

4)在传递给setValue:forKey:之前,你需要将你的结构包装到NSValue setValue:forKey:

因此,结果代码应如下所示:

DTCoreTextLayoutFrame *layoutFrame = self.v.attributedTextContentView.layoutFrame;
CGRect frame = [[layoutFrame valueForKey:@"_frame"] CGRectValue];
frame.size.width = 200.0;
NSValue* frameValue = [NSValue valueWithCGRect:frame];
[layoutFrame setValue:frameValue forKey:@"_frame"];

有关KVC的更多信息,请查看键值编码编程指南

更新:

如果要使用运行时函数,则需要:

1)获取实例变量的偏移量(所有objective-c对象都是结构)

2)创建指向您感兴趣的ivar的指针

3)直接读/写此指针

这是代码:

DTCoreTextLayoutFrame *layoutFrame = self.v.attributedTextContentView.layoutFrame;    
Ivar ivar = class_getInstanceVariable([DTCoreTextLayoutFrame class], "_frame");
ptrdiff_t offset = ivar_getOffset(ivar);
CGRect *framePtr = (__bridge void*)layoutFrame + offset;
CGRect frame = *framePtr;
frame.size.width = 100;
*framePtr = frame;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM