iphone - Sending data from my detail view back to my UITableView -
first of all, thank god stack overflow. new @ objective-c/cocoa/iphone development, , site amazing aid.
i have window, has tab bar, has navigation controller, loads uitableviewcontroller. clicking "add" button on navigation bar (created programatically), pushes uitableviewcontroller so:
invoiceaddviewcontroller *addcontroller = [[invoiceaddviewcontroller alloc] initwithnibname:@"invoiceaddviewcontroller" bundle:[nsbundle mainbundle]]; [self.navigationcontroller pushviewcontroller:addcontroller animated:yes];
this table view controller pushes it's own detail view:
uitableviewcell *targetcell = [self.tableview cellforrowatindexpath:indexpath]; generictextfielddetailviewcontroller *dvcontroller = [[generictextfielddetailviewcontroller alloc] initwithnibname:@"generictextfielddetailviewcontroller" bundle:[nsbundle mainbundle]]; dvcontroller.fieldname = targetcell.textlabel.text; dvcontroller.fieldvalue = targetcell.detailtextlabel.text; [self.navigationcontroller pushviewcontroller:dvcontroller animated:yes]; [dvcontroller release];
the concept being, click on cell in table view controller such "notes". pushes "generictextfielddetailviewcontroller" name of "field" clicked, , value (if 1 exists). allows me reuse detail view rather creating 1 ad nauseum every field.
in order push data back, created method on "add" uitableviewcontroller:
- (void) updatefield:(nsstring*) fieldname value:(nsstring*) fieldvalue { uitableviewcell *targetcell; if([fieldname isequaltostring:@"invoice id"]) { nsuinteger indexarr[] = {1,1}; targetcell = [[self tableview] cellforrowatindexpath:[nsindexpath indexpathwithindexes:indexarr length:2]]; targetcell.detailtextlabel.text = fieldvalue; } else if([fieldname isequaltostring:@"p.o. number"]) { nsuinteger indexarr[] = {1,2}; targetcell = [[self tableview] cellforrowatindexpath:[nsindexpath indexpathwithindexes:indexarr length:2]]; targetcell.detailtextlabel.text = fieldvalue; } else if([fieldname isequaltostring:@"add note"]) { nsuinteger indexarr[] = {3,0}; targetcell = [[self tableview] cellforrowatindexpath:[nsindexpath indexpathwithindexes:indexarr length:2]]; targetcell.detailtextlabel.text = fieldvalue; } }
this method designed receive data push method in "generic":
- (ibaction)savefield:(id)sender { self.fieldvalue = thetextfield.text; invoiceaddviewcontroller *parentcontroller = (invoiceaddviewcontroller*)self.view.superview; [parentcontroller updatefield:self.fieldname value:self.fieldvalue]; }
which brings problem: when save method fires off, throws invalid selector error because self.view.superview not uitableview pushed "generic" detail view.
i have tried following combinations (from gdb):
(gdb) po [[self view] superview] <uiviewcontrollerwrapperview: 0x4b6d4d0; frame = (0 64; 320 367); autoresize = w+h; layer = <calayer: 0x4b6c090>> (gdb) po [[self navigationcontroller] parentviewcontroller] <uitabbarcontroller: 0x4d2fa90> (gdb) po [self parentviewcontroller] <uinavigationcontroller: 0x4d2fdc0>
i feel i'm landing around uitableview want invoke, can't find it.
what doing wrong?
refrains pulling more hair out
the problem confusing view hierarchy navigation stack. detail view controller wants send message controller pushed on stack, second last object in navigation controller's viewcontrollers array.
try changing savefield: method to:
- (ibaction)savefield:(id)sender { self.fieldvalue = thetextfield.text; nsarray *navigationstack = self.navigationcontroller.viewcontrollers; invoiceaddviewcontroller *parentcontroller = (invoiceaddviewcontroller*)[navigationstack objectatindex:navigationstack.count - 2]; [parentcontroller updatefield:self.fieldname value:self.fieldvalue]; }
edit: should note design brittle. better way apply model-view-controller , create object represents field , title value. invoiceaddviewcontroller can pass instances of these objects detail controller, , detail controller changes them, these changes can reflected in other controllers.
edit 2: here hint of how work.
uitableviewcell *targetcell = [self.tableview cellforrowatindexpath:indexpath]; generictextfielddetailviewcontroller *dvcontroller = [[generictextfielddetailviewcontroller alloc] initwithnibname:@"generictextfielddetailviewcontroller" bundle:[nsbundle mainbundle]]; dvcontroller.dataobject = [self dataobjectforindexpath:indexpath]; [self.navigationcontroller pushviewcontroller:dvcontroller animated:yes]; [dvcontroller release];
i'm assuming you've implemented dataobjectforindexpath: method. presumably tableview:cellforrowatindexpath: use method configure cells.
now, can eliminate both savefield: , updatefield: methods. in invoiceaddviewcontroller, viewwillappear: used refresh view this:
- (void)viewwillappear:(bool)animated { [super viewwillappear:animated]; [self.tableview reloaddata] }
there whole world of possibilities here. reloaddata heavy handed one. experiment stuff kvo make more automatic.
in detail controller, of course, don't forget update object, in view disappear
self.dataobject.fieldvalue = thetextfield.text;
this started. there lot of possibilities , details consider. should @ lot of sample code, pattern gets used lot. coredatabooks example on developer portal uses similar pattern, there others.
Comments
Post a Comment