【问题标题】:Swift app crashes with `unrecognized selector sent to instance` on CLLocationManagerSwift 应用程序因 CLLocationManager 上的“无法识别的选择器发送到实例”而崩溃
【发布时间】:2014-08-25 02:39:37
【问题描述】:

与 StackOverflow 上的许多其他问题类似,我在运行我的应用程序时遇到 unrecognized selector sent to instance 错误。是什么让我的案例与众不同(我认为)是它是用 Swift 编写的,并且常见的原因不是这里的原因。

this 问题中,解决方案是在 Identity Inspector 中将该视图的“自定义类”设置为响应类。我检查了这个,就是这种情况(请注意,我确实在某些时候重命名了该类,但现在它肯定设置为“ViewController”)。

我包括下面的堆栈跟踪以及ViewController.swift 的代码。您还可以找到所有代码here。我设法通过重新开始来避免这个问题,这使我能够解决我的earlier question。这个新的试用版可以在this branch 找到。但是,我想知道哪里出了问题并解决这个问题。

一些想法

我无法成功回答的一个问题是CLLocationManagerDelegate 是否需要一些必需的方法?但是因为我让它在另一个分支中工作,我怀疑它没有必要。

2014-07-03 21:50:26.056 RowingTracker2[11416:60b] -[CLLocationManager requestWhenInUseAuthorization]: unrecognized selector sent to instance 0xa10c4a0
2014-07-03 21:50:26.059 RowingTracker2[11416:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[CLLocationManager     requestWhenInUseAuthorization]: unrecognized selector sent to instance 0xa10c4a0'
*** First throw call stack:
(
    0   CoreFoundation                      0x008831e4 __exceptionPreprocess + 180
1   libobjc.A.dylib                     0x01e2a8e5 objc_exception_throw + 44
2   CoreFoundation                      0x00920243 -[NSObject(NSObject) doesNotRecognizeSelector:] + 275
3   CoreFoundation                      0x0087350b ___forwarding___ + 1019
4   CoreFoundation                      0x008730ee _CF_forwarding_prep_0 + 14
5   RowingTracker2                      0x00003352 _TFC14RowingTracker214ViewController11viewDidLoadfS0_FT_T_ + 738
6   RowingTracker2                      0x000033a2 _TToFC14RowingTracker214ViewController11viewDidLoadfS0_FT_T_ + 34
7   UIKit                               0x0102f33d -[UIViewController loadViewIfRequired] + 696
8   UIKit                               0x0102f5d9 -[UIViewController view] + 35
9   UIKit                               0x00f4f267 -[UIWindow addRootViewControllerViewIfPossible] + 66
10  UIKit                               0x00f4f5ef -[UIWindow _setHidden:forced:] + 312
11  UIKit                               0x00f4f86b -[UIWindow _orderFrontWithoutMakingKey] + 49
12  UIKit                               0x00f5a3c8 -[UIWindow makeKeyAndVisible] + 65
13  UIKit                               0x00f0abc0 -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 2097
14  UIKit                               0x00f0f667 -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 824
15  UIKit                               0x00f23f92 -[UIApplication handleEvent:withNewEvent:] + 3517
16  UIKit                               0x00f24555 -[UIApplication sendEvent:] + 85
17  UIKit                               0x00f11250 _UIApplicationHandleEvent + 683
18  GraphicsServices                    0x031fff02 _PurpleEventCallback + 776
19  GraphicsServices                    0x031ffa0d PurpleEventCallback + 46
20  CoreFoundation                      0x007feca5 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 53
21  CoreFoundation                      0x007fe9db __CFRunLoopDoSource1 + 523
22  CoreFoundation                      0x0082968c __CFRunLoopRun + 2156
23  CoreFoundation                      0x008289d3 CFRunLoopRunSpecific + 467
24  CoreFoundation                      0x008287eb CFRunLoopRunInMode + 123
25  UIKit                               0x00f0ed9c -[UIApplication _run] + 840
26  UIKit                               0x00f10f9b UIApplicationMain + 1225
27  RowingTracker2                      0x00008021 top_level_code + 97
28  RowingTracker2                      0x0000805b main + 43
29  libdyld.dylib                       0x024ff701 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb) 

ViewController.swift

import UIKit
import MapKit
import CoreLocation

class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
    @IBOutlet var mapview: MKMapView = nil
    var locationmgr : CLLocationManager!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        locationmgr = CLLocationManager()
        locationmgr.delegate = self
        locationmgr.requestWhenInUseAuthorization() ///< Offending line.
//        mapview.showsUserLocation = true
    }


    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

【问题讨论】:

  • 确保您在 iOS 8.x 上进行测试。而不是在 iOS 7.x 或更低版本上。 “requestWhenInUseAuthorization”在 iOS 8.x 及更高版本中可用。
  • … 或者通过检查选择器是否存在来保护调用(还没有开始使用 Swift,在 Obj-C 中它会是 [locationmgr respondsToSelector:@selector(requestWhenInUseAuthorization)]
  • 仅供参考,您可以在 Swift 中使用:locationmgr.requestWhenInUseAuthorization?()。注意“?”前 ”()”。这会检查 API 是否可用,如果是则调用它,否则什么也不做。
  • @gagarwal,谢谢,但是“?”应该在对象名称之后,如locationmgr?.requestWhenInUseAuthorization()。我有这样的,它的工作原理。
  • 不幸的是,它适用于协议中的@optional 函数:stackoverflow.com/questions/24167791/…

标签: ios swift core-location xcode6


【解决方案1】:

同样,如果您看到与 CLLocationManager 相关的此错误,请检查您是否尝试在 iOS14 之前的 iOS 版本上使用 authorizationStatus 属性。

https://developer.apple.com/documentation/corelocation/cllocationmanager/3563952-authorizationstatus

【讨论】:

    【解决方案2】:

    这是我用来支持 iOS 7 中新的核心定位方法且没有错误的方法:

    SEL requestSelector = NSSelectorFromString(@"requestWhenInUseAuthorization");
    if ([locationManager respondsToSelector:requestSelector]) {
       [locationManager performSelector:requestSelector withObject:NULL];
    }
    

    【讨论】:

      【解决方案3】:

      由于requestWhenInUseAuthorization 方法仅在 iOS 8 上可用(根据Apple Documentation),您必须将其包装起来:

      Swift 代码:

      if (locationmgr.respondsToSelector(Selector("requestWhenInUseAuthorization"))) {
        locationmgr.requestWhenInUseAuthorization()
      }
      

      Objective-C 也是如此:

      if ([locationmgr respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
          [locationmgr requestWhenInUseAuthorization];
      }
      

      【讨论】:

        【解决方案4】:

        此代码无法在 iOS 7 及更低版本上运行 - 根据文档,requestWhenInUseAuthorization 仅适用于 iOS 8:

        可用性:

        适用于 iOS 8.0 及更高版本。

        【讨论】:

        • 我需要做什么才能让它在 iOS7 中运行?我需要它,否则我必须将我的 iPhone 移动到 iOS8 并且我每天都在使用它。所以,我宁愿不瞄准iOS8。
        • 我可以不调用那个函数吗?我现在在 iOS7 中这样做并使用 iOS8 模拟器进行了检查,但我想要一个绝对的答案。
        • 如果 CLLocationManager 没有响应该选择器,请不要调用请求函数。您在 iOS7 中隐式获得 Always 授权。使用 respondsToSelector 看看你是否应该调用它。
        猜你喜欢
        • 1970-01-01
        • 2016-02-13
        • 1970-01-01
        • 1970-01-01
        • 2019-10-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多