ฉันจะรับการอัปเดตตำแหน่งพื้นหลังได้ทุก ๆ นาทีในแอปพลิเคชัน iOS ของฉันได้อย่างไร


207

ฉันกำลังมองหาวิธีรับการอัปเดตตำแหน่งพื้นหลังทุก ๆ n นาทีในแอปพลิเคชัน iOS ของฉัน ฉันใช้ iOS 4.3 และวิธีแก้ปัญหาควรใช้งานกับ iPhone ที่ไม่ได้รับการเจลเบรคได้

ฉันลอง / พิจารณาตัวเลือกต่อไปนี้:

  • CLLocationManager startUpdatingLocation/startMonitoringSignificantLocationChanges: ใช้งานได้ในพื้นหลังตามที่คาดไว้โดยอิงตามคุณสมบัติที่กำหนดค่า แต่ดูเหมือนว่าเป็นไปไม่ได้ที่จะบังคับให้อัปเดตตำแหน่งทุก ๆ นาที
  • NSTimer: ใช้งานได้เมื่อแอพทำงานในเบื้องหน้า แต่ดูเหมือนจะไม่ได้รับการออกแบบมาสำหรับงานพื้นหลัง
  • การแจ้งเตือนในท้องถิ่น: การแจ้งเตือนในท้องถิ่นสามารถกำหนดเวลาได้ทุก n นาที แต่ไม่สามารถเรียกใช้รหัสบางอย่างเพื่อรับตำแหน่งปัจจุบัน (โดยที่ผู้ใช้ไม่จำเป็นต้องเปิดแอปผ่านการแจ้งเตือน) วิธีการนี้ดูเหมือนจะไม่ใช่วิธีการที่สะอาดเนื่องจากไม่ใช่วิธีการแจ้งเตือนที่ควรใช้
  • UIApplication:beginBackgroundTaskWithExpirationHandler: เท่าที่ฉันเข้าใจสิ่งนี้ควรใช้เพื่อทำงานบางอย่างให้เสร็จในพื้นหลัง (จำกัด เวลาด้วย) เมื่อแอปถูกย้ายไปที่พื้นหลังแทนที่จะใช้กระบวนการพื้นหลังที่ "ทำงานนาน"

ฉันจะใช้การอัปเดตตำแหน่งพื้นหลังปกติเหล่านี้ได้อย่างไร



การติดตามผลที่มีประโยชน์: stackoverflow.com/questions/10235203/…
Lolo

1
หากคุณพยายามทำให้มันใช้งานได้กับ iOS 7 คุณสามารถลองวิธีนี้ได้ที่นี่: stackoverflow.com/questions/18946881/หากคุณมีคำถามใด ๆ คุณยินดีที่จะเข้าร่วมการสนทนาที่นี่: mobileoop.com/background -location-update-programming-for-ios-7
Ricky

1
การค้นพบทั้งหมดของคุณถูกต้อง (ทั้งสี่หัวข้อย่อย) ข้อมูลที่มีค่านั่นคือรู้ว่าสิ่งที่ไม่ตรงกับคุณใช้กรณีและปัญหา? และใช่เมื่ออยู่ในโหมดหยุดชั่วคราวหรือไม่ทำงานไม่มีวิธีที่ดีที่สุดสำหรับการอัปเดตทุก ๆ นาที
LenArt

คำตอบ:


113

ฉันพบวิธีแก้ไขปัญหานี้โดยใช้ฟอรัม Apple Developer:

  • ระบุ location background mode
  • สร้างNSTimerในพื้นหลังด้วยUIApplication:beginBackgroundTaskWithExpirationHandler:
  • เมื่อnมีขนาดเล็กกว่าUIApplication:backgroundTimeRemainingมันจะทำงานได้ดี เมื่อnเป็นขนาดใหญ่ที่location managerควรจะเปิดใช้ (และคนพิการ) อีกครั้งก่อนที่จะมีเวลาเหลือที่จะหลีกเลี่ยงงานพื้นหลังไม่ถูกฆ่าตาย

งานนี้เพราะสถานที่เป็นหนึ่งในสามประเภทที่ได้รับอนุญาตของการดำเนินการพื้นหลัง

หมายเหตุ: ฉันเสียเวลาโดยทดสอบสิ่งนี้ในเครื่องจำลองซึ่งไม่สามารถใช้งานได้ อย่างไรก็ตามมันใช้งานได้ดีบนโทรศัพท์ของฉัน


24
คุณมีลิงค์ไปยังฟอรัมหรือไม่ ฉันต้องการใช้การจับคู่ตำแหน่งประเภทเดียวกันและไม่สามารถใช้งานได้ หรือโค้ดตัวอย่างบางส่วนจะได้รับการชื่นชมอย่างมาก
utahwithak

4
คุณช่วยอธิบายได้ไหมว่าทำไมงานพื้นหลังไม่ถูกฆ่าหลังจาก 10 นาที (เวลาสูงสุดที่อนุญาต) หากคุณเพิ่งหยุดและเริ่มผู้จัดการตำแหน่ง มันเป็นฟังก์ชั่นที่ตั้งใจไว้ไหม? มันฟังดูเหมือนบั๊กใน Apple SDK ถ้ามันเกิดขึ้นแบบนั้น คุณกำลังลองใช้ iOS เวอร์ชันใด
saurabh

5
@ ทั้งหมด: ใช่แอปของเรามีอยู่ใน AppStore ฉันจะไม่โพสต์รหัสทั้งหมดกระสุนที่กล่าวถึงทั้งหมดเป็นเอกสารที่มีคุณสมบัติชัดเจน ในกรณีที่คุณมีปัญหาโดยเฉพาะให้โพสต์คำถามของคุณเองเพื่ออธิบายสิ่งที่คุณได้ลองและสิ่งที่ผิดพลาด
wjans

3
@ user836026: ใช่นั่นคือสิ่งที่ฉันหมายถึงโดยการระบุโหมดพื้นหลัง หลังจากหยุดอัปเดตตำแหน่งแล้วควรเริ่มต้นใหม่อีกครั้งภายใน 10 นาทีเพื่อหลีกเลี่ยงแอปที่ถูกยกเลิก
wjans

