我正在尝试为我的自定义对象实现自定义getter和setter,尽管使用ARC HFObject
,我的应用Message sent to deallocated instance
仍因错误而崩溃。
我读过每一篇相关的文章,ARC之前写的文章都不适用,其他所有内容也无济于事。我打开了僵尸对象调试器选项。
在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的实现中,我删除了的自动获取和设置email
。firstName
,并像这样date
利用@dynamic
@dynamic email;
@dynamic firstName;
@dynamic date;
我也在values
我的HObject init中分配了字典
- (id)init {
self = [super init];
if (self) {
self.values = [NSMutableDictionary dictionary];
}
return self;
}
对于我的自定义获取/设置者。我已覆盖
- (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
按asHObject
和dirtyValues
as处理values
;出于演示目的,我将其重命名)
您可以看到该键下@"FirstName"
没有任何值。
我做了一些类似的测试,在这些测试中,我更改了所设置的属性的值并更改了数据类型。通常,不仅没有FirstName
价值,也没有价值Date
。但是,电子邮件的价值始终存在。
研究有关数据类型后,我意识到这是因为email
是一个string literal
无法释放。另一方面,firstName
和date
是可以释放的对象。
崩溃日志引用了一个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
字符串。
我尝试将字符串重置为NSStrings
using,(__brigde NSString *)obj
以及将CF对象桥接到ARC的所有其他可能方式,但这也不起作用。
这是我所做的一切。我感谢所有帮助。
问题在这里:
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] 删除。
我来说两句