In iOS, cllocationmanager locates the problem that causes memory access errors multiple times.

Source: Internet
Author: User
Tags call back

I haven't written anything for several months. Today I have time to write something about IOs (I found myself very unfocused, and I didn't do a good job in Android, and I switched to iOS again ).

In my program, the function of getting the user's current location address is provided. I wrote an auxiliary locationhelper class for positioning. In this class, cllocationmanager is called to take over the didupdatetolocation event to obtain the longitude and latitude coordinates, and then send a coordinate request to the background to return the address. In use, I create a locationhelper class in a viewcontroller and pass the viewcontroller as the lochandler's delegate to the past. When the coordinates are obtained, the positioning function is immediately stopped and the background request is sent to the return address, after obtaining the address, call back the lochandler method to complete the address Locating Process. In this process, the program will display a positioning progress bar that does not allow user operations until the positioning is complete to obtain the address. Locationhelper will be maintained by viewcontroller until the viewcontroller is released.

The approximate class definition of locationhelper is as follows:

@ Implementation locationhelper @ synthesize lochandler;-(ID) initlocationhelper :( id <mylocationdelegate>) handler {self = [Super init]; self. lochandler = handler; locationman = [[cllocationmanager alloc] init]; locationman. delegate = self; [locationman startupdatinglocation]; return self;}-(void) locationmanager :( cllocationmanager *) manager didupdatetolocation :( cllocation *) newlocation fromlocation :( cllocation *) oldlocation {// obtain the latitude and longitude cllocationcoordinate2d coordinate = newlocation. coordinate; cllocationdegrees latitude = coordinate. latitude; cllocationdegrees longpolling = coordinate. longpolling; [locationman stopupdatinglocation]; geoaddresshelper * gah = [[geoaddresshelper alloc] initwithgeox: longpolling andgeoy: latitude andresultdelegate: Self]; self. curgah = gah; [gah release];}-(void) ongeoaddressfound :( nsobject *) RES {[lochandler locationhelperfoundaddress: res];} @ end

Geoaddresshelper converts the longitude and latitude to a Chinese address through a network request:

@implementation GeoAddressHelper@synthesize eventDelegate,geoX,geoY;-(void)initWithGeoX:(double)x andGeoY:(double)y andResultDelegate:(NSObject*)evtDlg{    self.eventDelegate=evtDlg;        geoX=x;    geoY=y;        NSMutableString * url=(NSMutableString*)[MyApp getServerHttpUrl:@"opId=7100017"];    [url appendFormat:@"&x=%.6f&y=%.6f",x,y];        NetReqOperation * req=[[NetReqOperation alloc] initWithURL:url withDelegate:self];    [[MyApp netReqQueue] addOperation:req];    [req release];}- (void)OnNetReqFinished:(NSObject *)res{    [eventDelegate performSelectorOnMainThread:@selector(OnGeoAddressFound:) withObject:res waitUntilDone:YES];}@end

 

However, for the two seemingly simple classes, memory address errors (unrecognizable selector and so on) may occur from time to time, leading to program crash. The error stack is as follows:

-[__NSCFSet OnGeoAddressFound:]: unrecognized selector sent to instance 0xf678640(null)(0   CoreFoundation    0x340848d7 __exceptionPreprocess + 1861   libobjc.A.dylib   0x342d41e5 objc_exception_throw + 322   CoreFoundation    0x34087acb -[NSObject doesNotRecognizeSelector:] + 1743   CoreFoundation    0x34086945 ___forwarding___ + 3004   CoreFoundation    0x33fe1680 _CF_forwarding_prep_0 + 485   Foundation        0x359ce1b7 -[NSObject(NSThreadPerformAdditions) performSelector:onThread:withObject:waitUntilDone:modes:] + 2666   Foundation        0x359cde49 -[NSObject(NSThreadPerformAdditions) performSelectorOnMainThread:withObject:waitUntilDone:] + 1367   AutoTraffic2012   0x001232db -[GeoAddressHelper OnNetReqFinished:] + 5028   Foundation        0x359ce1b7 -[NSObject(NSThreadPerformAdditions) performSelector:onThread:withObject:waitUntilDone:modes:] + 2669   Foundation        0x359cde49 -[NSObject(NSThreadPerformAdditions) performSelectorOnMainThread:withObject:waitUntilDone:] + 13610  AutoTraffic2012   0x0011170f -[NetReqOperation OnNetReqFinished:] + 10611  CoreFoundation    0x33fe322b -[NSObject performSelector:withObject:] + 4212  Foundation        0x35a6e757 __NSThreadPerformPerform + 35013  CoreFoundation    0x34058b03 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 1414  CoreFoundation    0x340582cf __CFRunLoopDoSources0 + 21415  CoreFoundation    0x34057075 __CFRunLoopRun + 65216  CoreFoundation    0x33fda4dd CFRunLoopRunSpecific + 30017  CoreFoundation    0x33fda3a5 CFRunLoopRunInMode + 10418  GraphicsServices  0x3085efcd GSEventRunModal + 15619  UIKit             0x3745b743 UIApplicationMain + 1090)

 

From the error stack, it is clear that locationhelper is released. However, because locationhelper is referenced by viewcontroller and viewcontroller is displaying a positioning progress bar during this period, operations cannot exit. Therefore, it is theoretically impossible to be released in advance. This error is not easy to reproduce. I have been studying the code for a long time and have not found out where the writing is wrong.

After a lot of tests, we found that there was such a rule: if the program is often used, this error is not easy to appear; if the operation is slow, it is not easy to make a mistake; but if you leave your phone idle for a while, in addition, the interface switching speed is faster, so this error is very likely to occur during the first use.

After a period of idle time, what is the difference between program usage and normal usage? I think it may be related to the first positioning. When operating on a map, a rough location is often displayed for the first time, and a more precise location is displayed later. This may trigger two didupdatetolocation events consecutively, resulting in errors; the subsequent positioning may be a single positioning. In the Code, when the first position is successful, I have immediately called stopupdatinglocation to stop the position scan. Theoretically, the position will not be triggered again, so I have never thought about it.

However, the actual situation seems to be different from the imagination. From the symptom, it is likely that didupdatetolocation is triggered twice. So I added a locfired ID to the locationhelper. Once triggered, the ID is set to yes immediately and will not be processed again. After such processing, the error disappears.

Originally, stopupdatinglocation does not necessarily stop positioning immediately. After I obtained the coordinates of longitude and latitude for the first time and completed the address query, the positioning progress bar on viewcontroller disappears and allowed the operation. At this time, the locatipnhelper did not completely stop scanning, the didupdatetolocation event was triggered again, and a request for coordinates was initiated; at this time, viewcontroller may immediately be closed and released by pop when the user is fast, and locationhelper is also released, resulting in a memory access error caused by geoaddresshelper callback locationhelper when the request is complete. The problem is solved by setting a flag to prevent the second trigger.

Some people will say that, since geoaddresshelper references locationhelper, why not increase the reference count of locationhelper to prevent it from being automatically released? In fact, I did the same for the first time, but this caused another problem, so I did not add a reference later. I will explain the details in the next article.

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.