12
สำหรับผู้ที่สนใจเห็นโค้ดจริงที่สะท้อนถึงสิ่งที่กำลังพูดถึงอยู่ที่นี่ให้ตรวจสอบstackoverflow.com/questions/10235203/…
Lolo

55

บนiOS 8/9/10เพื่อให้การอัปเดตตำแหน่งพื้นหลังทุกๆ 5 นาทีทำดังนี้

  1. ไปที่โครงการ -> ความสามารถ -> โหมดพื้นหลัง -> เลือกการอัปเดตตำแหน่ง

  2. ไปที่โครงการ -> ข้อมูล -> เพิ่มคีย์ NSLocationAlwaysUsageDescription พร้อมค่าว่าง (หรือเลือกข้อความใดก็ได้)

  3. เพื่อให้สถานที่ทำงานเมื่อแอปของคุณอยู่ในพื้นหลังและส่งพิกัดไปยังบริการบนเว็บหรือทำอะไรกับพวกเขาทุก ๆ 5 นาทีนำไปใช้เช่นในรหัสด้านล่าง

ฉันไม่ได้ใช้งานพื้นหลังหรือตัวจับเวลาใด ๆ ฉันทดสอบโค้ดนี้กับอุปกรณ์ของฉันด้วย iOS 8.1 ซึ่งวางอยู่บนโต๊ะของฉันไม่กี่ชั่วโมงโดยที่แอพของฉันทำงานในพื้นหลัง อุปกรณ์ถูกล็อคและรหัสทำงานอย่างถูกต้องตลอดเวลา

@interface LocationManager () <CLLocationManagerDelegate>
@property (strong, nonatomic) CLLocationManager *locationManager;
@property (strong, nonatomic) NSDate *lastTimestamp;

@end

@implementation LocationManager

+ (instancetype)sharedInstance
{
    static id sharedInstance = nil;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[self alloc] init];
        LocationManager *instance = sharedInstance;
        instance.locationManager = [CLLocationManager new];
        instance.locationManager.delegate = instance;
        instance.locationManager.desiredAccuracy = kCLLocationAccuracyBest; // you can use kCLLocationAccuracyHundredMeters to get better battery life
        instance.locationManager.pausesLocationUpdatesAutomatically = NO; // this is important
    });

    return sharedInstance;
}

- (void)startUpdatingLocation
{
    CLAuthorizationStatus status = [CLLocationManager authorizationStatus];

    if (status == kCLAuthorizationStatusDenied)
    {
        NSLog(@"Location services are disabled in settings.");
    }
    else
    {
        // for iOS 8
        if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)])
        {
            [self.locationManager requestAlwaysAuthorization];
        }
        // for iOS 9
        if ([self.locationManager respondsToSelector:@selector(setAllowsBackgroundLocationUpdates:)])
        {
            [self.locationManager setAllowsBackgroundLocationUpdates:YES];
        }

        [self.locationManager startUpdatingLocation];
    }
}

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
    CLLocation *mostRecentLocation = locations.lastObject;
    NSLog(@"Current location: %@ %@", @(mostRecentLocation.coordinate.latitude), @(mostRecentLocation.coordinate.longitude));

    NSDate *now = [NSDate date];
    NSTimeInterval interval = self.lastTimestamp ? [now timeIntervalSinceDate:self.lastTimestamp] : 0;

    if (!self.lastTimestamp || interval >= 5 * 60)
    {
        self.lastTimestamp = now;
        NSLog(@"Sending current location to web service.");
    }
}

@end

3
ใช้งานได้นานกว่าสองสามชั่วโมงหรือไม่ ดูเหมือนว่าแม้ว่าแอปจะไม่ถูกยกเลิกอุปกรณ์จะหยุดการอัปเดตตำแหน่งหลังจากผ่านไปหนึ่งชั่วโมงหรือมากกว่านั้นแอปจะไปที่พื้นหลัง
Myxtic

2
การดึงข้อมูลพื้นหลังถูกปิดใช้งานในโครงการของฉัน (มันไม่สำคัญว่าจะปิดหรือเปิด) อย่างไรก็ตาม pausesLocationUpdatesAutomatically ต้องถูกตั้งค่าเป็น NO เพื่อให้ตัวอย่างด้านบนทำงานได้อย่างถูกต้อง มันจะไม่ทำงานต่อโดยอัตโนมัติเมื่อคุณเริ่มเคลื่อนไหวอีกครั้งหากระบบหยุดก่อนหน้านี้ นั่นคือสาเหตุในตัวอย่างด้านบนฉันตั้งค่าคุณสมบัตินี้เป็น NO
Leszek Szary

1
ฉันคิดว่าคุณพูดถูก พบข้อมูลเพิ่มเติมเกี่ยวกับปัญหาที่นี่: stackoverflow.com/q/17484352/1048331
Myxtic

2
@LeszekS คุณต้องเพิ่มโค้ดด้านล่างสำหรับ iOS 9 รองรับพื้นหลัง - if ([self.locationManager respondsToSelector:@selector(setAllowsBackgroundLocationUpdates:)]) { [self.locationManager setAllowsBackgroundLocationUpdates:YES]; }
Fenil

2
ความสะดวกสบายของการทำเช่นนี้คืออะไร? คุณยังคงทิ้งแบตเตอรี่โดยมีความแม่นยำสูงคงที่ สิ่งเดียวที่คุณไม่ได้ทำคือคุณไม่ได้ใช้ตำแหน่งที่ได้รับจริงจนกว่าคุณจะถึงช่วงเวลา 5 นาที ...
Honey

34

ฉันทำสิ่งนี้ในแอปพลิเคชันที่ฉันกำลังพัฒนา ตัวจับเวลาไม่ทำงานเมื่อแอปอยู่ในพื้นหลัง แต่แอปได้รับการอัปเดตตำแหน่งอย่างต่อเนื่อง ฉันอ่านที่ไหนสักแห่งในเอกสารประกอบ (ฉันไม่สามารถหามันได้ในตอนนี้ฉันจะโพสต์การอัปเดตเมื่อฉันทำ) ว่าวิธีการนั้นสามารถเรียกได้เฉพาะในลูปที่รันอยู่เท่านั้นเมื่อแอปอยู่ในพื้นหลัง ตัวแทนแอปพลิเคชันมีลูปที่ทำงานอยู่แม้ใน bg ดังนั้นคุณไม่จำเป็นต้องสร้างของคุณเองเพื่อใช้งานได้ [ฉันไม่แน่ใจว่านี่เป็นคำอธิบายที่ถูกต้องหรือไม่ แต่นั่นเป็นสิ่งที่ฉันเข้าใจจากสิ่งที่ฉันอ่าน]

