使用自定义getter和setter将消息发送到带有ARC的已释放实例的消息

我正在尝试为我的自定义对象实现自定义getter和setter,尽管使用ARC HFObject,我的应用Message sent to deallocated instance仍因错误而崩溃

我读过每一篇相关的文章,ARC之前写的文章都不适用,其他所有内容也无济于事。我打开了僵尸对象调试器选项。


设置自定义HObject

在HObject.h中,我已经声明了以下四个属性:

@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;

在HObject的实现中,我删除了的自动获取和设置emailfirstName,并像这样date利用@dynamic

@dynamic email;
@dynamic firstName;
@dynamic date;

我也在values我的HObject init中分配了字典

- (id)init {
    self = [super init];

    if (self) {
        self.values = [NSMutableDictionary dictionary];
    }

    return self;
}

实施自定义Getter和Sender

对于我的自定义获取/设置者。我已覆盖

- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector

- (void)forwardInvocation:(NSInvocation *)invocation

如下所示:

- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
{
    NSString *sel = NSStringFromSelector(selector);
    if ([sel rangeOfString:@"set"].location == 0) {
        return [NSMethodSignature signatureWithObjCTypes:"v@:@"];
    } else {
        return [NSMethodSignature signatureWithObjCTypes:"@@:"];
    }
}

- (void)forwardInvocation:(NSInvocation *)invocation
{
    NSString *key = NSStringFromSelector([invocation selector]);
    if ([key rangeOfString:@"set"].location == 0) { 
        key = [key substringWithRange:NSMakeRange(3, [key length]-4)]; 

        id obj;   
        [invocation getArgument:&obj atIndex:2];   

        [self.values setObject:obj forKey:key];
    } else {
        id obj = [self.values objectForKey:key];

        [invocation setReturnValue:&obj];
    }
}

我在这里想要做的是将属性的所有值存储到我的values字典中,并从那里检索它们。


应用崩溃

在我的视图控制器的实现中,我尝试创建一个HObject并为我的属性设置值,然后登录值字典以查看所有值。

- (void)buttonPressed:(id)sender {
    HObject *obj = [[HObject alloc] init];

    NSString *name = @"this is a string object";
    obj.date = [NSDate date];
    obj.email = @"[email protected]";
    obj.firstName = [NSString stringWithFormat:@"%@", name];


    NSLog(@"Values %@", [obj values]);
}

那时应用程序崩溃了,这是我的控制台日志

2014-07-27 04:12:37.899 App[61501:60b] 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[61501:60b] *** -[CFString release]: message sent to deallocated instance 0x109473fe0

如果您可以从这里帮助我,我将不胜感激。我还将包括我的调试过程,以帮助您


我的调试过程(很长,如果您已经可以帮助我,请跳过)

我最初创建了许多这样的对象并将它们存储在数组中,当我这样做时,与创建单个对象相反。我的应用崩溃了一点。

我的数组:

@property (nonatomic, strong) NSArray *array;

方法:

- (void)createArray
{
    int i = 1; //number of testobjs

    NSMutableArray *objects = [NSMutableArray arrayWithCapacity:i];

    for (int j = 0; j<i; j++) {
        HFObject *obj = [[User alloc] init];

        NSString *name = @"this is a string object";
        [obj setObject:[NSDate date] forKey:@"Date"];
        obj.email = @"[email protected]";
        obj.firstName = [NSString stringWithFormat:@"%@", name];

        [objects addObject:obj];
    }


    self.array = [NSArray arrayWithArray:objects];

}

- (void)buttonPressed:(id)sender {
    HObject *object = [self.array objectAtIndex:0];

    NSLog(@"Values %@", [object values]);
}

崩溃日志:

2014-07-27 04:34:02.893 App[61623:60b] *** -[CFString isNSString__]: message sent to deallocated instance 0x1094988f0
(lldb) 

现在,此崩溃日志与之前的崩溃日志几乎相同,除了此日志未记录其中的值 [object values]

