2011-02-22 180 views
0

开发iOS应用程序。我有一个对象类Product.h和.m分别与我的选择器类一起实现我的车辆选择以匹配产品和车辆。该文件将自定义对象添加到NSMutableArray

product.h

#import <Foundation/Foundation.h> 


@interface Product : NSObject { 

} 

@property (nonatomic, retain) NSString *iProductID; 
@property (nonatomic, retain) NSString *vchProductCode; 
@property (nonatomic, retain) NSString *vchPriceCode; 
@property (nonatomic, retain) NSString *vchHitchUPC; 
@property (nonatomic, retain) NSString *mHitchList; 
@property (nonatomic, retain) NSString *mHitchMap; 
@property (nonatomic, retain) NSString *fShippingWeight; 
@property (nonatomic, retain) NSString *vchWC; 
@property (nonatomic, retain) NSString *vchCapacity; 
@property (nonatomic, retain) NSString *txtNote1; 
@property (nonatomic, retain) NSString *txtNote2; 
@property (nonatomic, retain) NSString *txtNote3; 
@property (nonatomic, retain) NSString *txtNote4; 
@property (nonatomic, retain) NSString *vchDrilling; 
@property (nonatomic, retain) NSString *vchUPCList; 
@property (nonatomic, retain) NSString *vchExposed; 
@property (nonatomic, retain) NSString *vchShortDesc; 
@property (nonatomic, retain) NSString *iVehicleID; 
@property (nonatomic, retain) NSString *iProductClassID; 
@property (nonatomic, retain) NSString *dtDateMod; 
@property (nonatomic, retain) NSString *txtBullet1; 
@property (nonatomic, retain) NSString *txtBullet2; 
@property (nonatomic, retain) NSString *txtBullet3; 
@property (nonatomic, retain) NSString *txtBullet4; 
@property (nonatomic, retain) NSString *txtBullet5; 
@property (nonatomic, retain) NSString *iUniqueIdentifier; 
@property (nonatomic, retain) NSString *dtDateLastTouched; 
@property (nonatomic, retain) NSString *txtNote6; 
@property (nonatomic, retain) NSString *InstallTime; 
@property (nonatomic, retain) NSString *SGID; 
@property (nonatomic, retain) NSString *CURTID; 
@property (nonatomic, retain) NSString *SGRetail; 
@property (nonatomic, retain) NSString *SGMemPrice; 
@property (nonatomic, retain) NSString *InstallSheet; 
@property (nonatomic, retain) NSString *mHitchJobber; 
@property (nonatomic, retain) NSString *CatID; 
@property (nonatomic, retain) NSString *ParentID; 

-(id) initWithDict:(NSDictionary *)dic; 

-(NSString *) description; 

@end 

产品执行的.m

#import "Product.h" 


@implementation Product 

@synthesize iProductID; 
@synthesize vchProductCode; 
@synthesize vchPriceCode; 
@synthesize vchHitchUPC; 
@synthesize mHitchList; 
@synthesize mHitchMap; 
@synthesize fShippingWeight; 
@synthesize vchWC; 
@synthesize vchCapacity; 
@synthesize txtNote1; 
@synthesize txtNote2; 
@synthesize txtNote3; 
@synthesize txtNote4; 
@synthesize vchDrilling; 
@synthesize vchUPCList; 
@synthesize vchExposed; 
@synthesize vchShortDesc; 
@synthesize iVehicleID; 
@synthesize iProductClassID; 
@synthesize dtDateMod; 
@synthesize txtBullet1; 
@synthesize txtBullet2; 
@synthesize txtBullet3; 
@synthesize txtBullet4; 
@synthesize txtBullet5; 
@synthesize iUniqueIdentifier; 
@synthesize dtDateLastTouched; 
@synthesize txtNote6; 
@synthesize InstallTime; 
@synthesize SGID; 
@synthesize CURTID; 
@synthesize SGRetail; 
@synthesize SGMemPrice; 
@synthesize InstallSheet; 
@synthesize mHitchJobber; 
@synthesize CatID; 
@synthesize ParentID; 