ก่อนอื่นให้เพิ่มlocationออบเจกต์สำหรับคีย์UIBackgroundModesใน info.plist ของแอปของคุณ ตอนนี้สิ่งที่คุณต้องทำคือเริ่มอัปเดตตำแหน่งในแอปของคุณ

    CLLocationManager locationManager = [[CLLocationManager alloc] init];
    locationManager.delegate = self;//or whatever class you have for managing location
    [locationManager startUpdatingLocation];

จากนั้นเขียนวิธีการจัดการการอัปเดตตำแหน่งพูด-(void)didUpdateToLocation:(CLLocation*)locationในแอปผู้รับมอบสิทธิ์ แล้วใช้วิธีการlocationManager:didUpdateLocation:fromLocationของCLLocationManagerDelegateในชั้นเรียนในที่ที่คุณเริ่มต้นผู้จัดการสถานที่ตั้ง (เนื่องจากเราตั้งค่าตำแหน่งผู้จัดการตัวแทนที่ 'ตัวเอง') ภายในวิธีนี้คุณต้องตรวจสอบว่าช่วงเวลาหลังจากที่คุณต้องจัดการกับการอัปเดตตำแหน่งได้ผ่านไปแล้วหรือยัง คุณสามารถทำได้โดยการบันทึกเวลาปัจจุบันทุกครั้ง หากเวลานั้นผ่านไปให้เรียกวิธี UpdateLocation จากตัวแทนแอปของคุณ:

NSDate *newLocationTimestamp = newLocation.timestamp;
NSDate *lastLocationUpdateTiemstamp;

int locationUpdateInterval = 300;//5 mins

NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
if (userDefaults) {

        lastLocationUpdateTiemstamp = [userDefaults objectForKey:kLastLocationUpdateTimestamp];

        if (!([newLocationTimestamp timeIntervalSinceDate:lastLocationUpdateTiemstamp] < locationUpdateInterval)) {
            //NSLog(@"New Location: %@", newLocation);
            [(AppDelegate*)[UIApplication sharedApplication].delegate didUpdateToLocation:newLocation];
            [userDefaults setObject:newLocationTimestamp forKey:kLastLocationUpdateTimestamp];
        }
    }
}

วิธีนี้จะเรียกวิธีการของคุณทุก 5 นาทีแม้ในขณะที่แอปของคุณอยู่ในพื้นหลัง Imp: การนำไปใช้งานนี้เป็นการสิ้นเปลืองแบตเตอรี่หากความแม่นยำของข้อมูลตำแหน่งของคุณไม่สำคัญคุณควรใช้[locationManager startMonitoringSignificantLocationChanges]

ก่อนที่จะเพิ่มสิ่งนี้ลงในแอพของคุณโปรดอ่านคู่มือการเขียนโปรแกรมการรับรู้ตำแหน่ง


3
ด้วยวิธีนี้บริการตำแหน่งถูกเปิดใช้งานอย่างต่อเนื่อง (แน่นอนว่าแบตเตอรี่หมด) ฉันไม่ต้องการมัน ฉันต้องการเปิดใช้งานบริการระบุตำแหน่งทุก ๆ นาทีและปิดการใช้งานทันทีเมื่อมีการแก้ไขที่ดี (เพิ่งสังเกตว่าฉันไม่ได้อธิบายอย่างชัดเจนในคำถามของฉัน) ฉันสามารถบรรลุพฤติกรรมนี้ในวิธีการแก้ปัญหาที่ฉันอธิบาย
wjans

3
คุณสามารถตั้งค่าความถูกต้องของเครื่องมือจัดการตำแหน่งได้ 1 กม. ซึ่งจะทำให้แบตเตอรีของคุณใกล้ หลังจาก 5 นาทีคุณจะตั้งค่าความแม่นยำเป็น 1m เมื่อคุณได้รับตำแหน่งที่พอใจ (ปกติหลังจาก 5 วินาที) เพียงตั้งค่าความแม่นยำกลับไปที่ 1km
knagode

knagode ฉันลองวิธีแก้ปัญหาที่แนะนำของคุณสำหรับปัญหาการระบายน้ำแบตเตอรี่ แต่แม้หลังจากเพิ่มความแม่นยำหลังจาก N นาที, locationManager: didUpdateLocations วิธีการจะไม่ถูกเรียกอีกครั้ง ฉันลอง startUpdating และ stopUpdating แทนการเพิ่มและลดความแม่นยำมันถูกเรียกว่าประสบความสำเร็จในการมอบหมาย locationManager: didUpdateLocations วิธีหลังจาก N นาที แต่ไม่ทำงานในโหมดพื้นหลัง ...
Hardik Darji

สำหรับลิงก์ของเอกสาร ดูที่นี่ : "วิธีการของวัตถุผู้รับมอบสิทธิ์ของคุณจะถูกเรียกจากเธรดที่คุณเริ่มบริการตำแหน่งที่ตั้งที่สอดคล้องกันเธรดนั้นต้องมีลูปที่ใช้งานอยู่เช่นเดียวกับที่พบในเธรดหลักของแอปพลิเคชันของคุณ"
น้ำผึ้ง

24

ตอนนี้ iOS6 ออกมาเป็นวิธีที่ดีที่สุดในการให้บริการบอกตำแหน่งที่ทำงานตลอดไปคือ ...

