【问题标题】:loop array of locations in separate thread在单独的线程中循环位置数组
【发布时间】:2014-09-25 00:00:48
【问题描述】:

我正在为 iPhone 开发一个应用程序,我正在跟踪用户的当前位置。当didupdateLocations 委托方法实际执行时,我想测试 NSArray 中的位置是否在包含其他位置的预定义数组中,这个数组会随着时间的推移而增长。

我在这个方法中运行了一个 for 循环来测试我自己的位置数组,但我想把它移到一个单独的线程中。因此,如果我自己的具有多个位置的数组增长到大量,for 循环不会冻结我的 UI。 我已经像这样尝试过,但我得到了不希望的结果。我知道位置跟踪肯定发生在一个单独的线程中。但是那些didupdateLocations 在单独的线程上执行。 Apple 文档对此事不是很清楚。我的最终目标是与我的数组进行比较,而不是锁定 UI。

  - (void)locationManager:(CLLocationManager *)manager
         didUpdateLocations:(NSArray *)thisLocation {

    dispatch_queue_t queue= dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    // get the last object in the array of locations
    CLLocation* location = [thisLocation lastObject];

     dispatch_async(queue, ^{
         [self checkmyArray:location];
     });

}



 -(void)checkmyArray:(CLLocation *)workingLocation{

    NSLog(@"SoundTheAlarm");
     int alarm_on_c = 0;
     NSUInteger tmp_count = [theData.LocationsObjectArray count];
     BOOL alarm;
     NSMutableDictionary * tempObject;
     CLLocationDistance distance = 0.0;


    for (int i = 0; i < tmp_count; i++) {

        tempObject= [theData.LocationsObjectArray objectAtIndex:i];

         thisLoc = [[tempObject objectForKey:@"onoff"] isEqual:@YES];


        if (thisLoc) {


            //check if we are near that location
            double lat = [[tempObject objectForKey:@"latitude"] doubleValue];
            double lon = [[tempObject objectForKey:@"longitude"] doubleValue];

            // goal = [[CLLocation alloc] initWithLatitude:40.097771 longitude:-74.941399];
            goal = [[CLLocation alloc] initWithLatitude:lat longitude:lon];

            // check the destination between current location and goal location - in meters
            distance = [goal distanceFromLocation:workingLocation];

            NSLog(@"distance %f\n", distance);
        }


        // if distance from goal is less than 350 meters
        if (distance <= 350){

                [self scheduleNotification:[tempObject objectForKey:@"name"]];

                // turn off tracking for this location
                [tempObject setObject:@NO forKey:@"onoff"];
                [theData.LocationsObjectArray replaceObjectAtIndex:i withObject:tempObject];

                NSIndexPath *path = [NSIndexPath indexPathForRow:i inSection:0];
                ExtendedSavedCellTableViewCell *cell = (ExtendedSavedCellTableViewCell *)[self.tableView cellForRowAtIndexPath:path];
                cell.switchView.on = NO;

                // save the update to the switch to the database as well
                NSString *lat = [tempObject objectForKey:@"latitude"];

                /*check to determine if the uiswitch is turned off or on.*/

                [self fetchedResultsController:@NO lat:lat index:path];
                [self displayAlertViewForAlarm:[tempObject objectForKey:@"name"]];


}

-(void)displayAlertViewForAlarm:(NSString *)nameOfLocation{

     dispatch_async(dispatch_get_main_queue(), ^(void) {


    UIAlertView *myAlert = [[UIAlertView alloc] initWithTitle:@"Destination reached"
                                                      message:nameOfLocation
                                                     delegate:self
                                            cancelButtonTitle:@"Go Away"
                                            otherButtonTitles:@"Notify", nil];


    [myAlert show];
     });



}

【问题讨论】:

标签: ios objective-c arrays multithreading


【解决方案1】:

如果可以避免的话,在 iOS 中使用线程通常是个坏主意。在您的情况下,我将实现执行循环的函数,以便在多次迭代后自动退出循环,然后安排下一个迭代块在另一个通过事件循环的过程中发生。换句话说,是这样的:

- (void) checkLocationsStartingAt:(NSNumber)start
{
    NSInteger s = (start) ? [start intValue] : 0;
    for (i = s; i < list.length; i++) {
        if (i > TOO_MANY) {
            [self performSelector:@selector(checkLocationsStartingAt:)
                       withObject:@(i) 
                       afterDelay:0.001];
            return;
        } else {
            // check element at i
        }
    }
}

见:NSObject Reference

【讨论】:

  • 这个?我猜你的意思是 self
  • Andrew 我只是有点困惑 TOO_MANY 是从哪里填充的?抱歉这个菜鸟问题。
  • 在 iOS 中使用线程没有任何问题。它受到鼓励,并且在许多情况下都非常有益,尤其是当您使用 GCD(@Miguel 就是这样)之类的东西时。
  • @Miguel 您可以将其定义为程序中其他地方的常量(例如,在 *.m 文件的顶部)
  • @vikingosegundo 哎呀...最近做了很多 JavaScript... :-)
【解决方案2】:

您正在根据一组其他位置检查一个位置。 当您距离某个位置小于 350m 时,您会显示警报。 您可能在列表中许多项目的 350m 范围内。 您没有阻止多个警报的代码。

因此,您有时会收到很多警报。

您有几个选择。一个可能比其他更适合您的需求。可能是我没有列出的一个。

  • 您可以重复使用单个 UIAlertView 实例并检查 visible 属性就可以了。如果它已经可见,则什么也不做。
  • 一旦你得到一个“命中”,你就可以跳出循环
  • 您可以输入BOOL,它会记录您是否显示了警报并且 每次再次显示警报之前,请检查BOOL

【讨论】:

    猜你喜欢
    • 2014-06-08
    • 1970-01-01
    • 1970-01-01
    • 2019-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-16
    • 1970-01-01
    相关资源
    最近更新 更多