-(id) initWithDict:(NSDictionary *)dic 
{ 
    [super init]; 
    //Initialize all variables 
    self.iProductID = [[NSString alloc] initWithString:[dic objectForKey:@"iProductID"]]; 

    self.vchProductCode = [[NSString alloc] initWithString:[dic objectForKey:@"vchProductCode"]]; 

    self.vchPriceCode = [[NSString alloc] initWithString:[dic objectForKey:@"vchPriceCode"]]; 

    self.vchHitchUPC = [[NSString alloc] initWithString:[dic objectForKey:@"vchHitchUPC"]]; 

    self.mHitchList = [[NSString alloc] initWithString:[dic objectForKey:@"mHitchList"]]; 

    self.mHitchMap = [[NSString alloc] initWithString:[dic objectForKey:@"mHitchMap"]]; 

    self.fShippingWeight = [[NSString alloc] initWithString:[dic objectForKey:@"fShippingWeight"]]; 

    self.vchWC = [[NSString alloc] initWithString:[dic objectForKey:@"vchWC"]]; 

    self.vchCapacity = [[NSString alloc] initWithString:[dic objectForKey:@"vchCapacity"]]; 

    self.txtNote1 = [[NSString alloc] initWithString:[dic objectForKey:@"txtNote1"]]; 

    self.txtNote2 = [[NSString alloc] initWithString:[dic objectForKey:@"txtNote2"]]; 

    self.txtNote3 = [[NSString alloc] initWithString:[dic objectForKey:@"txtNote3"]]; 

    self.txtNote4 = [[NSString alloc] initWithString:[dic objectForKey:@"txtNote4"]]; 

    self.vchDrilling = [[NSString alloc] initWithString:[dic objectForKey:@"vchDrilling"]]; 

    self.vchUPCList = [[NSString alloc] initWithString:[dic objectForKey:@"vchUPCList"]]; 

    self.vchExposed = [[NSString alloc] initWithString:[dic objectForKey:@"vchExposed"]]; 

    self.vchShortDesc = [[NSString alloc] initWithString:[dic objectForKey:@"vchShortDesc"]]; 

    self.iVehicleID = [[NSString alloc] initWithString:[dic objectForKey:@"iVehicleID"]]; 

    self.iProductClassID = [[NSString alloc] initWithString:[dic objectForKey:@"iProductClassID"]]; 

    self.dtDateMod = [[NSString alloc] initWithString:[dic objectForKey:@"dtDateMod"]]; 

    self.txtBullet1 = [[NSString alloc] initWithString:[dic objectForKey:@"txtBullet1"]]; 

    self.txtBullet2 = [[NSString alloc] initWithString:[dic objectForKey:@"txtBullet2"]]; 

    self.txtBullet3 = [[NSString alloc] initWithString:[dic objectForKey:@"txtBullet3"]]; 

    self.txtBullet4 = [[NSString alloc] initWithString:[dic objectForKey:@"txtBullet4"]]; 

    self.txtBullet5 = [[NSString alloc] initWithString:[dic objectForKey:@"txtBullet5"]]; 

    self.iUniqueIdentifier = [[NSString alloc] initWithString:[dic objectForKey:@"iUniqueIdentifier"]]; 

    self.dtDateLastTouched = [[NSString alloc] initWithString:[dic objectForKey:@"dtDateLastTouched"]]; 

    self.txtNote6 = [[NSString alloc] initWithString:[dic objectForKey:@"txtNote6"]]; 

    self.InstallTime = [[NSString alloc] initWithString:[dic objectForKey:@"InstallTime"]]; 

    self.SGID = [[NSString alloc] initWithString:[dic objectForKey:@"SGID"]]; 

    self.CURTID = [[NSString alloc] initWithString:[dic objectForKey:@"CURTID"]]; 

    self.SGRetail = [[NSString alloc] initWithString:[dic objectForKey:@"SGRetail"]]; 

    self.SGMemPrice = [[NSString alloc] initWithString:[dic objectForKey:@"SGMemPrice"]]; 

    self.InstallSheet = [[NSString alloc] initWithString:[dic objectForKey:@"InstallSheet"]]; 

    self.mHitchJobber = [[NSString alloc] initWithString:[dic objectForKey:@"mHitchJobber"]]; 

    self.CatID = [[NSString alloc] initWithString:[dic objectForKey:@"CatID"]]; 

    self.ParentID = [[NSString alloc] initWithString:[dic objectForKey:@"ParentID"]]; 

    return self; 
} 