- (void)applicationWillResignActive:(UIApplication *)application
{
/*
 Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
 Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
 */

NSLog(@"to background");

app.isInBackground = TRUE;

UIApplication *app = [UIApplication sharedApplication];

// Request permission to run in the background. Provide an
// expiration handler in case the task runs long.
NSAssert(bgTask == UIBackgroundTaskInvalid, nil);

bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
    // Synchronize the cleanup call on the main thread in case
    // the task actually finishes at around the same time.
    dispatch_async(dispatch_get_main_queue(), ^{

        if (bgTask != UIBackgroundTaskInvalid)
        {
            [app endBackgroundTask:bgTask];
            bgTask = UIBackgroundTaskInvalid;
        }
    });
}];

// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    // Do the work associated with the task.

    locationManager.distanceFilter = 100;
    locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
    [locationManager startMonitoringSignificantLocationChanges];
    [locationManager startUpdatingLocation];

    NSLog(@"App staus: applicationDidEnterBackground");
    // Synchronize the cleanup call on the main thread in case
    // the expiration handler is fired at the same time.
    dispatch_async(dispatch_get_main_queue(), ^{
        if (bgTask != UIBackgroundTaskInvalid)
        {
            [app endBackgroundTask:bgTask];
            bgTask = UIBackgroundTaskInvalid;
        }
    });
});

NSLog(@"backgroundTimeRemaining: %.0f", [[UIApplication sharedApplication] backgroundTimeRemaining]);

}

เพิ่งทดสอบแบบนี้:

ฉันเริ่มต้นแอปไปพื้นหลังและย้ายเข้าไปในรถภายในไม่กี่นาที จากนั้นฉันกลับบ้านเป็นเวลา 1 ชั่วโมงและเริ่มเคลื่อนไหวอีกครั้ง (โดยไม่ต้องเปิดแอปอีกครั้ง) สถานที่เริ่มต้นอีกครั้ง จากนั้นหยุดสองชั่วโมงแล้วเริ่มใหม่อีกครั้ง ทุกอย่างตกลงอีกครั้ง ...

อย่าลืมใช้บริการระบุตำแหน่งใหม่ใน iOS6

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{   
    CLLocation *loc = [locations lastObject];

    // Lat/Lon
    float latitudeMe = loc.coordinate.latitude;
    float longitudeMe = loc.coordinate.longitude;
}

1
หากแอพขัดข้องหรือถูกฆ่าระบบจะไม่รีสตาร์ทใช่ไหม
เคน

1
สำหรับรหัสที่อ่านได้มากขึ้นคุณสามารถเลือก [location lastObject]; แทน [location objectAtIndex: [นับจำนวนสถานที่] - 1]
axello

วิธีการของคุณเป็นเพียงที่ iOS6?
pengwang

เราต้องใช้สิ่งนี้หรือไม่? ฉันคิดว่ามีโค้ดตัวจัดการตำแหน่งใน viewDidLoad ของคลาสและตั้งค่าคีย์พื้นหลังในไฟล์ plist ที่แอพที่ลงทะเบียนสำหรับการอัปเดตตำแหน่งควรจะดีพอหรือไม่ คุณช่วยฉันด้วยเรื่องนี้ได้ไหม!
nithinreddy

ใช่มันจะทำงานเหมือนเครื่องราง nithinreddy แต่มันจะหยุดทำงานหลังจาก 10 นาทีตั้งแต่ iOS ฆ่ากระทู้ยาวหลังจากนั้น โซลูชันของฉันสมบูรณ์แบบถ้าคุณต้องการให้บริการเหล่านั้นเริ่มต้นตลอดไป ฉันทำการทดสอบสองวันที่ผ่านมาและมันใช้พลังงานแบตเตอรี่ 6% ทุกชั่วโมง ใช้ [locationManager startUpdatingLocation] แทนจะลดลง 17%
Alejandro Luengo

13

สำหรับคนอื่นที่มีฝันร้ายให้ค้นหาสิ่งนี้ ฉันมีทางออกที่ง่าย

  1. ดูตัวอย่างนี้จากraywenderlich.com -> มีโค้ดตัวอย่างทำงานได้อย่างสมบูรณ์แบบ แต่น่าเสียดายที่ไม่มีตัวจับเวลาระหว่างตำแหน่งพื้นหลัง สิ่งนี้จะทำงานอย่างไม่มีกำหนด
  2. เพิ่มตัวจับเวลาโดยใช้:

    -(void)applicationDidEnterBackground {
    [self.locationManager stopUpdatingLocation];
    
    UIApplication*    app = [UIApplication sharedApplication];
    
    bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
        [app endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;
    }];
    
     self.timer = [NSTimer scheduledTimerWithTimeInterval:intervalBackgroundUpdate
                                                  target:self.locationManager
                                                selector:@selector(startUpdatingLocation)
                                                userInfo:nil
                                                 repeats:YES];
    
    }
    
  3. อย่าลืมเพิ่ม "ลงทะเบียนแอพเพื่ออัปเดตตำแหน่ง" ใน info.plist


สิ่งนี้ได้รับตำแหน่งนานกว่า 3 นาทีหรือไม่?
SleepNot

ต้องตั้งค่าตำแหน่งในความสามารถ -> โหมดพื้นหลัง
Sergio Andreotti

มันไม่ทำงาน !! ฉันได้ตรวจสอบบน iOS 8 และ iOS 10
Kirti

ช่วยแก้ให้ด้วยนะถ้าฉันผิด. ขึ้นอยู่กับสิ่งที่ฉันอ่านคุณเริ่มตำแหน่งผู้จัดการเพียงครั้งเดียว หลังจากนั้นช่วงเวลาทั้งหมดซ้ำซ้อน ตั้งแต่เริ่มแล้ว
ฮันนี่

มันใช้งานได้ แต่มันหยุดลงหลังจาก 170 วินาที ฉันต้องการทำงานในพื้นหลังโดยไม่ จำกัด เวลา
anshuman burmman

8

นี่คือสิ่งที่ฉันใช้:

import Foundation
import CoreLocation
import UIKit

class BackgroundLocationManager :NSObject, CLLocationManagerDelegate {

    static let instance = BackgroundLocationManager()
    static let BACKGROUND_TIMER = 150.0 // restart location manager every 150 seconds
    static let UPDATE_SERVER_INTERVAL = 60 * 60 // 1 hour - once every 1 hour send location to server