稍微研究一下这个问题,我看着调试器的左窗口(不确定它的实际名称),我看到了:

()

HFObject按asHObjectdirtyValuesas处理values;出于演示目的,我将其重命名)

您可以看到该键下@"FirstName"没有任何值。

我做了一些类似的测试,在这些测试中,我更改了所设置的属性的值并更改了数据类型。通常,不仅没有FirstName价值,也没有价值Date但是,电子邮件的价值始终存在。

研究有关数据类型后,我意识到这是因为email是一个string literal无法释放。另一方面,firstNamedate是可以释放的对象。

崩溃日志引用了一个CFString属性,据我了解,该属性不使用ARC。我从未创建过Core Foundation对象,因此我着手通过记录以下内容来发现它是在setter中创建的[obj class]

- (void)forwardInvocation:(NSInvocation *)invocation
{
    NSString *key = NSStringFromSelector([invocation selector]);
    if ([key rangeOfString:@"set"].location == 0) { 
        key = [key substringWithRange:NSMakeRange(3, [key length]-4)]; 

        id obj;   
        [invocation getArgument:&obj atIndex:2];   

        NSLog(@"%@", [obj class]);  //I ADDED THIS LOG

        [self.values setObject:obj forKey:key];
    } else {
        id obj = [self.values objectForKey:key];

        [invocation setReturnValue:&obj];
    }
}

再摔了一次之后,我上了obj

2014-07-27 04:58:03.893 HeadsUp[61765:60b] __NSDate
2014-07-27 04:58:03.894 HeadsUp[61765:60b] __NSCFConstantString
2014-07-27 04:58:03.894 HeadsUp[61765:60b] __NSCFString
2014-07-27 04:58:03.904 HeadsUp[61765:60b] *** -[__NSDate release]: message sent to deallocated instance 0x109554370
(lldb) 

在这里,您可以看到Date由于某种原因而被释放,而我的字符串现在是__NSCF字符串。

我尝试将字符串重置为NSStringsusing,(__brigde NSString *)obj以及将CF对象桥接到ARC的所有其他可能方式,但这也不起作用。

这是我所做的一切。我感谢所有帮助。

马丁·R

问题在这里:

id obj;   
[invocation getArgument:&obj atIndex:2];

getArgument只需将对象指针复制到其中obj而不保留它。但是,由于obj(默认情况下)是__strong变量,因此它将在当前方法的末尾释放。为了解决这个问题,使用

__unsafe_unretained id obj;   
[invocation getArgument:&obj atIndex:2];   

另请注意,您的getter实现无效。例如,setFirstName:使用键“ FirstName”将键存储在字典中,但是getterfirstName尝试读取键“ firstName”的值。

(正如评论中已经提到的,仅单独覆盖三个属性的访问器方法而不是动态转发可能会更容易且更容易出错。)

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

消息已发送到已释放实例ARC

来自分类Dev

转换为ARC后,我收到“发送到已释放实例的消息”

来自分类Dev

iPhone消息已发送到已释放实例

来自分类Dev

[CFNumber版本]:消息发送到已释放实例

来自分类Dev

[UINavigationController保留]:发送到已释放实例的消息

来自分类Dev

iPhone numberOfSectionsInTableView消息发送到已释放实例

来自分类Dev

UITextField textInputView消息发送到已释放实例

来自分类Dev

发送到已释放实例iOS [_UILayoutGuide isDescendantOfView:]的消息:

来自分类Dev

[CFString版本]:消息发送到已释放实例

来自分类Dev

[_UILabelLayer isHidden]:发送到已释放实例的消息

来自分类Dev

[CALayer isKindOfClass:]:消息发送到已释放实例

来自分类Dev

发送到已释放实例iOS [_UILayoutGuide isDescendantOfView:]的消息:

来自分类Dev

[UIImageAsset保留]:发送到已释放实例的消息

来自分类Dev

消息已发送到iCarousel内部UIButton上的已释放实例

