【问题标题】:iPhone performSelectorInBackgroundiPhone performSelectorInBackground
【发布时间】:2011-11-21 11:32:09
【问题描述】:

我有这个问题: 这是我的 appDelegate 文件的一部分,我在其中创建了一个“performSelectorInBackground”方法。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

[self addSplash];

[self getLocation];

[self performSelectorInBackground:@selector(backgroundOp) withObject:nil];

return YES;

}

首先我添加一些启动画面,我得到一个位置和调用背景方法。 这是后台方法的内容:

- (void) backgroundOp
{

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    [self createEditableCopyOfDatabaseIfNeeded];

    [self initTempData];

    [self initApp];

    [self checkDataVersion];

    } 

    [self setAppStrings];

    [self performSelectorOnMainThread:@selector(resultOp) withObject:nil waitUntilDone:YES];

    [pool release];


}

我下载了一些数据,检查数据的版本,为应用程序设置字符串和调用主线程方法来创建标签栏控制器代码:

- (void) resultOp
{

    tabBarController.delegate = self;


    [self.window addSubview:tabBarController.view];
    [self addTabBarArrow];
    [self.window makeKeyAndVisible];

    [self removeSplash];

}

在这里,我创建了一个标签栏控制器并删除了启动画面。然后启动我的 firstViewController。

问题是在我的 firstViewController 中显示了当前位置,但这是错误的。有时是正确的,但很多时候是错误的。 哪里有问题?是否有任何选项如何检查后台线程是否结束?或解决我的问题的其他方法(我只需要:显示带有活动指示器的启动画面和一些消息(此消息在方法中更改,例如 init、获取位置等),然后我需要获取位置、删除启动画面并显示 firstViewController)。 .. 非常感谢

编辑:这是位置代码:

- (void) getLocation 
{


    splashScreenController.splashLabel.text = @"Localization ...";

    locationManager = [[CLLocationManager alloc] init];
    locationManager.delegate = self;
    locationManager.distanceFilter = kDistanceFilter;
    locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
    [locationManager startUpdatingLocation];



}

【问题讨论】:

  • 您没有显示用于接收和评估位置的代码,而只是显示与您的问题完全无关的代码。

标签: iphone objective-c multithreading geolocation performselector


【解决方案1】:

请记住,位置更新运行的时间越长,它就越准确。该位置的第一个“命中”并不总是最好的(大多数情况下是错误的)。

也许你可以在你有 CLLocationManager 事件的地方显示你的代码。

另外,错误的位置与正确的位置相差多少?我认为 AGPS 事物首先通过使用附近的 WiFi 热点快速检查其位置,然后通过使用 GPS 芯片变得更加准确。

【讨论】:

  • 我认为解决方案是检查后台方法是否完成。但我不知道如何检查它......
【解决方案2】:

无论您在何处使用您获取的位置(我无法从您发布的代码中真正看到),您都应该检查您收到的 newLocation 的 Horizo​​ntalAccuracy 属性(如果高度很重要,还应该检查 VerticalAccuracy)。你可以这样说

if(newLocation.horizontalAccuracy < 100) {
    //do something with newLocation
    //because it is accurate to 100 meters
}

如果您不进行这些类型的检查,您可能会得到一些非常不准确的位置,最初距离您的真实位置最多三到四公里。

此外,当使用多个线程时,数据完整性有时会成为问题。您需要确保变量不会在多个方法中同时被访问和更改,或者谁知道您是否会得到正确的输出。

另外,重要的是要注意,在 backgroundOp 中调用的所有方法也将在后台执行,即使没有以这种方式显式调用它们。使用

[self performSelectorOnMainThread:foo withObject:foobar waitUntilDone:NO];

返回主线程。

编辑:

viewDidLoad {
    [super viewDidLoad];
    iterations = -5;
}

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation 
    *)newLocation fromLocation:(CLLocation *)oldLocation {
    iterations++;
    if(iterations > 0) {
        if(newLocation.horizontalAccuracy < 50) {
            //do something with location with radius of uncertainty
            //of less than 50
        }
    }

【讨论】:

  • 但是当我在主线程(不是在后台)上使用 perform 方法尝试这个时,一切正常且良好......
  • 我试试这个:[self performSelectorOnMainThread:foo withObject:foobar waitUntilDone:NO];但什么都没有改变......
  • 我并不是说这会解决你的问题。我只是说这是需要注意的事情。您的问题似乎是您正在使用的前几个位置更新非常不准确。通过使用我向您展示的更改(在使用位置的方法中等待,直到获得足够的准确度,您将获得所需的准确度。
  • 是的,问题如你所说。该应用程序启动速度非常快,但收到的位置不准确。我的解决方法:先调用getLocation方法,再调用[NSThread sleepForTimeInterval:2.0]。然后我得到了正确的位置。
  • 我不会那样做的。尝试在头文件(int)中创建一个计数器变量(称为迭代或其他东西),并在 viewDidLoad 方法中将其初始化为 -5。在您的 locationManager:didUpdateToNewLocation:fromOldLocation: 中,增加迭代次数。然后只有在迭代次数大于 0 时才开始使用 newLocations。这比在主线程上使用 NSThread sleepThreadForTimeInterval 安全得多。
猜你喜欢
  • 2011-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多