ios - How to return a value from a function that is generated from a parse query within the function? -
problem: when call below function within viewcontroller tableview cellforrowatindexpath method, nil, need set generated object pfobject variable called rankobject declared globally in viewcontroller. i've tried lot of things, including completion handlers, , still stuck. how accomplish task?
func getormakerankrelations(sound: pfobject) { var rankrelation = sound.relationforkey("userranks") let currentuser = pfuser.currentuser()! var relationquery = rankrelation.query() relationquery?.wherekey("user", equalto: currentuser) relationquery?.findobjectsinbackgroundwithblock { (theobject: [anyobject]?, error: nserror?) -> void in if (theobject?.isempty == true) { println("rank object empty") //make ranking pfobject var ranking = pfobject(classname: "ranking") ranking["user"] = pfuser.currentuser()! ranking["rank"] = 0 //upload ranking parse ranking.saveinbackgroundwithblock { (saved: bool, error: nserror?) -> void in if saved { println("saved ranking") //add relation between sound , ranking rankrelation.addobject(ranking) sound.saveinbackgroundwithblock { (saved: bool, error: nserror?) -> void in if saved { println("saved relation") var theobject = (theobject![0] as? pfobject)! self.rankobject = theobject //////////note: variable saves while in closure ///////////// } else { println("relation not saved :(") } } } else { println(error) } } } else { var theobject = (theobject![0] as? pfobject)! self.rankobject = theobject //////////note: variable saves while in closure ///////////// } } }
here how call function in tableview:
getormakerankrelation(sound)
not dealing specifics of asynch call, fact asynchronous, in objective-c (and swift) declare function take @ least 2 parameters: whatever needed parameterize remote request, , block run when request completes.
reading code, i'd advise breaking , create part own functions, remain sane, so...
- (void)getorcreaterankforsound:(pfobject *)sound completion:(void (^)(pfobject *, nserror *))completion { [self getrankforsound:sound completion:^(pfobject *rank, nserror *error) { if (!rank && !error) { // there's no rank, , no error either, must create 1 [self createrankforsound:sound completion:^(pfobject *rank, nserror *error) { completion(rank, error); }]; } else { completion(rank, error); } }]; } - (void)createrankforsound:(pfobject *)sound completion:(void (^)(pfobject *, nserror *))completion { // build pfobject rank sound, save , tell our // caller happened invoking completion block // ... [newlycreatedrank saveinbackgroundwithblock:^(bool success, nserror *error) { return (success)? completion(newlycreatedrank, nil) : completion(nil, error); }]; }
now cellforrowatindexpath can safely call method, because caches results.
// pseudo code in cellforrowatindexpath pfobject *sound = self.mydatasourcearray[indexpath.row]; // want change cell subview present rank object // don't make network requests in method without caching result // assume have dictionary of rank objects indexed sound object id correspond pfobject *rank = self.ranksforsound[sound.objectid]; if (rank) { // no need make network request, use rank, presumably update cell cell.ranklabel.text = // function of rank } else { // need make network request, put placeholder value in cell , call our function cell.ranklabel.text = // placeholder value [self getorcreaterankforsound:sound completion:^(pfobject *rank, nserror *error) { // important, cell might have scrolled away time block runs // don't alter cell directly, reload it. cellforrowatindexpath // called again, cache primed if (!error) { [tableview reloadrowsatindexpaths:@[indexpath]]; } }]; } // configure other parts of cell return cell;
Comments
Post a Comment