    let locationManager = CLLocationManager()
    var timer:NSTimer?
    var currentBgTaskId : UIBackgroundTaskIdentifier?
    var lastLocationDate : NSDate = NSDate()

    private override init(){
        super.init()
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyKilometer
        locationManager.activityType = .Other;
        locationManager.distanceFilter = kCLDistanceFilterNone;
        if #available(iOS 9, *){
            locationManager.allowsBackgroundLocationUpdates = true
        }

        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.applicationEnterBackground), name: UIApplicationDidEnterBackgroundNotification, object: nil)
    }

    func applicationEnterBackground(){
        FileLogger.log("applicationEnterBackground")
        start()
    }

    func start(){
        if(CLLocationManager.authorizationStatus() == CLAuthorizationStatus.AuthorizedAlways){
            if #available(iOS 9, *){
                locationManager.requestLocation()
            } else {
                locationManager.startUpdatingLocation()
            }
        } else {
                locationManager.requestAlwaysAuthorization()
        }
    }
    func restart (){
        timer?.invalidate()
        timer = nil
        start()
    }

    func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
        switch status {
        case CLAuthorizationStatus.Restricted:
            //log("Restricted Access to location")
        case CLAuthorizationStatus.Denied:
            //log("User denied access to location")
        case CLAuthorizationStatus.NotDetermined:
            //log("Status not determined")
        default:
            //log("startUpdatintLocation")
            if #available(iOS 9, *){
                locationManager.requestLocation()
            } else {
                locationManager.startUpdatingLocation()
            }
        }
    }
    func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {

        if(timer==nil){
            // The locations array is sorted in chronologically ascending order, so the
            // last element is the most recent
            guard let location = locations.last else {return}

            beginNewBackgroundTask()
            locationManager.stopUpdatingLocation()
            let now = NSDate()
            if(isItTime(now)){
                //TODO: Every n minutes do whatever you want with the new location. Like for example sendLocationToServer(location, now:now)
            }
        }
    }

    func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
        CrashReporter.recordError(error)

        beginNewBackgroundTask()
        locationManager.stopUpdatingLocation()
    }

    func isItTime(now:NSDate) -> Bool {
        let timePast = now.timeIntervalSinceDate(lastLocationDate)
        let intervalExceeded = Int(timePast) > BackgroundLocationManager.UPDATE_SERVER_INTERVAL
        return intervalExceeded;
    }

    func sendLocationToServer(location:CLLocation, now:NSDate){
        //TODO
    }

    func beginNewBackgroundTask(){
        var previousTaskId = currentBgTaskId;
        currentBgTaskId = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler({
            FileLogger.log("task expired: ")
        })
        if let taskId = previousTaskId{
            UIApplication.sharedApplication().endBackgroundTask(taskId)
            previousTaskId = UIBackgroundTaskInvalid
        }

        timer = NSTimer.scheduledTimerWithTimeInterval(BackgroundLocationManager.BACKGROUND_TIMER, target: self, selector: #selector(self.restart),userInfo: nil, repeats: false)
    }
}

ฉันเริ่มการติดตามใน AppDelegate เช่นนั้น:

BackgroundLocationManager.instance.start()

ขอบคุณ โครงการของเราต้องติดตามตำแหน่งของผู้ใช้ + ส่งกิจกรรม PubNub ในเบื้องหลังและโซลูชันของคุณทำงานได้ดีจริงๆ
user921509

สวัสดี Hmitkov ฉันจะโทรหาเมธอด sendLocationToServer เพื่อส่งตำแหน่งผู้ใช้บนเซิร์ฟเวอร์ได้อย่างไร
AmanGupta007

@ AmanGupta007 คุณสามารถโทรหา sendLocationToServer ใน func locationManager (ผู้จัดการ: didUpdateLocations :) สังเกตเห็นความคิดเห็น // TODO ในรหัส
hmitkov

@hmitkov เป็นไปได้ไหมที่จะเริ่มและหยุดบริการหาตำแหน่งขณะที่แอปอยู่ในพื้นหลัง ตัวอย่างเช่นเริ่มบริการบอกตำแหน่งจากการแจ้งเตือนแบบพุชคว้าละติจูด / ลองจิจูดส่งไปยังเว็บเซอร์วิสจากนั้นหยุดอัปเดตตำแหน่ง ทำสิ่งนี้ทุกครั้งที่มี 'content-available' = 1 รวมอยู่ในส่วนผลัก
DookieMan

1
ฉันลองใช้รหัสนี้ แต่ดูเหมือนว่ามันไม่ทำงานบน iOS11 ใช่ไหม (ฉันไม่ได้ทดสอบกับรุ่นอื่น ๆ )
Tom

6

น่าเสียดายที่สมมติฐานทั้งหมดของคุณดูเหมือนถูกต้องและฉันไม่คิดว่าจะมีวิธีการทำเช่นนี้ เพื่อประหยัดอายุการใช้งานแบตเตอรี่บริการระบุตำแหน่งของ iPhone จะขึ้นอยู่กับการเคลื่อนไหว หากโทรศัพท์อยู่ในจุดเดียวแสดงว่าบริการตำแหน่งไม่สามารถมองเห็นได้

CLLocationManagerจะเรียกlocationManager:didUpdateToLocation:fromLocation:เมื่อโทรศัพท์ได้รับการปรับปรุงสถานที่ซึ่งจะเกิดขึ้นถ้าหนึ่งในสามของการบริการสถานที่ (หอโทรศัพท์มือถือ, GPS, WiFi) เล็งเห็นการเปลี่ยนแปลง

อีกสองสามสิ่งที่อาจช่วยแจ้งวิธีแก้ไขเพิ่มเติม

  • การเริ่มต้นและการหยุดบริการทำให้didUpdateToLocationวิธีการมอบหมายถูกเรียก แต่newLocationอาจมีการประทับเวลาเก่า

  • การตรวจสอบภูมิภาคอาจช่วยได้

  • เมื่อทำงานในพื้นหลังโปรดทราบว่าอาจเป็นเรื่องยากที่จะได้รับการสนับสนุน LocationServices "เต็ม" ที่ได้รับอนุมัติจาก Apple จากสิ่งที่ฉันได้เห็นพวกเขาได้รับการออกแบบมาโดยเฉพาะstartMonitoringSignificantLocationChangesเป็นทางเลือกที่ใช้พลังงานต่ำสำหรับแอพที่ต้องการการสนับสนุนตำแหน่งพื้นหลังและสนับสนุนให้นักพัฒนาซอฟต์แวร์ใช้อย่างนี้เว้นแต่ว่าแอพนั้นต้องการมันจริงๆ

