i'm trying refresh map view , load new data server when device acquires user location. here's i'm doing:
- (void)viewdidload { cgrect bounds = self.view.bounds; mapview = [[mkmapview alloc] initwithframe:bounds]; mapview.showsuserlocation=yes; mapview.delegate=self; [self.view insertsubview:mapview atindex:0]; [self refreshmap]; } - (void)mapview:(mkmapview *)themapview didupdateuserlocation:(mkuserlocation *)userlocation { //this avoid frequent updates, need 1 position , don't need continuously track user's location if (userlocation.location.horizontalaccuracy > self.myuserlocation.location.horizontalaccuracy) { self.myuserlocation = userlocation; cllocationcoordinate2d centercoord = { userlocation.location.coordinate.latitude, userlocation.location.coordinate.longitude }; [themapview setcentercoordinate:centercoord zoomlevel:10 animated:yes]; [self refreshmap]; } } - (void)refreshmap { [[uiapplication sharedapplication] setnetworkactivityindicatorvisible:yes]; [self.mapview removeannotations:self.mapview.annotations]; //default position nsstring *lat = @"45.464161"; nsstring *lon = @"9.190336"; if (self.myuserlocation != nil) { lat = [[nsnumber numberwithdouble:myuserlocation.coordinate.latitude] stringvalue]; lon = [[nsnumber numberwithdouble:myuserlocation.coordinate.longitude] stringvalue]; } nsstring *url = [[nsstring alloc] initwithformat:@"http://myserver/geo_search.json?lat=%@&lon=%@", lat, lon]; nsurlrequest *therequest=[nsurlrequest requestwithurl:[nsurl urlwithstring:url] cachepolicy:nsurlrequestuseprotocolcachepolicy timeoutinterval:60.0]; [[nsurlconnection alloc] initwithrequest:therequest delegate:self]; [url release]; [[uiapplication sharedapplication] setnetworkactivityindicatorvisible:no]; } i have - (void)connection:(nsurlconnection *)connection didreceivedata:(nsdata *)data, create , add annotations.
here's happens: location after while, loaded data close default location. location , should remove old annotations , add new ones, instead keep seeing old annotations , new ones added anyway (let's receive 10 annotations each time, means have 20 on map when should have 10).
what doing wrong?
ok might little long worked me , hope you. app used share different traffic status reports between drivers.
i had problem also, tried load annotations server, delete them , reload annotations array map every time user sends annotation server himself/presses "refresh" button/every 1.5 minutes - have current set.
so thought might have time interval takes load new annotations server, or array itself, later realized might connected way entire code organized , maybe things got in way/timing of others.
what did moving [self.map addannotations:an array of annotations] command main thread , whole loading process back, used temp array instead of "self.map.annotations" delete current annotations, worked ok afterwards left :), though i'm not world-class expert (not close) , i'm sure others might have more professional , efficient solution, code sample:
//this in viewdidload, kicks off whole process [self performselectorinbackground:@selector(retrieveannotationsdatafromserver) withobject:self]; //this method loading data -(void)retrieveannotationsdatafromserver { nsautoreleasepool *pool=[[nsautoreleasepool alloc]init]; //code loading.. nsurl *url=[nsurl urlwithstring:@"http://your server name here"]; nsstring *result=[nsstring stringwithcontentsofurl:url encoding:4 error:nil]; nslog(@"%@",result); nsdata *data = [nsdata datawithcontentsofurl:url]; nsxmlparser *parser = [[nsxmlparser alloc]initwithdata:data]; [parser setdelegate:self]; [parser parse]; //inside parser delegate take each element of report , store in mutable array create annotations later (report title, report description/subtitle, report location longitude , report location latitude) [pool drain]; nslog(@"retrieveannotatinsdatafromserver pool drained"); } //now, in case last thing happen before pool drained parser`s "didenddocument" method gonna called, delayed loading this: - (void)parserdidenddocument:(nsxmlparser *)parser { nslog(@"parser - document ended, creating annotationsarray"); nslog(@"this size of ra array:%d",[self.recievedtitles count]); (int i=0;i<[self.recievedtitles count];i++) { //rc=recieved coordinate //ra=recieved annotation cllocationcoordinate2d rc; rc.latitude=[[self.recievedlatitude objectatindex:i] doublevalue]; rc.longitude=[[self.recievedlongitude objectatindex:i] doublevalue]; if([self.recievedtitles objectatindex:i]==nil) continue; annotation *ra=[[annotation alloc]initwithcoordinate:rc andtitle:[self.recievedtitles objectatindex:i] andsubtitle:[self.recievedsubtitles objectatindex:i]]; //the "self.annotationsarray" array use hold current set retrieved server [self.annotationsarray addobject:ra]; [ra autorelease]; nslog(@"ra %d inserted",i); } nslog(@"data retrieving ended, loading annotations map"); [self performselectoronmainthread:@selector(addannotations) withobject:self waituntildone:no]; } //this method defined apply in main thread instead of in background whole loading process.. i'm sure can done better. -(void)addannotations { [self.map addannotations:self.annotationsarray]; nslog(@"annotations loaded map"); } //now have retrieved them server first time, reloading , refreshing part comes next, method called time user press refresh, sends report sever, or automatically every 1.5 minutes: -(void)refreshmap { nsarray *annotationstodelete=[[nsarray alloc] initwitharray:self.annotationsarray]; [self.map removeannotations:annotationstodelete]; [annotationstodelete release]; [self performselectorinbackground:@selector(retrieveannotationsdatafromserver) withobject:self]; } please comment on answer since happy learn less complicated way of solving matter.
i think of these type of problems have been solved if there way "wait until done" when using background threads, because happens code continues run forward before whole process of downloading-parsing-creating annotation-loading map process finished.
Comments
Post a Comment