تحسين CLLocationManager/CoreLocation لاسترداد نقاط البيانات بشكل أسرع على iPhone

StackOverflow https://stackoverflow.com/questions/1081219

سؤال

أنا أستخدم حاليًا CoreLocation + CLLocationManager لمقارنة الموقع الحالي للمستخدمين بعدد N من المواقع الأخرى.المشكلة التي أواجهها هي أنني أتعامل مع مناطق حضرية تكون فيها المواقع قريبة من بعضها البعض، لذلك أحتاج إلى تحديد موقع المستخدم بدقة بقدر ما يسمح به الجهاز دون التضحية بالكثير من الوقت.حساباتي دقيقة للغاية، والمشكلة هي أن جمع 10 عينات يستغرق وقتًا طويلاً للغاية.سأقوم بلصق الكود الخاص بالمرشحات/الدقة أدناه.إذا كان بإمكان أي شخص التعليق على كيفية تسريع هذا الأمر، فسيكون ذلك رائعًا.وإلى أن أقوم بتسريع الأمر، فهو غير مفيد إلى حد ما في تطبيقي حيث يستغرق جمع المعلومات حاليًا حوالي 3-4 دقائق، وهي مدة لا تقبلها الفئة الديموغرافية المستهدفة.

الكود يبدو كالتالي:

[self.locationManager setDistanceFilter:kCLDistanceFilterNone];
[self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
    if (newLocation.horizontalAccuracy > 0.0f &&
        newLocation.horizontalAccuracy < 120.0f) { // roughly an accuracy of 120 meters, we can adjust this.

    [myLocs addObject:newLocation];
}

شكرًا على أي حيل تحسينية لتسريع هذا الأمر.

هل كانت مفيدة؟

المحلول

ولقد كان الكثير من القضايا مع CLLocationManager على اي فون أيضا. من تطبيقات مختلفة، والتجربة والخطأ وهذا هو ما كنت أحسب؛

1) استخدام فئة المفردة لlocationManager، ONLY ONE مثيل، اتبع الأمثلة في:

وأبل LocateMe سبيل المثال

وTweetero: http://tweetero.googlecode.com/svn/trunk

وأنا أفكر هل يمكن أن يكون فقط مدير موقع واحد قيد التشغيل، هناك فقط رقاقة GPS واحد في اي فون، وبالتالي إذا كنت اطلاق متعددة موقع مدير الكائن أنها سوف تتعارض، وتحصل أخطاء من مدير GPS موقع تفيد أنه يمكن 'تحديث ر.

2) كن حذرا للغاية كيف تقوم بتحديث locationManager.desiredAccuracy و    locationManager.distanceFilter

واتبع سبيل المثال في التعليمات البرمجية أبل لهذا في FlipsideViewController:

[MyCLController sharedInstance].locationManager.desiredAccuracy = accuracyToSet;
[MyCLController sharedInstance].locationManager.distanceFilter = filterToSet;

وهذا النهج يعمل، ويسبب عدم وجود أخطاء. إذا قمت بتحديث desiredAccuracy أو    distanceFilter في حلقة مندوب الرئيسية:

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation  fromLocation:(CLLocation *)oldLocation

وكور الموقع من المرجح أن يشكو أنه لا يمكن تحديث القيم، وتعطيك أخطاء.    أيضا، فقط استخدام الثوابت لdesiredAccuracy الموردة من قبل شركة آبل، وليس غيرها،    وبالتالي،

<اقتباس فقرة>   

وkCLLocationAccuracyBest، kCLLocationAccuracyNearestTenMeters،
  kCLLocationAccuracyHundredMeters، kCLLocationAccuracyKilometer،
  kCLLocationAccuracyThreeKilometers

واستخدام قيم أخرى قد تعطيك أخطاء من locationManager.    لdistanceFilter يمكنك استخدام أي قيمة، ولكن تكون على علم وقد ذكر الناس فإنه لديه مشاكل،    القيمة الرئيسية الافتراضي لهي: -1 = أفضل، لقد استعملت 10.0 ويبدو موافق

و3) لفرض التحديث الجديد، استدعاء الأسلوب startUpdates كما هو الحال في Tweetero، هذه القوات  locationManager للقيام بذلك شيء، وأنه ينبغي أن نحاول وتحصل على قيمة جديدة.