โชคดี!

อัปเดต: ความคิดเหล่านี้อาจล้าสมัยในขณะนี้ ดูเหมือนว่าผู้คนจะประสบความสำเร็จด้วยคำตอบ @wjans ด้านบน


1
มีแอพที่มีอยู่ใน AppStore (เช่น "My Locus") ซึ่งทำให้สามารถรับการอัปเดตตำแหน่งในพื้นหลังได้ พวกเขาไม่ให้บริการสถานที่ใช้งาน แต่เพิ่งได้รับการเปิดใช้งานตามช่วงเวลาที่กำหนด พวกเขาทำเช่นนี้ได้อย่างไร
wjans

2
ในสถานการณ์ที่คุณอธิบายแอพมักใช้วิธีการ startMonitoringSignentiallyLocationChanges ที่นี่โทรศัพท์จะ 'ปลุก' ชั่วคราวเมื่อได้รับการอัปเดตตำแหน่ง แต่ไม่มีช่วงเวลาที่คุณสามารถตั้งค่าเป็น 'ping' บริการนี้ในพื้นหลัง เมื่อโทรศัพท์เคลื่อนที่ (หรือเปลี่ยนจาก Cellular เป็น GPS หรือเป็น Wifi) จะทำให้เกิดการอัปเดต การบรรยาย Stanford iTunes U ในหัวข้อนี้มีประโยชน์มากสำหรับฉัน - หวังว่ามันจะช่วยให้คุณหาวิธีแก้ปัญหา: itunes.apple.com/us/itunes-u/iphone-application-development/ …
Chazbot

2
ขอบคุณสำหรับตัวชี้ อย่างไรก็ตามฉันยังไม่เข้าใจว่าแอปกำลังทำอะไรอยู่ แม้ว่าโทรศัพท์ของฉันจะอยู่ที่โต๊ะทำงานของฉัน แต่ฉันไม่สามารถเคลื่อนไหวได้เลยฉันสามารถดูบริการบอกตำแหน่งได้ทุก ๆ 10 นาที (อย่างแน่นอน) หากฉันเข้าใจถูกต้องstartMonitoringSignificantLocationChangesจะไม่ให้การอัปเดตใด ๆ ในกรณีนั้น
wjans

1
@wjans คุณใช้พลังงานจากแบตเตอรี่ในโทรศัพท์ของคุณเป็นอย่างไรคุณสังเกตเห็นว่ามีการระบายแอพ Mylocus ลงอย่างเห็นได้ชัด?
user836026

6

ฉันเขียนแอพโดยใช้บริการตำแหน่งแอพต้องส่งตำแหน่งทุก ๆ 10 วินาที และมันทำงานได้ดีมาก

เพียงใช้วิธี " allowDeferredLocationUpdatesUntilTraveled: หมดเวลา " ตามเอกสารของ Apple

สิ่งที่ฉันทำคือ:

ต้องใช้:ลงทะเบียนโหมดพื้นหลังเพื่ออัปเดตตำแหน่ง

1.สร้างLocationMangerและstartUpdatingLocationด้วยaccuracyและfilteredDistanceเป็นสิ่งที่คุณต้องการ:

-(void) initLocationManager    
{
    // Create the manager object
    self.locationManager = [[[CLLocationManager alloc] init] autorelease];
    _locationManager.delegate = self;
    // This is the most important property to set for the manager. It ultimately determines how the manager will
    // attempt to acquire location and thus, the amount of power that will be consumed.
    _locationManager.desiredAccuracy = 45;
    _locationManager.distanceFilter = 100;
    // Once configured, the location manager must be "started".
    [_locationManager startUpdatingLocation];
}

2.เพื่อให้แอปทำงานตลอดไปโดยใช้allowDeferredLocationUpdatesUntilTraveled:timeoutวิธีการในพื้นหลังคุณต้องรีสตาร์ทupdatingLocationด้วยพารามิเตอร์ใหม่เมื่อแอปย้ายไปที่พื้นหลังเช่นนี้

- (void)applicationWillResignActive:(UIApplication *)application {
     _isBackgroundMode = YES;

    [_locationManager stopUpdatingLocation];
    [_locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
    [_locationManager setDistanceFilter:kCLDistanceFilterNone];
    _locationManager.pausesLocationUpdatesAutomatically = NO;
    _locationManager.activityType = CLActivityTypeAutomotiveNavigation;
    [_locationManager startUpdatingLocation];
 }

3.แอปได้รับการอัปเดตตำแหน่งตามปกติด้วยการlocationManager:didUpdateLocations:โทรกลับ:

-(void) locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
//  store data
    CLLocation *newLocation = [locations lastObject];
    self.userLocation = newLocation;

   //tell the centralManager that you want to deferred this updatedLocation
    if (_isBackgroundMode && !_deferringUpdates)
    {
        _deferringUpdates = YES;
        [self.locationManager allowDeferredLocationUpdatesUntilTraveled:CLLocationDistanceMax timeout:10];
    }
}

4.แต่คุณควรจัดการข้อมูลในการlocationManager:didFinishDeferredUpdatesWithError:ติดต่อกลับเพื่อวัตถุประสงค์ของคุณ

- (void) locationManager:(CLLocationManager *)manager didFinishDeferredUpdatesWithError:(NSError *)error {

     _deferringUpdates = NO;

     //do something 
}

5. หมายเหตุ:ฉันคิดว่าเราควรรีเซ็ตพารามิเตอร์ของLocationManagerแต่ละครั้งที่สลับแอประหว่างโหมดแบ็คกราวน์ / โหมดกราวด์


@ All โซลูชันใดที่อธิบายวิธีนี้หรือมากกว่าที่อธิบายไว้ของ wjans ฉันควรจะประหยัดแบตเตอรี่ของอุปกรณ์หรือทั้งสองอย่างจะมีผลเหมือนกันหรือไม่
Yash