-(NSString *) description 
{ 
    return [NSString stringWithFormat:@"iProductID = %@\n vchProductCode = %@\n vchPriceCode = %@\n vchHitchUPC = %@\n mHitchList = %@\n mHitchMap = %@\n fShippingWeight = %@\n vchWC = %@\n vchCapacity = %@\n txtNote1 = %@\n txtNote2 = %@\n txtNote3 = %@\n txtNote4 = %@\n vchDrilling = %@\n vchUPCList = %@\n vchExposed = %@\n vchShortDesc = %@\n iVehicleID = %@\n iProductClassID = %@\n dtDateMod = %@\n txtBullet1 = %@\n txtBullet2 = %@\n txtBullet3 = %@\n txtBullet4 = %@\n txtBullet4 = %@\n txtBullet5 = %@\n iUniqueIdentifier = %@\n dtDateLastTouched = %@\n txtNote6 = %@\n InstallTime = %@\n SGID = %@\n CURTID = %@\n SGRetail = %@\n SGMemPrice = %@\n InstallSheet = %@\n mHitchJobber = %@\n CatID = %@\n ParentID = %@\n", iProductID, vchProductCode, vchPriceCode, vchHitchUPC, mHitchList, mHitchMap, fShippingWeight, vchWC, vchCapacity, txtNote1, txtNote2, txtNote3, txtNote4, vchDrilling, vchUPCList, vchExposed, vchShortDesc, iVehicleID, iProductClassID, dtDateMod, txtBullet1, txtBullet2, txtBullet3, txtBullet4,txtBullet5, iUniqueIdentifier, dtDateLastTouched,txtNote6,InstallTime,SGID,CURTID,SGRetail,SGMemPrice,InstallSheet,mHitchJobber,CatID, ParentID]; 
} 

@end 

忽略了一个事实,它很长我也试着刚才设置的属性,但随后我的产品没有必须的任何值。所以我alloc'd所有属性,不知道这是 “正确的”

产品的使用 picker.h

#import <UIKit/UIKit.h> 

@class Vehicle; 
@class Product; 



@interface Picker : UITableViewController <NSXMLParserDelegate> { 
    NSString *currentRow; 
    NSString *currentElement; 
    Vehicle *vehicle; 
} 

@property (nonatomic, retain) NSMutableArray *dataArray; 

//@property (readwrite, copy) NSString *currentRow; 
//@property (readwrite, copy) NSString *currentElement; 

-(void) getYears:(NSString *)string; 
-(void) getMakes:(NSString *)year; 
-(void) getModels:(NSString *)year: (NSString *)make; 
-(void) getStyles:(NSString *)year: (NSString *)make: (NSString *)model; 

-(void) getHitch:(NSString *)year: (NSString *)make: (NSString *)model: (NSString *)style; 

-(void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName; 

-(void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string; 

-(void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict; 

@end 

实现的.m的

#import "Product.h" 
#import "Picker.h" 
#import "KioskAppDelegate.h" 
#import "JSON.h" 
#import "Vehicle.h" 

@implementation Picker 

@synthesize dataArray; 
-(void) getHitch:(NSString *)year: (NSString *)make: (NSString *)model: (NSString *)style{ 
    currentRow = [NSString stringWithString:@"z:row"]; 
    currentElement = [NSString stringWithString:@"gethitch"]; 

    //Reinitialize data array 
    [self.dataArray removeAllObjects]; 
    [self.dataArray release]; 
    self.dataArray = [[NSArray alloc] initWithObjects:nil]; 

    //Build url & string 
    NSString *thisString = [[NSString alloc] initWithString:@""]; 
    thisString = [NSString stringWithFormat:@"http://api.curthitch.biz/AJAX_CURT.aspx?action=GetHitch&dataType=json&year=%@&make=%@&model=%@&style=%@",year,make,model,style]; 

    //Request 
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:thisString]]; 

    //Perform request and fill data with json 
    NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; 

    //Get string from data 
    NSString *json_string = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding]; 

    //set up parser 
    SBJsonParser *parser = [[SBJsonParser alloc] init]; 

    //parse json into object 
    NSArray *tempArray = [parser objectWithString:json_string error:nil]; 
    for (NSDictionary *dic in tempArray) { 
     Product *tempProduct = [[Product alloc] initWithDict:dic]; 
     NSLog(@"is tempProduct valid %@", (tempProduct) ? @"YES" : @"NO"); 
     [self.dataArray addObject:tempProduct]; 
    } 
} 

@end 

所以我剥离出来所有的表格方法和misc垃圾无关紧要。最后,我的问题是将“tempProduct”对象添加到可变数组dataArray中,以便我可以自定义表格单元格。 使用json框架im解析出一些返回一个NSDictionary对象数组的json。通过我的字典对象看起来不错,我用我的所有字段的属性填充我的自定义对象,这些字段都很好,并且值看起来正确。然而,我不能将此添加到数组中,我试过几个不同的实现不起作用。不知道我做错了什么。在某些情况下,执行po tempProduct会打印说明,有时不会。与右键单击变量并选择打印说明相同。

实际的错误信息

