ios - NSMutableArray data sorting by a distance -


have problem mutablearray. i've data array in tableview, , ok, when data sorting distance , i'm choosing item in cell, shows me incorrect data in new viewcontroller. shows data without sorting. it's broken link) hope help)

i'm new in obj-c, apologise)

here code:

       list = [[nsmutablearray alloc] init];          [list addobject:@{@"name": @"central office", @"address":@"наб. Обводного канала, д.66А", @"phone":@"+7 (812) 320-56-21 (многоканальный)", @"worktime":@"ПН-ПТ: с 9:30 до 18:30", @"email":@"mail@ibins.ru", @"payment":@"Принимаются к оплате пластиковые карты visa и mastercard", @"longitude":@30.336842, @"latitude":@59.913950}];          [list addobject:@{@"name": @"second office", @"address":@"ул. Камышовая, д.38", @"phone":@"+7 (812) 992-992-6; +7 (812) 456-26-43", @"worktime":@"Ежедневно: с 9:30 до 20:00", @"email":@"sever@ibins.ru", @"payment":@"Принимаются к оплате пластиковые карты visa и mastercard", @"longitude":@30.219863, @"latitude":@60.008805}];          [list addobject:@{@"name": @"third office", @"address":@"street name", @"phone":@"phone number", @"worktime":@"work time", @"email":@"email address", @"longitude":@30.294254, @"latitude":@60.028728}];       [self constructlist];     [self constructpins];     }    - (ibaction)switchdisplaytype:(id)sender {     [uiview beginanimations:@"view flip" context:nil];     [uiview setanimationduration:0.80];     [uiview setanimationcurve:uiviewanimationcurveeaseinout];     [uiview setanimationtransition:uiviewanimationtransitionflipfromright forview:self.view cache:no];     [uiview commitanimations];      if ([(uisegmentedcontrol*)sender selectedsegmentindex] == 1) {         map.hidden = yes;         contentsv.hidden = no;     }     else {         map.hidden = no;         contentsv.hidden = yes;     } }  - (mkannotationview *)mapview:(mkmapview *)mapview viewforannotation:(id <mkannotation>)annotation {     static nsstring* bridgeannotationidentifier = @"bridgeannotationidentifier";      mkpinannotationview* custompinview = [[[mkpinannotationview alloc]                                            initwithannotation:annotation reuseidentifier:bridgeannotationidentifier] autorelease];     custompinview.pincolor = mkpinannotationcolorred;     custompinview.animatesdrop = yes;     custompinview.canshowcallout = yes;      uibutton* rightbutton = [uibutton buttonwithtype:uibuttontypedetaildisclosure];    // nslog(@"%@",rightbutton);     [rightbutton addtarget:self                     action:@selector(annotationbuttontapped:)           forcontrolevents:uicontroleventtouchupinside];     custompinview.rightcalloutaccessoryview = rightbutton;     return custompinview;//[kml viewforannotation:annotation]; }  - (void)annotationbuttontapped:(id)sender {     detailvc *samplevc = [[detailvc alloc] initwithnibname:@"detailvc" bundle:[nsbundle mainbundle]];     [self.navigationcontroller pushviewcontroller:samplevc animated:yes];     [samplevc release];      (nsdictionary *dict in list) {         if ([[dict valueforkey:@"name"] isequaltostring:selectedanntitle]) {             [samplevc updateviewwithdict:dict];         }     } }    - (void)constructpins {     (nsdictionary *dict in list) {         mkcoordinateregion region;         mkcoordinatespan span;         span.latitudedelta = 0.3;         span.longitudedelta = 0.3;          cllocationcoordinate2d location;          location.latitude = [[dict valueforkey:@"latitude"] floatvalue];         location.longitude = [[dict valueforkey:@"longitude"] floatvalue];          if (location.latitude == 0.0 && location.longitude == 0.0)             return;          region.span = span;         region.center = location;          mkpointannotation *point = [[mkpointannotation alloc] init];         point.coordinate = location;         point.title = [dict valueforkey:@"name"];          [map addannotation:point];         [map setregion:region animated:yes];     } }  - (void)constructlist {     int n = 0;     (nsdictionary *dict in list) {         uiview *container = [[uiview alloc] initwithframe:cgrectmake(0, 100*n, 320, 100)];         container.backgroundcolor = [uicolor whitecolor];          uibutton *button = [[uibutton alloc] initwithframe:cgrectmake(0, 0, 320, 100)];         button.tag = n;         [button addtarget:self action:@selector(buttontapped:) forcontrolevents:uicontroleventtouchupinside];         [container addsubview:button];           nsstring *str = [nsstring stringwithformat:@"%@\naddress: %@\nphone: %@\nwork time: %@", [dict valueforkey:@"name"], [dict valueforkey:@"address"], [dict valueforkey:@"phone"], [dict valueforkey:@"worktime"]];         uilabel *namelabel = [[uilabel alloc] initwithframe:cgrectmake(10, 10, 300, 80)];         namelabel.textalignment = nstextalignmentleft;         namelabel.numberoflines = 0;         namelabel.text = str;         namelabel.font = [uifont fontwithname:@"helveticaneue" size:12.0];         [container addsubview:namelabel];           uiview *separator = [[uiview alloc]initwithframe:cgrectmake(0, 99, 320, 1)];         separator.backgroundcolor = [uicolor darkgraycolor];         [container addsubview:separator];           [contentsv addsubview:container];           n++;         contentsv.contentsize = cgsizemake(0, 100*n);     } }  - (float)distancebetweenlat1:(float)tlat1 lon1:(float)tlon1 lat2:(float)tlat2 lon2:(float)tlon2 {     float result = 0.0;     int r = 6371;      float currentlatitude = tlat1;     float currentlongtitude = tlon1;      float lat2 = tlat2;     float lon2 = tlon2;      float dlat = (lat2-currentlatitude)*m_pi/180;     float dlon = (lon2-currentlongtitude)*m_pi/180;     float nllat = currentlatitude*m_pi/180;     lat2 = lat2*m_pi/180;      float = sin(dlat/2) * sin(dlat/2) +  sin(dlon/2) * sin(dlon/2) * cos(nllat) * cos(lat2);     float c = 2 * atan2(sqrt(a), sqrt(1-a));     result = r * c;      return result; }  - (void)mapview:(mkmapview *)mapview didselectannotationview:(mkannotationview *)view {     selectedanntitle = [view.annotation title];      return;      detailvc *samplevc = [[detailvc alloc] initwithnibname:@"detailvc" bundle:[nsbundle mainbundle]];     [self.navigationcontroller pushviewcontroller:samplevc animated:yes];       nsstring *ttl = [view.annotation title];      (nsdictionary *dict in list) {         if ([[dict valueforkey:@"name"] isequaltostring:ttl]) {             [samplevc updateviewwithdict:dict];         }     }      [map deselectannotation:view.annotation animated:no]; }  - (void)buttontapped:(id)sender {     detailvc *samplevc = [[detailvc alloc] initwithnibname:@"detailvc" bundle:[nsbundle mainbundle]];     [self.navigationcontroller pushviewcontroller:samplevc animated:yes];       int n = 0;     (nsdictionary *dict in list) {         if (n == [sender tag]) {             [samplevc updateviewwithdict:dict];         }         n++;     } }  - (void)mapview:(mkmapview *)mapview didupdateuserlocation:(mkuserlocation *)userlocation {     nslog(@"didupdateuserlocation");      mkannotationview* annotationview = [mapview viewforannotation:userlocation];     annotationview.canshowcallout = no;      if (!userlocationupdated) {         if (userlocation.coordinate.latitude > 0.1 && userlocation.coordinate.longitude > 0.1) {          //   nslog(@"sort distance");              userlocationupdated = yes;              (int = 0; < [list count]; i++) {                 nsmutabledictionary *record = [[nsmutabledictionary alloc] initwithdictionary:[list objectatindex:i]];                  float latitude = [[record valueforkey:@"latitude"] floatvalue];                 float longitude = [[record valueforkey:@"longitude"] floatvalue];                  float dist = [self distancebetweenlat1:map.userlocation.coordinate.latitude lon1:map.userlocation.coordinate.longitude lat2:latitude lon2:longitude];                 nsnumber *distn = [nsnumber numberwithfloat:dist];                 [record setobject:distn forkey:@"distance"];                [list replaceobjectatindex:i withobject:record];             }              nssortdescriptor *descriptor = [[nssortdescriptor alloc] initwithkey:@"distance" ascending:yes];             nsarray *itemslistsorted = [[nsarray alloc] initwitharray:list];             itemslistsorted = [itemslistsorted sortedarrayusingdescriptors:[nsarray arraywithobjects:descriptor,nil]];              (uiview *view in contentsv.subviews) {                 [view removefromsuperview];             }              (int = 0; < [itemslistsorted count]; i++) {                 uiview *container = [[uiview alloc] initwithframe:cgrectmake(0, 100*i, 320, 100)];                 container.backgroundcolor = [uicolor whitecolor];                  uibutton *button = [[uibutton alloc] initwithframe:cgrectmake(0, 0, 320, 100)];                 button.tag = i;                 [button addtarget:self action:@selector(buttontapped:) forcontrolevents:uicontroleventtouchupinside];                 [container addsubview:button];                   nsstring *str = [nsstring stringwithformat:@"%@\naddress: %@\nphone: %@\nworktime: %@", [[itemslistsorted objectatindex:i] valueforkey:@"name"], [[itemslistsorted objectatindex:i] valueforkey:@"address"], [[itemslistsorted objectatindex:i] valueforkey:@"phone"], [[itemslistsorted objectatindex:i] valueforkey:@"worktime"]];                 uilabel *namelabel = [[uilabel alloc] initwithframe:cgrectmake(10, 10, 300, 80)];                 namelabel.textalignment = nstextalignmentleft;                 namelabel.numberoflines = 0;                 namelabel.text = str;                 namelabel.font = [uifont fontwithname:@"helveticaneue" size:12.0];                 [container addsubview:namelabel];                   uilabel *distancelabel = [[uilabel alloc] initwithframe:cgrectmake(10, 2, 300, 21)];                 distancelabel.textalignment = nstextalignmentright;                 distancelabel.text = [nsstring stringwithformat:@"%.1f км", [[[itemslistsorted objectatindex:i] valueforkey:@"distance"] floatvalue]];                 distancelabel.font = [uifont fontwithname:@"helveticaneue" size:12.0];                 distancelabel.textcolor = [uicolor lightgraycolor];                 [container addsubview:distancelabel];                   uiview *separator = [[uiview alloc]initwithframe:cgrectmake(0, 99, 320, 1)];                 separator.backgroundcolor = [uicolor darkgraycolor];                 [container addsubview:separator];                   [contentsv addsubview:container];                   contentsv.contentsize = cgsizemake(0, 100*(i+1));             }         }     } }  - (void)didreceivememorywarning {     [super didreceivememorywarning]; }  @end 

although there numerous issues code (the least of minor precision issues distance calculation), the problem not distance calculation.

the detail view controller shows incorrect data because given data list array not sorted distance.

in didupdateuserlocation delegate method, contents of list copied local array named itemslistsorted.

only itemslistsorted array sorted distance , display updated using local array.

but original list array (which buttontapped method uses source of data send detail view controller) never updated.

so if "central office" @ index 0 in list gets moved index 2 in itemslistsorted, display shows correct position when tap on it, buttontapped method sends item @ index 2 list array not have "central office" (it's still @ index 0 in list).


1 way fix problem stop using local array , sort list array directly.

in didupdateuserlocation, replace these 2 lines:

nsarray *itemslistsorted = [[nsarray alloc] initwitharray:list]; itemslistsorted = [itemslistsorted sortedarrayusingdescriptors:[nsarray arraywithobjects:descriptor,nil]]; 

with this:

[list sortusingdescriptors:[nsarray arraywithobjects:descriptor,nil]]; 

and replace references itemslistsorted in same method list.



regarding other issues code, there not enough room point them out or explain them in 1 answer. however, here few highlights:

  • instead of manually creating "table view", use actual uitableview.
  • instead of manually calculating distance between coordinates, use distancefromlocation method in cllocation class or mkmetersbetweenmappoints function.
  • in viewforannotation, should return nil if annotation of type mkuserlocation otherwise appear red pin others.
  • use arc instead of manual memory management.

Comments

Popular posts from this blog

PHPMotion implementation - URL based videos (Hosted on separate location) -

javascript - Using Windows Media Player as video fallback for video tag -

c# - Unity IoC Lifetime per HttpRequest for UserStore -