来自分类Dev

消息已发送到iCarousel内部UIButton上的已释放实例

来自分类Dev

如何使用Chromecast将消息从自定义收件人发送到发件人应用?

来自分类Dev

如何将消息从自定义UIView发送到单独的文件中的UIViewController

来自分类Dev

Swift:[MyApp.MyClass保留]:消息发送到已释放实例

来自分类Dev

iOS 10 [CFString版本]:消息发送到已释放实例

来自分类Dev

发送到已释放实例的searchDisplayController消息(仅在iOS7中)

来自分类Dev

iOS:[CFRunLoopTimer版本]:消息发送到已释放实例错误调试

来自分类Dev

[__NSArrayI objectAtIndex:]:消息发送到已释放实例0x7fbdae1a2080

来自分类Dev

收到错误“-[NSThread threadDictionary]:消息发送到已释放实例”

来自分类Dev

UITableView中崩溃,将消息发送到已释放的UIViewController

来自分类Dev

iOS 8:-[UIInputViewSet setRestorableResponder:]:消息发送到已释放实例0x7d6659b0

来自分类Dev

iOS 8:-[UIInputViewSet setRestorableResponder:]:消息发送到已释放实例0x7d6659b0

来自分类Dev

如何使用pjsua2 android发送带有自定义标头的SIP消息

来自分类Dev

将消息发送到Azure网站实例

来自分类Dev

带有自定义消息的吐司

Related 相关文章

  1. 1

    消息已发送到已释放实例ARC

  2. 2

    转换为ARC后,我收到“发送到已释放实例的消息”

  3. 3

    iPhone消息已发送到已释放实例

  4. 4

    [CFNumber版本]:消息发送到已释放实例

  5. 5

    [UINavigationController保留]:发送到已释放实例的消息

  6. 6

    iPhone numberOfSectionsInTableView消息发送到已释放实例

  7. 7

    UITextField textInputView消息发送到已释放实例

  8. 8

    发送到已释放实例iOS [_UILayoutGuide isDescendantOfView:]的消息:

  9. 9

    [CFString版本]:消息发送到已释放实例

  10. 10

    [_UILabelLayer isHidden]:发送到已释放实例的消息

  11. 11

    [CALayer isKindOfClass:]:消息发送到已释放实例

  12. 12

    发送到已释放实例iOS [_UILayoutGuide isDescendantOfView:]的消息:

  13. 13

    [UIImageAsset保留]:发送到已释放实例的消息

  14. 14

    消息已发送到iCarousel内部UIButton上的已释放实例

  15. 15

    消息已发送到iCarousel内部UIButton上的已释放实例

  16. 16

    如何使用Chromecast将消息从自定义收件人发送到发件人应用?

  17. 17

    如何将消息从自定义UIView发送到单独的文件中的UIViewController

  18. 18

    Swift:[MyApp.MyClass保留]:消息发送到已释放实例

  19. 19

    iOS 10 [CFString版本]:消息发送到已释放实例

  20. 20

    发送到已释放实例的searchDisplayController消息(仅在iOS7中)

  21. 21

    iOS:[CFRunLoopTimer版本]:消息发送到已释放实例错误调试

  22. 22

    [__NSArrayI objectAtIndex:]:消息发送到已释放实例0x7fbdae1a2080

  23. 23

    收到错误“-[NSThread threadDictionary]:消息发送到已释放实例”

  24. 24

    UITableView中崩溃,将消息发送到已释放的UIViewController

  25. 25

    iOS 8:-[UIInputViewSet setRestorableResponder:]:消息发送到已释放实例0x7d6659b0

  26. 26

    iOS 8:-[UIInputViewSet setRestorableResponder:]:消息发送到已释放实例0x7d6659b0

  27. 27

    如何使用pjsua2 android发送带有自定义标头的SIP消息

  28. 28

    将消息发送到Azure网站实例

  29. 29

    带有自定义消息的吐司

热门标签

归档