2
ฉันลองใช้ทั้งสองวิธีที่คุณพูดถึงและเห็นว่า @ wjans มีวิธีประหยัดแบตเตอรี่มากกว่า แต่หลังจากการมาของ iOS 8 ดูเหมือนว่าวิธีการแก้ปัญหานั้นจะไม่ทำงานอย่างถูกต้องอีกต่อไป สำหรับรายละเอียดเพิ่มเติม: ส่วนใหญ่แอปไม่สามารถอยู่ในโหมดเบื้องหลังได้นาน
samthui7

@ samthui7 ทำไมคุณตั้ง pausesLocationUpdatesAutomatically = false
CedricSoubrie

ความต้องการของแอพของฉันคือการส่ง userLocation ทุก ๆ 10 วินาทีในขณะpausesLocationUpdatesAutomatically = trueที่แจ้งให้ผู้จัดการตำแหน่งหยุดการอัปเดตชั่วคราวหากไม่มีการเปลี่ยนตำแหน่ง ( เอกสารของ Apple ) อย่างไรก็ตามฉันยังไม่ได้ทดสอบกรณีอย่างชัดเจนlocation manager pauses updates: D
samthui7

@CedricSoubrie: การตั้งค่าpausesLocationUpdatesAutomatically = trueทำให้แอปของฉันหยุดอัปเดตตำแหน่ง
samthui7

5
if ([self.locationManager respondsToSelector:@selector(setAllowsBackgroundLocationUpdates:)]) {
    [self.locationManager setAllowsBackgroundLocationUpdates:YES];
}

สิ่งนี้จำเป็นสำหรับการติดตามตำแหน่งพื้นหลังตั้งแต่ iOS 9


1
สิ่งนี้ช่วยชีวิตฉันไว้! ใช้เป้าหมายการปรับใช้ iOS8 พร้อมกับอุปกรณ์ iOS9
Yaro

4

ฉันใช้วิธีของ xs2bush ในการรับช่วงเวลา (โดยใช้timeIntervalSinceDate) และขยายเพิ่มเล็กน้อย ฉันต้องการตรวจสอบให้แน่ใจว่าฉันได้รับความถูกต้องตามที่ฉันต้องการและฉันไม่ได้ใช้พลังงานจากแบตเตอรี่โดยใช้วิทยุ gps เกินความจำเป็น

ฉันให้ที่ตั้งทำงานอย่างต่อเนื่องด้วยการตั้งค่าต่อไปนี้:

locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
locationManager.distanceFilter = 5;

นี่เป็นแบตเตอรี่ที่ค่อนข้างต่ำ เมื่อฉันพร้อมที่จะอ่านตำแหน่งของฉันเป็นระยะต่อไปฉันจะตรวจสอบก่อนว่าตำแหน่งนั้นอยู่ในความถูกต้องที่ฉันต้องการหรือไม่ถ้าใช่ฉันก็ใช้ตำแหน่งนั้น หากไม่เป็นเช่นนั้นฉันจะเพิ่มความแม่นยำด้วย:

locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
locationManager.distanceFilter = 0;

รับตำแหน่งของฉันแล้วเมื่อฉันมีที่ตั้งฉันจะเปลี่ยนความแม่นยำกลับลงมาอีกครั้งเพื่อลดการสิ้นเปลืองแบตเตอรี่ ฉันได้เขียนตัวอย่างการทำงานเต็มรูปแบบแล้วและฉันได้เขียนซอร์สสำหรับโค้ดฝั่งเซิร์ฟเวอร์เพื่อรวบรวมข้อมูลตำแหน่งที่ตั้งเก็บไว้ในฐานข้อมูลและอนุญาตให้ผู้ใช้ดูข้อมูล gps แบบเรียลไทม์หรือดึงและดูเส้นทางที่เก็บไว้ก่อนหน้านี้ ฉันมีลูกค้าสำหรับ iOS, Android, windows phone และ java me ลูกค้าทั้งหมดถูกเขียนขึ้นตามธรรมชาติและพวกเขาทำงานอย่างถูกต้องในพื้นหลัง โครงการได้รับอนุญาตจาก MIT

โครงการ iOS ของคุณมีการกำหนดเป้าหมายสำหรับ iOS 6 ใช้ SDK ฐานของ iOS 7 คุณจะได้รับรหัสที่นี่

กรุณายื่นปัญหา github ถ้าคุณเห็นปัญหาใด ๆ กับมัน ขอบคุณ


ฉันลองวิธีการแก้ปัญหาของคุณ แต่ไม่ทำงาน ... เมื่อแอปไปที่พื้นหลังแล้วแม้หลังจากเพิ่มความแม่นยำแอปไม่ได้รับการเรียกว่าวิธี didUpdateToLocation ในกรณีของฉัน
Hardik Darji

@HardikDarji คำถามสำคัญ คุณกำลังจะย้าย? มิฉะนั้นการอัปเดตตำแหน่งอาจหยุดลง ลองนำโทรศัพท์ของคุณออกไปเดินเล่นหรือขับรถและดูว่าสามารถแก้ไขได้หรือไม่
nickfox

ขอบคุณสำหรับการตอบสนองที่รวดเร็ว แต่ฉันต้องการอัปเดตตำแหน่งในทุก ๆ 2 นาทีโดยไม่สนใจว่าโทรศัพท์ของฉันเคลื่อนไหวหรือไม่ ในสถานการณ์นี้ didUpdateToLocation ไม่มีการเรียกวิธีการ ฉันกำลังค้นหาที่นี่สำหรับ: ฉันจะอัปเดตตำแหน่งได้อย่างไรทุก ๆ n นาที !!!
Hardik Darji

ลองตั้งค่า timeIntervalInSeconds เป็น 120 และไม่แสดงข้อคิดเห็นบรรทัดนี้: locationManager.pausesLocationUpdatesAutomatically = NO;
nickfox

1
โซลูชันที่คุณโพสต์ในความคิดเห็นด้านบนฆ่าแบตเตอรี่หรือคุณยังทำการปรับปรุงบางอย่างอยู่
samfr

2

