ios - 使用自定义 getter 和 setter 将消息发送到带有 ARC 的已释放实例
<p><p>我正在尝试为我的自定义对象 <code>HFObject</code> 实现自定义 getter 和 setter,尽管使用了 ARC,但我的应用程序因 <code>Message sent to deallocated instance</code> 错误而崩溃。</p>
<p>我已经阅读了所有相关的帖子,在 ARC 之前编写的那些不适用,其他所有内容都没有帮助。我打开了僵尸对象调试器选项。</p>
<hr/>
<h2>设置自定义 HObject</h2>
<p>在 HObject.h 中我声明了这四个属性:</p>
<pre><code>@property (retain) NSString *email; //Will use custom getter/setter
@property (retain) NSString *firstName; //Will use custom getter/setter
@property (retain) NSDate *date; //Will use custom getter/setter
@property (nonatomic, retain) NSMutableDictionary *values;
</code></pre>
<p>在HObject的实现中,我去掉了<code>email</code>的自动获取和设置。 <code>firstName</code> 和 <code>date</code> 像这样使用 <code>@dynamic</code></p>
<pre><code>@dynamic email;
@dynamic firstName;
@dynamic date;
</code></pre>
<p>我还在我的 HObject init 中分配 <code>values</code> 字典</p>
<pre><code>- (id)init {
self = ;
if (self) {
self.values = ;
}
return self;
}
</code></pre>
<hr/>
<h2>实现自定义 Getter & Sender</h2>
<p>对于我的自定义 getter/setter。我已经覆盖了</p>
<p><code>- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector</code> </p>
<p>和</p>
<pre><code>- (void)forwardInvocation:(NSInvocation *)invocation
</code></pre>
<p>如下图:</p>
<pre><code>- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
{
NSString *sel = NSStringFromSelector(selector);
if (.location == 0) {
return ;
} else {
return ;
}
}
- (void)forwardInvocation:(NSInvocation *)invocation
{
NSString *key = NSStringFromSelector();
if (.location == 0) {
key = -4)];
id obj;
;
;
} else {
id obj = ;
;
}
}
</code></pre>
<p>我在这里要做的是将属性的所有值存储到我的 <code>values</code> 字典中,并从那里检索它们。</p>
<hr/>
<h2>应用程序崩溃</h2>
<p>在我的 ViewController 的实现中,我尝试创建一个 HObject 并为我的属性设置值,然后我记录值字典以查看我的所有值。</p>
<pre><code>- (void)buttonPressed:(id)sender {
HObject *obj = [ init];
NSString *name = @"this is a string object";
obj.date = ;
obj.email = @"[email protected]";
obj.firstName = ;
NSLog(@"Values %@", );
}
</code></pre>
<p>此时应用程序崩溃,这是我的控制台日志</p>
<pre><code>2014-07-27 04:12:37.899 App Values {
Date = "2014-07-27 08:12:37 +0000";
Email = "[email protected]";
FirstName = "this is a string object";
}
2014-07-27 04:12:37.901 HeadsUp *** -: message sent to deallocated instance 0x109473fe0
</code></pre>
<p>如果您能从这里帮助我,我将不胜感激。我还包括我的调试过程,以防对您有所帮助</p>
<hr/>
<h2>我的调试过程(很长,如果您已经可以帮助我,请跳过)</h2>
<p>我最初创建了许多这样的对象并将它们存储在一个数组中,当我这样做时,而不是创建单个对象。我的应用崩溃了一点。</p>
<p>我的数组:</p>
<pre><code>@property (nonatomic, strong) NSArray *array;
</code></pre>
<p>方法:</p>
<pre><code>- (void)createArray
{
int i = 1; //number of testobjs
NSMutableArray *objects = ;
for (int j = 0; j<i; j++) {
HFObject *obj = [ init];
NSString *name = @"this is a string object";
forKey:@"Date"];
obj.email = @"[email protected]";
obj.firstName = ;
;
}
self.array = ;
}
- (void)buttonPressed:(id)sender {
HObject *object = ;
NSLog(@"Values %@", );
}
</code></pre>
<p>崩溃日志:</p>
<pre><code>2014-07-27 04:34:02.893 App *** -: message sent to deallocated instance 0x1094988f0
(lldb)
</code></pre>
<p>现在这个崩溃日志几乎和之前一样了,除了这没有记录 <code></code></p> 里面的值
<p>稍微调查一下这个问题,我查看了调试器的左侧窗口(不确定它实际上叫什么),我看到了这个:</p>
<p> <img src="/image/vjRpb.png" alt="()"/> </p>
<p>(将 <code>HFObject</code> 视为 <code>HObject</code> 并将 <code>dirtyValues</code> 视为 <code>values</code>;出于演示目的,我将它们重命名)</p>
<p>您可以看到在 <code>@"FirstName"</code> 键下没有任何值。</p>
<p>我做了几个类似的测试,我更改了我正在设置的属性的值并更改了数据类型。很多时候,不仅<code>FirstName</code> 没有值,<code>Date</code> 也没有。但是,电子邮件的值(value)始终存在。</p>
<p>在研究了 dataTypes 之后,我意识到这是因为 <code>email</code> 是一个无法释放的 <code>string literal</code>。另一方面,<code>firstName</code> 和 <code>date</code> 是可以释放的对象。</p>
<p>崩溃日志引用了一个 <code>CFString</code> 属性,我了解到它不使用 ARC。我从未创建过 Core Foundation 对象,所以我开始通过记录 <code></code>:</p> 来发现它是在 setter 中创建的
<pre><code>- (void)forwardInvocation:(NSInvocation *)invocation
{
NSString *key = NSStringFromSelector();
if (.location == 0) {
key = -4)];
id obj;
;
NSLog(@"%@", );//I ADDED THIS LOG
;
} else {
id obj = ;
;
}
}
</code></pre>
<p>再次崩溃后,我得到了 <code>obj</code> 类</p>
<pre><code>2014-07-27 04:58:03.893 HeadsUp __NSDate
2014-07-27 04:58:03.894 HeadsUp __NSCFConstantString
2014-07-27 04:58:03.894 HeadsUp __NSCFString
2014-07-27 04:58:03.904 HeadsUp *** -: message sent to deallocated instance 0x109554370
(lldb)
</code></pre>
<p>在这里您可以看到 <code>Date</code> 由于某种原因正在被释放,而我的字符串现在是 <code>__NSCF</code> 字符串。</p>
<p>我尝试使用 <code>(__brigde NSString *)obj</code> 将字符串重置为 <code>NSStrings</code> 以及您可以将 CF 对象桥接到 ARC 的所有其他可能方式,但这并没有也可以工作。</p>
<p>这是我所做的一切。我感谢任何和所有的帮助。</p></p>
<br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
<p><p>问题出在这里:</p>
<pre><code>id obj;
;
</code></pre>
<p><code>getArgument</code> 只是将对象指针复制到 <code>obj</code> 而不保留它。
然而,由于 <code>obj</code> 是(默认情况下)一个 <code>__strong</code> 变量,它将在
当前方法的结束。要解决问题,请使用</p>
<pre><code>__unsafe_unretained id obj;
;
</code></pre>
<p>还请注意,您的 getter 实现不起作用。例如,<code>setFirstName:</code>
使用键“FirstName”将键存储在字典中,但 getter <code>firstName</code>
尝试读取键“firstName”的值。</p>
<p>(正如评论中已经提到的那样,它可能会更容易且不易出错
只是分别覆盖三个属性的访问器方法,而不是
动态转发。)</p></p>
<p style="font-size: 20px;">关于ios - 使用自定义 getter 和 setter 将消息发送到带有 ARC 的已释放实例,我们在Stack Overflow上找到一个类似的问题:
<a href="https://stackoverflow.com/questions/24979501/" rel="noreferrer noopener nofollow" style="color: red;">
https://stackoverflow.com/questions/24979501/
</a>
</p>
页:
[1]