By dmost
on Wed, 06/20/2012 - 17:09
Congrats to Qualcomm Austria on getting v1.5.8 out!
I started using it immediately and believe I found an issue related to loading a dataset; more specifically the DataSetItem helper in the sample code.
Using the out-of-the-box ImageTargets example, if you pass a non-retained string into addTargetName; there's a failure as soon as the string is accessed in the qcar thread (QCARutils.mm line 722).
For example:
[CODE]
// Provide a list of targets we're expecting - the first in the list is the default
NSString * path = [NSString stringWithFormat:@"%@", @"StonesAndChips.xml"];
[qUtils addTargetName:@"Stones & Chips" atPath:path];
[/CODE]
The common idiom is "if you want the object, you retain it". Since I don't need 'path' after the addTargetName:atPath: call; I let it get auto-released. If I retain the object; the crash goes away.
After some investigation I believe the issue is that the "DataSetItem" class does not retain the string. Looking at the sample code; it seems to assign the string to it's protected var:
[CODE]
- (id) initWithName:(NSString *)theName andPath:(NSString *)thePath
{
self = [super init];
if (self) {
name = theName; <--- oops, plain old assignment
path = thePath;
dataSet = nil;
}
return self;
}
[/CODE]
If you don't use "self.path" (which you wouldn't do in init) then you're not using the accessor. That's going right into the var, and isn't retained.
I see the properties for name/path retain strings, but I think it's more common to 'copy' a string. Probably that's just a personal preference.
I updated my version of QCARutils.h to remove the var names; they're redundant with recent XCode versions:
[CODE]
#pragma mark --- Class interface for DataSet list ---
@interface DataSetItem : NSObject
@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) NSString *path;
@property (nonatomic) QCAR::DataSet *dataSet;
- (id) initWithName:(NSString *)theName andPath:(NSString *)thePath;
@end
[/CODE]
I updated my version of QCARutils.mm to so properties and ivars have different names, so I can't accidentally use the ivar; retained the strings, and added a dealloc:
[CODE]
#pragma mark --- Class interface for DataSet list ---
@implementation DataSetItem
@synthesize name = _name;
@synthesize path = _path;
@synthesize dataSet = _dataSet;
- (id) initWithName:(NSString *)theName andPath:(NSString *)thePath
{
self = [super init];
if (self) {
_name = [theName copy];
_path = [thePath copy];
_dataSet = nil;
}
return self;
}
- (void)dealloc {
[_name release];
[_path release];
[super dealloc];
}
@end
[/CODE]
If you agree with the above assessment, I hope the above will save you some time.
Again, many thanks for such an amazing SDK.
--Dave
Re: Found a v1.
Re: Found a v1.
Re: Found a v1.