开发者

Adding Custom Object to NSMutableArray

Developing ios app. I have an object class Product.h and .m respectively along with my picker class which implements my vehicle selection to match products to vehicle. The files

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

Product implementation .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.vc开发者_开发问答hWC = [[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

Ignoring the fact that its really long I also tried to just set the property but then my product didnt have any values. So I alloc'd for all properties, not sure which is "correct"

the use of product 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

The implementation .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

So I stripped out all the table methods and misc crap that doesnt matter. In the end my problem is adding the "tempProduct" object to the mutable array dataArray so that I can customize the table cells. Using the json framework im parsing out some json which returns an array of NSDictionary objects. Stepping through that my dictionary objects look good, I populate my custom object with properties for all my fields which goes through fine, and the values look right. However I cant add this to the array, I've tried several different implementations doesn't work. Not sure what I'm doing wrong. In some instances doing a po tempProduct prints the description and sometimes it does not. same with right clicking on the variable and choosing print description.

Actual error message

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'


Your problem is this:

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

There are a couple things wrong here:

  1. This is a memory leak. The property is declared as a retain property, and you're giving it an owned object. Therefore you've declared ownership of the object twice (once with +alloc, then again by retaining it in the property setter method), but you only relinquish ownership once (when the object is deallocated).
  2. You're not giving self a mutable array. You're giving it an immutable array. In other words, NSArray != NSMutableArray. Once you've created an NSArray, you cannot change its contents. You can only do that with an NSMutableArray.

To fix this, you should change the line to:

self.dataArray = [NSMutableArray array];

Beyond this, you have memory leaks all over the place.

  • For example, pretty much every single line in your -[Product initWithDict:] method is leaking memory. They should all be replaced with:

    self.propertyName = [dic objectForKey:@"dictionary key"];
    
  • This is flat-out wrong:

    [self.dataArray release];
    

    You should do:

    self.dataArray = nil;
    
  • This is another leak:

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

    You should do:

    NSString *thisString = [NSString stringWithFormat:@"http://api.curthitch.biz/AJAX_CURT.aspx?action=GetHitch&dataType=json&year=%@&make=%@&model=%@&style=%@",year,make,model,style];
    
  • you +alloc a string referenced by json_string, but you never release it.

  • you +alloc an SBJsonParser, but you never release it.
  • you +alloc a Product on each iteration of your for loop, but you never release it.

It's pretty clear that you haven't read some of the fundamental documentation. I strongly suggest that you do:

  • The Objective-C Programming Language Reference
  • The Memory Management Programming Guide
  • Naming Conventions
  • Everything you need to know about pointers in C (boredzo.org)


Your problem is that you allocate an NSArray and not an NSMutableArray in your assignment to self.dataArray. Try [[NSMutableArray alloc] init] Also, if you alloc / init objects, and then use a retain, you will over-retain your objects. Autorelease them at the time of assignment

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