2011-02-22 15:53:56.058 Kiosk[8547:207] -[__NSArrayI addObject:]: unrecognized selector sent to instance 0x4e1ba40 
2011-02-22 15:53:56.060 Kiosk[8547:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayI addObject:]: unrecognized selector sent to instance 0x4e1ba40' 
*** Call stack at first throw: 
(
    0 CoreFoundation      0x00dbabe9 __exceptionPreprocess + 185 
    1 libobjc.A.dylib      0x00f0f5c2 objc_exception_throw + 47 
    2 CoreFoundation      0x00dbc6fb -[NSObject(NSObject) doesNotRecognizeSelector:] + 187 
    3 CoreFoundation      0x00d2c366 ___forwarding___ + 966 
    4 CoreFoundation      0x00d2bf22 _CF_forwarding_prep_0 + 50 
    5 Kiosk        0x00003ead -[Picker getHitch::::] + 1091 
    6 Kiosk        0x00003007 -[Picker tableView:didSelectRowAtIndexPath:] + 1407 
    7 UIKit        0x0009b794 -[UITableView _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:] + 1140 
    8 UIKit        0x00091d50 -[UITableView _userSelectRowAtPendingSelectionIndexPath:] + 219 
    9 Foundation       0x007937f6 __NSFireDelayedPerform + 441 
    10 CoreFoundation      0x00d9bfe3 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 19 
    11 CoreFoundation      0x00d9d594 __CFRunLoopDoTimer + 1220 
    12 CoreFoundation      0x00cf9cc9 __CFRunLoopRun + 1817 
    13 CoreFoundation      0x00cf9240 CFRunLoopRunSpecific + 208 
    14 CoreFoundation      0x00cf9161 CFRunLoopRunInMode + 97 
    15 GraphicsServices     0x0102e268 GSEventRunModal + 217 
    16 GraphicsServices     0x0102e32d GSEventRun + 115 
    17 UIKit        0x0003442e UIApplicationMain + 1160 
    18 Kiosk        0x0000239a main + 104 
    19 Kiosk        0x00002329 start + 53 
) 
terminate called after throwing an instance of 'NSException' 

回答

6

你的问题是这样的:

self.dataArray = [[NSArray alloc] initWithObjects:nil]; 

有几件事错在这里:

  1. 这是内存泄漏。该属性被声明为retain属性,并且您正在给它一个拥有对象。因此,您已声明对象两次的所有权为(一次使用+alloc,然后再使用retaining它在属性设置器方法中),但您只会放弃一次所有权(当对象被释放时)。你不给self一个可变数组。你给它一个不变的数组。换句话说,NSArray != NSMutableArray。创建NSArray后,您无法更改其内容。你只能用NSMutableArray来做到这一点。

为了解决这个问题,你应该行更改为:

self.dataArray = [NSMutableArray array]; 

除此之外,你有内存泄漏所有的地方。

  • 例如,您的-[Product initWithDict:]方法中几乎每一行都是内存泄漏。

    self.propertyName = [dic objectForKey:@"dictionary key"]; 
    
  • 这是完全错误:

    [self.dataArray release]; 
    

    你应该这样做:

    self.dataArray = nil; 
    
  • 这是另一种泄漏:

    NSString *thisString = [[NSString alloc] initWithString:@""]; 
    thisString = [NSString stringWithFormat:@"http://api.curthitch.biz/AJAX_CURT.aspx?action=GetHitch&dataType=json&year=%@&make=%@&model=%@&style=%@",year,make,model,style]; 
    
    他们都应该被替换

    你s HOULD做:

    NSString *thisString = [NSString stringWithFormat:@"http://api.curthitch.biz/AJAX_CURT.aspx?action=GetHitch&dataType=json&year=%@&make=%@&model=%@&style=%@",year,make,model,style]; 
    
  • +alloc通过json_string引用的字符串,但你永远不release它。

  • you +alloc an SBJsonParser,但你从来没有release它。
  • you +alloc a Product在您的for循环的每次迭代中,但您从来没有release它。

很明显,你还没有读过一些基本的文档。我强烈建议你做:

+0

或者 - 不要在初始化程序中调用self。即'dataArray = [[NSMutabelArray alloc] init];'。但请记住要在'dealloc'中发布它, – Abizern 2011-02-22 23:13:06

+0

@Abizern是的,这是很好的建议。我的回答虽然在技术上不是最佳实践,但是打算用他的代码改变最少量的东西。 (这对他来说可能更容易理解) – 2011-02-22 23:14:16

+1

NP。但是他将会看到许多用这种方式编写的示例代码,所以提到它是有道理的。 – Abizern 2011-02-22 23:16:01

0

你的问题是,你分配一个NSArray而不是NSMutableArray赋值给self.dataArray。尝试[[NSMutableArray alloc] init] 另外,如果你分配/ init对象,然后使用保留,你将过度保留你的对象。在分配时自动释放它们