iphone - My subclass as a property won't accept new values for its properties -
i have uiviewcontroller
presents uiviewcontroller
picker , returns 4 values. have custom class called chemical can hold these values. in delegate method receives values (the didselectsource
1 in adjustviewcontroller
) put breakpoint , can see proper values come back, when try assign them local chemical
called selectedchemical
, values don't stick , exc_bad_access
. when hover on selectedchemical.chemname
says, "out of scope".
i don't it.
#import <foundation/foundation.h> @interface chemical : nsobject { nsstring *chemname; nsstring *chemconcentration; float chemconstant; bool chemisliquid; } @property (nonatomic, retain) nsstring *chemname; @property (nonatomic, retain) nsstring *chemconcentration; @property float chemconstant; @property bool chemisliquid; - (id)initwithchemical:(nsstring *)chemical andconcentration:(nsstring *)concentration andconstant:(float)constant andisliquid:(bool)isliquid; @end
#import "chemical.h" @implementation chemical @synthesize chemname; @synthesize chemconcentration; @synthesize chemconstant; @synthesize chemisliquid; - (id)initwithchemical:(nsstring *)chemical andconcentration:(nsstring *)concentration andconstant:(float)constant andisliquid:(bool)isliquid { if((self = [super init])) { self.chemname = chemical; self.chemconcentration = concentration; self.chemconstant = constant; self.chemisliquid = isliquid; } return self; } @end
#import <uikit/uikit.h> #import "sourcepickerviewcontroller.h" #import "chemical.h" @interface adjustviewcontroller : uiviewcontroller <sourcepickerviewcontrollerdelegate>{ // ib controls uitextfield *sourcefield; uitextfield *volumefield; uilabel *startinglabel; uilabel *targetlabel; uitextview *advicelabel; // setup variables kind of chemical int numberofcomponents; nsdictionary *dictionaryofsources; // local ivars float percentremove; float gallonsremove; float selectedchemsourceamount; int delta; nsstring *selectedchemname; nsstring *selectedchemconcentration; float selectedchemconstant; bool selectedchemisliquid; nsstring *compositename; nsstring *messagebody; nsstring *advicemessage; } @property (nonatomic, retain) iboutlet uitextfield *sourcefield; @property (nonatomic, retain) iboutlet uitextfield *volumefield; @property (nonatomic, retain) iboutlet uilabel *startinglabel; @property (nonatomic, retain) iboutlet uilabel *targetlabel; @property (nonatomic, retain) iboutlet uitextview *advicelabel; @property (nonatomic, retain) nsstring *selectedchemname; @property (nonatomic, retain) nsstring *selectedchemconcentration; @property float selectedchemconstant; @property bool selectedchemisliquid; @property (nonatomic, retain) nsstring *compositename; @property (nonatomic, retain) nsstring *messagebody; @property (nonatomic, retain) nsstring *advicemessage; @property int numberofcomponents; @property (nonatomic, retain) nsdictionary *dictionaryofsources; - (ibaction)backgroundtap:(id)sender; - (ibaction)startingsliderchanged:(id)sender; - (ibaction)startingsliderfinishedchanging; - (ibaction)targetsliderchanged:(id)sender; - (ibaction)targetsliderfinishedchanging; - (ibaction)getchemicalsource; - (void)updateadvice; @end
#import "adjustviewcontroller.h" @implementation adjustviewcontroller @synthesize sourcefield; @synthesize volumefield; @synthesize startinglabel; @synthesize targetlabel; @synthesize advicelabel; @synthesize numberofcomponents; @synthesize dictionaryofsources; @synthesize compositename; @synthesize messagebody; @synthesize advicemessage; @synthesize selectedchemname; @synthesize selectedchemconcentration; @synthesize selectedchemconstant; @synthesize selectedchemisliquid; - (ibaction)backgroundtap:(id)sender { [sourcefield resignfirstresponder]; [volumefield resignfirstresponder]; [self updateadvice]; } - (ibaction)startingsliderchanged:(id)sender { uislider *slider = (uislider *)sender; int progressasint = (int)(slider.value + 0.5f); nsstring *newvalue = [[nsstring alloc] initwithformat:@"%d", progressasint]; startinglabel.text = newvalue; [newvalue release]; } - (ibaction)targetsliderchanged:(id)sender { uislider *slider = (uislider *)sender; int progressasint = (int)(slider.value + 0.5f); nsstring *newvalue = [[nsstring alloc] initwithformat:@"%d", progressasint]; targetlabel.text = newvalue; [newvalue release]; } - (ibaction)startingsliderfinishedchanging { // [self updateadvice]; } - (ibaction)targetsliderfinishedchanging { // [self updateadvice]; } // present picker chlorine selection - (ibaction)getchemicalsource { sourcepickerviewcontroller *sourcepickerviewcontroller = [[sourcepickerviewcontroller alloc] init]; sourcepickerviewcontroller.delegate = self; nslog(@"getchemicalsource setting numberofcomponents %d", self.numberofcomponents); sourcepickerviewcontroller.numberofcomponents = self.numberofcomponents; nslog(@"getchemicalsource sending numberofcomponents %d", sourcepickerviewcontroller.numberofcomponents); sourcepickerviewcontroller.dictionaryofsources = self.dictionaryofsources; [self presentmodalviewcontroller:sourcepickerviewcontroller animated:yes]; [sourcepickerviewcontroller release]; } - (void)updateadvice { nslog(@"--updateadvice"); nslog(@" selectedchemical name = %@", selectedchemname); nslog(@" selectedchemical concentration = %@", selectedchemconcentration); nslog(@" selectedchemical constant = %1.6f", selectedchemconstant); nslog(@" selectedchemical liquid = %d", selectedchemisliquid); // first check see if there source , volume, otherwise prompt user enter them if ([volumefield.text isequaltostring:@""] || [sourcefield.text isequaltostring:@""]) { advicemessage = @"enter source , volume."; } // if there source , volume, calculate! else { if ([selectedchemconcentration isequaltostring:@""]) { // if there's no concentration, make string name compositename = selectedchemname; nslog(@" compositename without concentration = %@", compositename); } else { // if there concentration, make string name , concentration , space between. compositename = [[nsstring alloc] initwithformat:@"%@ %@", selectedchemname, selectedchemconcentration]; nslog(@" compositename concentration = %@", compositename); } delta = [targetlabel.text intvalue] - [startinglabel.text intvalue]; // difference between target , starting levels nslog(@" delta = %d", delta); selectedchemsourceamount = delta * [volumefield.text intvalue] * selectedchemconstant; // calculates amount of source chemical necessary in ounces nslog(@" selectedchemsourceamount = %1.1f", selectedchemsourceamount); // if delta positive, add chemical if (delta > 0) { nslog(@">> delta > 0"); if (selectedchemisliquid) { if (selectedchemsourceamount > 128) { // amount more gallon selectedchemsourceamount = selectedchemsourceamount / 128; messagebody = [[nsstring alloc] initwithformat:@"to increase %@ %d ppm, add %1.1f gal of ", self.title, delta, selectedchemsourceamount]; } else { // less gallon messagebody = [[nsstring alloc] initwithformat:@"to increase %@ %d ppm, add %1.1f fl oz of ", self.title, delta, selectedchemsourceamount]; } } else { // chemical solid if (selectedchemsourceamount > 16) { // amount more pound selectedchemsourceamount = selectedchemsourceamount / 16; messagebody = [[nsstring alloc] initwithformat:@"to increase %@ %d ppm, add %1.1f lb of ", self.title, delta, selectedchemsourceamount]; } else { // less pound messagebody = [[nsstring alloc] initwithformat:@"to increase %@ %d ppm, add %1.1f oz of ", self.title, delta, selectedchemsourceamount]; } } advicemessage = [[nsstring alloc] initwithformat:@"%@%@.", messagebody, compositename]; } // if delta zero, stay course if (delta == 0) { nslog(@"== delta = 0"); advicemessage = @"you're on target. no action necessary."; } // if delta negative, remove water if (delta < 0) { nslog(@"<< delta < 0"); advicemessage = @"you're on target. remove water."; } } advicelabel.text = advicemessage; // set advice label [messagebody release]; // , rid of message [compositename release]; [advicemessage release]; } - (void)viewdidload { nslog(@"adjustviewcontroller launched"); sourcefield.text = @""; advicelabel.text = @""; percentremove = 0; gallonsremove = 0; delta = 0; selectedchemsourceamount = 0; // [self updateadvice]; [super viewdidload]; } - (void)didreceivememorywarning { // releases view if doesn't have superview. [super didreceivememorywarning]; // release cached data, images, etc aren't in use. } - (void)viewdidunload { sourcefield = nil; volumefield = nil; startinglabel = nil; targetlabel = nil; advicelabel = nil; dictionaryofsources = nil; [super viewdidunload]; // release retained subviews of main view. // e.g. self.myoutlet = nil; } - (void)dealloc { [sourcefield release]; [volumefield release]; [startinglabel release]; [targetlabel release]; [advicelabel release]; [dictionaryofsources release]; [super dealloc]; } #pragma mark - #pragma mark picker view delegate methods // returns values picker if source chosen - (void)sourcepickerviewcontroller:(sourcepickerviewcontroller *)controller didselectsource:(nsstring *)source andconcentration:(nsstring *)concentration andconstant:(float)constant andisliquid:(bool)isliquid { selectedchemname = source; selectedchemconcentration = concentration; selectedchemconstant = constant; selectedchemisliquid = isliquid; // update source textfield. if concentration empty, use source otherwise concatenate them if ([selectedchemconcentration isequaltostring:@""]) { sourcefield.text = [[nsstring alloc] initwithformat:@"%@", selectedchemname]; } else { sourcefield.text = [[nsstring alloc] initwithformat:@"%@ %@", selectedchemname, selectedchemconcentration]; } // [self updateadvice]; nslog(@"returned source = %@, concentration = %@, constant = %1.7f, isliquid = %d", source, concentration, constant, isliquid); nslog(@"selectedchemical.chemname = %@, chemconcentration = %@, chemconstant = %1.7f, chemisliquid = %d", selectedchemname, selectedchemconcentration, selectedchemconstant, selectedchemisliquid); [self dismissmodalviewcontrolleranimated:yes]; } // returns picker without choosing new source - (void)sourcepickerviewcontroller:(sourcepickerviewcontroller *)controller didselectcancel:(bool)didcancel { // [self updateadvice]; nslog(@"returned without selecting source"); [self dismissmodalviewcontrolleranimated:yes]; } @end
you have few problems won't end solving this
- as mentioned, init needs call [super init]
- classes have retained properties need dealloc message sets them nil
and things might help
what messagebody? release it, allocated if delta > 0. should release if alloc. use , don't need release
messagebody = [nsstring stringwithformat:@"to increase %@ %dppm, add %1.1f gal of ", self.title, delta, sourceamount];
same compositename -- alloc , assign property. should release if alloc or retain (or call method you). use stringwithformat in else, , don't release
same advicemessage -- alloc, , not, release.
please read learn memory rules iphone:
http://loufranco.com/blog/files/managing-memory-iphone.html
i wrote people debug exc_bad_access
http://loufranco.com/blog/files/understanding-exc_bad_access.html
Comments
Post a Comment