ดูเหมือนว่า stopUpdatingLocation เป็นสิ่งที่ทำให้ตัวจับเวลา Watchdog พื้นหลังทำงานดังนั้นฉันจึงแทนที่ด้วย didUpdateLocation ด้วย:

     [self.locationManager setDesiredAccuracy:kCLLocationAccuracyThreeKilometers];
     [self.locationManager setDistanceFilter:99999];

ซึ่งดูเหมือนว่าจะปิด GPS ได้อย่างมีประสิทธิภาพ ตัวเลือกสำหรับพื้นหลัง NSTimer จะกลายเป็น:

- (void) changeAccuracy {
[self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[self.locationManager setDistanceFilter:kCLDistanceFilterNone];
}

ทั้งหมดที่ฉันทำคือการสลับความแม่นยำเป็นระยะเพื่อให้ได้พิกัดที่มีความแม่นยำสูงทุกสองสามนาทีและเนื่องจาก locationManager ไม่ได้ถูกหยุดทำงาน backgroundTimeRemaining จะยังคงอยู่ที่ค่าสูงสุด นี่เป็นการลดการใช้แบตเตอรี่จาก ~ 10% ต่อชั่วโมง (ด้วย kCLLocationAccuracyBest ที่ดีที่สุดในพื้นหลัง) เป็น ~ 2% ต่อชั่วโมงบนอุปกรณ์ของฉัน


2

มี cocoapod APScheduledLocationManagerที่ช่วยให้ได้รับการอัปเดตตำแหน่งพื้นหลังทุก ๆnวินาทีด้วยความแม่นยำของตำแหน่งที่ต้องการ

let manager = APScheduledLocationManager(delegate: self)
manager.startUpdatingLocation(interval: 170, acceptableLocationAccuracy: 100)

ที่เก็บยังมีตัวอย่างแอปที่เขียนด้วย Swift 3


คุณมีอะไรแบบนี้ในวัตถุประสงค์ค
Moxarth

1

ใน iOS 9 และ watchOS 2.0 มีวิธีการใหม่ใน CLLocationManager ที่ให้คุณขอตำแหน่งปัจจุบัน: CLLocationManager: requestLocation () สิ่งนี้จะเสร็จสมบูรณ์ทันทีจากนั้นส่งคืนตำแหน่งไปยังผู้รับมอบสิทธิ์ CLLocationManager

คุณสามารถใช้ NSTimer เพื่อขอตำแหน่งทุกนาทีด้วยวิธีนี้ในตอนนี้และไม่ต้องทำงานกับวิธีการ startUpdatingLocation และ stopUpdatingLocation

อย่างไรก็ตามถ้าคุณต้องการที่จะจับตำแหน่งตามการเปลี่ยนแปลงของ X meters จากตำแหน่งสุดท้ายเพียงแค่ตั้งค่าคุณสมบัติ DistanceFilter ของ CLLocationManger และเป็น X call startUpdatingLocation ()


-1

สิ่งที่แนบมานั้นเป็นวิธีการแก้ปัญหาอย่างรวดเร็วใน

กำหนดApp registers for location updatesใน info.plist

ทำให้ locationManager ทำงานอยู่ตลอดเวลา

สลับkCLLocationAccuracyระหว่างBestForNavigation(เป็นเวลา 5 วินาทีเพื่อรับตำแหน่ง) และThreeKilometersสำหรับช่วงเวลารอที่เหลือเพื่อหลีกเลี่ยงการระบายแบตเตอรี่

ตัวอย่างนี้อัปเดตตำแหน่งทุก ๆ 1 นาทีในเบื้องหน้าและทุก ๆ 15 นาทีในพื้นหลัง

ตัวอย่างทำงานได้ดีกับ Xcode 6 Beta 6 ซึ่งทำงานในอุปกรณ์ iOS 7

ใน App Delegate (mapView เป็นตัวเลือกชี้ไปที่ mapView Controller)

func applicationDidBecomeActive(application: UIApplication!) {
    if appLaunched! == false { // Reference to mapView used to limit one location update per timer cycle
        appLaunched = true
        var appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
        var window = appDelegate.window
        var tabBar = window?.rootViewController as UITabBarController
        var navCon = tabBar.viewControllers[0] as UINavigationController
        mapView = navCon.topViewController as? MapViewController
    }
    self.startInitialPeriodWithTimeInterval(60.0)
}

func applicationDidEnterBackground(application: UIApplication!) {
    self.startInitialPeriodWithTimeInterval(15 * 60.0)
}

func startInitialPeriodWithTimeInterval(timeInterval: NSTimeInterval) {
    timer?.invalidate() // reset timer
    locationManager?.desiredAccuracy = kCLLocationAccuracyBestForNavigation
    timer = NSTimer.scheduledTimerWithTimeInterval(5.0, target: self, selector: Selector("getFirstLocationUpdate:"), userInfo: timeInterval, repeats: false)
}

func getFirstLocationUpdate(sender: NSTimer) {
    let timeInterval = sender.userInfo as Double
    timer?.invalidate()
    mapView?.canReportLocation = true
    timer = NSTimer.scheduledTimerWithTimeInterval(timeInterval, target: self, selector: Selector("waitForTimer:"), userInfo: timeInterval, repeats: true)
}

func waitForTimer(sender: NSTimer) {
    let time = sender.userInfo as Double
    locationManager?.desiredAccuracy = kCLLocationAccuracyBestForNavigation
    finalTimer = NSTimer.scheduledTimerWithTimeInterval(5.0, target: self, selector: Selector("getLocationUpdate"), userInfo: nil, repeats: false)
}

func getLocationUpdate() {
    finalTimer?.invalidate()
    mapView?.canReportLocation = true
}

ใน mapView (locationManager ชี้ไปที่วัตถุใน AppDelegate)

override func viewDidLoad() {
    super.viewDidLoad()
    var appDelegate = UIApplication.sharedApplication().delegate! as AppDelegate
    locationManager = appDelegate.locationManager!
    locationManager.delegate = self
    canReportLocation = true
}

  func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
        if canReportLocation! {
            canReportLocation = false
            locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers
        } else {
            //println("Ignore location update")
        }
    }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.