و4) جوهر المكان مندوب الروتين هو صعب الحصول على تحديثات دقيقة من.    عند تهيئة التطبيقات الخاصة بك أولا يمكنك أن تكون خارج في دقة بمقدار 1000 متر أو أكثر، وبالتالي    محاولة واحدة لن تفعل ذلك. ثلاث محاولات بعد التهيئة عادة ما يحصل لك    في حدود 47 أو نحو ذلك متر وهو أمر جيد. تذكر أن كل محاولة المتعاقبة تسير    يستغرق وقتا أطول وأطول لتحسين دقة الخاص بك، وبالتالي فإنه يحصل مكلفة بسرعة.    هذا ما عليك فعله:    خذ قيمة جديدة إلا إذا كان الأخير AND    إذا كان الموقع الجديد لديه قليلا أفضل دقة تأخذ الموقع الجديد OR    إذا كان الموقع الجديد لديه دقة <50 متر تأخذ الموقع الجديد OR    إذا تجاوز عدد المحاولات 3 أو 5 ودقة <150 متر AND    تم تغيير موقع، ثم وهذا هو موقع جديد وانتقل الجهاز حتى تأخذ هذه    قيمة حتى لو انها دقة هو أسوأ.    وهنا قال لي الموقع متاحة للقيام بذلك:

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation  *)newLocation  fromLocation:(CLLocation *)oldLocation
{
    locationDenied = NO;

    if(![[NSUserDefaults standardUserDefaults] boolForKey:@"UseLocations"])
    {
        [self stopAllUpdates];
        return;
    }

    NSDate* eventDate = newLocation.timestamp;
    NSTimeInterval howRecent = abs([eventDate timeIntervalSinceNow]);
    attempts++;

    if((newLocation.coordinate.latitude != oldLocation.coordinate.latitude) && (newLocation.coordinate.longitude != oldLocation.coordinate.longitude))
        locationChanged = YES;
        else
            locationChanged = NO;

    #ifdef __i386__
            //Do this for the simulator since location always returns Cupertino
            if (howRecent < 5.0)
    #else
                // Here's the theory of operation
                // If the value is recent AND
                // If the new location has slightly better accuracy take the new location OR
                // If the new location has an accuracy < 50 meters take the new location OR
                // If the attempts is maxed (3 -5) AND the accuracy < 150 AND the location has changed, then this must be a new location and the device moved
                // so take this new value even though it's accuracy might be worse
                if ((howRecent < 5.0) && ( (newLocation.horizontalAccuracy < (oldLocation.horizontalAccuracy - 10.0)) || (newLocation.horizontalAccuracy < 50.0)
                                          || ((attempts >= attempt) && (newLocation.horizontalAccuracy <= 150.0) && locationChanged)))
    #endif
                {
                    attempts = 0;
                    latitude = newLocation.coordinate.latitude;
                    longitude = newLocation.coordinate.longitude;
                    [currentLocation release];
                    currentLocation = [newLocation retain];
                    goodLocation = YES;

                    [[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateLocationNotification" object: nil];

                    if (oldLocation != nil) {
                        distanceMoved = [newLocation getDistanceFrom:oldLocation];
                        currentSpeed = newLocation.speed;
                        distanceTimeDelta = [newLocation.timestamp timeIntervalSinceDate:oldLocation.timestamp];
                    }
                }
    // Send the update to our delegate
    [self.delegate newLocationUpdate:currentLocation];
}

إذا كان لديك اي فون 3GS الحصول على التحديثات العنوان هو أسهل كثيرا، وهنا رمز في نفس وحدة على النحو الوارد أعلاه:

//This is the Heading or Compass values
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading {
    if (newHeading.headingAccuracy > 0)
    {
        [newHeading retain];
        // headingType = YES for True North or NO for Magnetic North
        if(headingType) {
            currentHeading = newHeading.trueHeading;
        } else {
            currentHeading = newHeading.magneticHeading;
        }

        goodHeading = YES;
        [[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateHeadingNotification" object: nil];

    }
}

وهذا الأمل يساعد الناس!

نصائح أخرى

وdidUpdateToLocation فقط التحديثات عندما يقوم المستخدم بتحريك الموقع. هذا يمكن أن يكون متقطعا، وأنا متأكد من أنك قد لاحظت. CCLocationManager لا يرسل تحديثات منتظمة، ولكن بدلا من ذلك يرسل التحديثات عندما انتقلت للمستخدم، أو أنه يزيد انها دقة. عندما أكون الثابتة وأبدأ التطبيق، وعادة ما تحصل حوالي ثلاثة تحديثات، ومن ثم لا شيء لفترة من الوقت. خرائط جوجل لا نوع مماثل من شيء، مما يدل على عصابة مقابل نقطة كما يزيد دقة. فما استقاموا لكم فاستقيموا اقترح الانتظار حتى كنت قد تصل دقة الخاص بك المطلوبة (<120.0f) ومن ثم أداء العمل الخاص بك أو حساب.

إذا كنت تستخدم لتحديد المواقع «طبيعية»، حيث يتم إرسال التحديثات، وأنها مستمرة في صقل انها دقة، وأنا أخشى اي فون لم يتم تصميم للقيام بذلك.

وبدلا من ذلك، يمكنك استخدام API MapKit، وتظهر للمستخدم الخريطة مع موقعها، والسماح ل"تقبل" بمجرد أن تشعر الموقع دقيقة بما فيه الكفاية. وألاحظ أحيانا أحصل على بالغة، ثم 30 ثانية في وقت لاحق وهي تتحرك لي ربما 50 مترا أقرب إلى حيث أنا في الواقع أنا.

لقد كتبت GIT repo حول هذا الأمر، والذي يمكنك استخدامه مجانًا https://github.com/xelvenone/M6GPSLocationManager

  • إذا كانت دقة النتيجة أفضل من الدقة المقبولة، فقد انتهينا
  • إذا حصلنا على تحديث بشأن الحدوث، فإننا ننتظر الحد الأقصى لانتظار الوقت للحصول على نتيجة أفضل، - إذا لم يحدث هذا، فقد انتهينا ونأخذ الأفضل
  • إذا كنا نحصل باستمرار على تحديثات تتجاوز الحد الأقصى للمحاولات، فإننا نختار أفضلها (ربما نتحرك على أي حال)
  • إذا لم نحصل على أي تحديث آخر خلال 30 ثانية، فقد انتهينا (ربما لن يكون هناك أي تحديث آخر)

شفرة

- (void)scopeToCurrentLocationWithAcceptableAccuracy:(CLLocationAccuracy)acceptableAccuracy
              maximumWaitTimeForBetterResult:(NSTimeInterval)maximumWaitTimeForBetterResult
                             maximumAttempts:(NSInteger)maximumAttempts
                                onCompletion:(M6GPSLocationManagerCompletion)completion;
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top