网点更名?破坏 geocodeAddressString()?

Posted

技术标签:

【中文标题】网点更名?破坏 geocodeAddressString()?【英文标题】:outlets renaming themselves? breaking geocodeAddressString()? 【发布时间】:2016-09-22 16:31:58 【问题描述】:

环境:

Xcode-8 ios-10 Swift-3

概述:

我有一个关于 Outlets 的奇怪问题,它似乎在设置时更改了目标的名称,我相信这是问题的根源我与geocodeAddressString()

一点背景故事:

我的观点有很多元素,但就本文而言,我主要关注UITextField 以及我认为它们如何影响我的MKMapView 代码(在某种程度上基于我看到的 cmets在这里) 我的UITextField 正在使用扩展(最初由'nhgrif')的稍微修改的形式,我在这里发现它的目的是能够设置菊花链文本字段,例如点击弹出键盘上的 Next(或 Return)按钮将自动进入所需的下一个(或在某些情况下为上一个)文本字段。
private var kAssociationKeyNextField:     UInt8 = 0
private var kAssociationKeyPreviousField: UInt8 = 1 // I added this

extension UITextField 
    @IBOutlet var nextField: UITextField? 
        get  return objc_getAssociatedObject(self, &kAssociationKeyNextField) as? UITextField 
        set(newField)  objc_setAssociatedObject(self, &kAssociationKeyNextField, newField, .OBJC_ASSOCIATION_RETAIN) 
    
    // I added the following
    @IBOutlet var previousField: UITextField? 
        get  return objc_getAssociatedObject(self, &kAssociationKeyPreviousField) as? UITextField 
        set(newField)  objc_setAssociatedObject(self, &kAssociationKeyPreviousField, newField, .OBJC_ASSOCIATION_RETAIN) 
    

从 Xcode / Storyboard 的角度来看,这提供了以下 UI,用于设置菊花链中的下一个(和/或上一个)字段:

向下钻取

除了截屏视频之外,我不确定如何真正解释我所看到的问题,但由于我不知道如何在此处发布此类问题,因此必须进行一堆截屏... 从 Name 字段开始,将 nextField 设置为 Address: 然后选择 Address 字段并将 previousField 设置为 Name 并将 nextField 设置为城市: 到目前为止,一切似乎都运行良好... 现在选择 City 字段并将 previousField 设置为 Address 并将 nextField 设置为状态Yikes!请注意,与 State 字段关联的名称现在是“Next Field" 继续使用 State 字段,将 previousField 设置为 City 并将 nextField 设置为 邮编State 字段仍显示为“Next Field” -现在 Zipcode 字段 ALSO 显示为“下一个字段”李> 以 Zipcode 字段结束,将 previousField 设置为 State - 故意离开 @987654341 @未设置:

更多代码

这是该特定视图类的其余代码中的大部分
class NewLocationViewController: UIViewController, CLLocationManagerDelegate, UITextFieldDelegate 

    @IBOutlet weak var doGeoLocate: UISwitch!
    @IBOutlet weak var name:        UITextField!
    @IBOutlet weak var address:     UITextField!
    @IBOutlet weak var city:        UITextField!
    @IBOutlet weak var state:       UITextField!
    @IBOutlet weak var zipcode:     UITextField!
    @IBOutlet weak var done:        UIBarButtonItem!
    @IBOutlet weak var map:         MKMapView!

    var coords:          CLLocationCoordinate2D?
    var locationManager: CLLocationManager = CLLocationManager()
    var currentLocation: CLLocation!

    override func viewDidLoad() 
        super.viewDidLoad()

        name.delegate    = self
        address.delegate = self
        city.delegate    = self
        state.delegate   = self
        zipcode.delegate = self

        locationManager.requestWhenInUseAuthorization()
        if CLLocationManager.locationServicesEnabled() 
            locationManager.desiredAccuracy = kCLLocationAccuracyBest
            locationManager.delegate        = self
            locationManager.startUpdatingLocation()
        
        currentLocation  = nil
        doGeoLocate.isOn = false
        map.isHidden     = true
        done.isEnabled   = false

        navigationController?.isNavigationBarHidden = false
        navigationController?.isToolbarHidden       = false
    

    func textFieldShouldReturn(_ textField: UITextField) -> Bool 
        if doGeoLocate.isOn == true 
            textField.resignFirstResponder()
        
        else if textField.nextField == nil 
            if (!checkFields()) 
                // walk back up chain to find last non-filled text-field...
                var tmpField = textField
                while ((tmpField.previousField != nil) && (tmpField.previousField?.hasText)!) 
                    tmpField = tmpField.previousField!
                
                tmpField.previousField?.becomeFirstResponder()
            
            else 
                textField.resignFirstResponder()
            
        
        else 
            textField.nextField?.becomeFirstResponder()
        
        return checkFields()
    

    func checkFields() -> Bool 
        //... if doGeoLocate switch is on - return true
        //... if ALL fields are populated, call geocodeAddress() and return true
        //... otherwise return false
    

    func geocodeAddress() 
        print("GA") //#=#
        let geoCoder = CLGeocoder()
        let addr     = "\(address.text) \(city.text) \(state.text) \(zipcode.text)"
        print("ADDR: `\(addr)'")//#=#
        geoCoder.geocodeAddressString(addr, completionHandler: 
            (placemarks: [CLPlacemark]?, error: NSError?) -> Void in
            print("IN geocodeAddressString")//#=#
            //if error.localizedDescription.isEmpty == false 
            //    print("Geocode failed with error: \(error.localizedDescription)")
            //
            //else if placemarks!.count > 0 
                let placemark      = placemarks![0]
                let location       = placemark.location
                self.coords        = location!.coordinate
                self.map.isHidden  = false
            //
         as! CLGeocodeCompletionHandler)    //<<<=== NOTE THIS LINE
    

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) 
        //...
    

    @IBAction func toggleGeoLocate(_ sender: AnyObject) 
        //...
    

    @IBAction func useNewLocation(_ sender: AnyObject) 
        //...
    

在运行应用程序并填写所有字段时,当我单击与邮政编码字段关联的数字键盘中的“完成”按钮时,我遇到了异常。调试日志如下所示:
TFSR: (TFSR Optional("Name") => Optional("Address"))
    Returning false
TFSR: (TFSR Optional("Address") => Optional("City"))
    Returning false
TFSR: (TFSR Optional("City") => Optional("State"))
    Returning false
TFSR: (TFSR Optional("State") => Optional("Zipcode"))
    Returning false
GA
ADDR: `Optional("2112 Murray Avenue ") Optional("Pittsburgh ") Optional("PA") Optional("15217")'
(lldb) 

异常显示为:
    func geocodeAddress() 
        //...
        geoCoder.geocodeAddressString(addr, completionHandler: 
            (placemarks: [CLPlacemark]?, error: NSError?) -> Void in
            //...
         as! CLGeocodeCompletionHandler)    //<<< Thread 1: EXC_BREAKPOINT (code=1, subcode=0x10006c518)
    

是的,我确认我没有在代码中设置断点

求和

我有理由确定geocodeAddressString() 代码是正确的(我在另一个用于 Swift-2 的应用程序中使用它),但我对州和邮政编码的方式非常怀疑 当我尝试将 Outlets 与其他字段链接时,它们会被重命名。有人有什么想法吗?

【问题讨论】:

正如你所说,这无关 - 但你在说什么变量?变量不是以小写字母开头的驼峰式大小写,与函数名称相同吗?或者变量应该是全小写(带下划线?) - 那么这与对象的属性有什么关系? 【参考方案1】:

我建议去掉那些不同的演员:

func geocodeAddress() 
    //...
    geoCoder.geocodeAddressString(addr)  placemarks, error in
        //...
    

让它为你推断出正确的类型是最简单的。


关于网点的命名,IB试图让您的生活更轻松,在没有任何指定名称的情况下为您命名。但是有了这些额外的出口,它的默认算法就达不到要求了。您可以通过在“身份检查器”的“文档”部分中自己命名网点来解决此问题。

【讨论】:

哇!这似乎解决了崩溃问题(谢谢!!),但我仍然不明白为什么设置网点会重命名目标。我将使用新代码更新原始帖子 嗯 - 我是要去编辑帖子,但这样做似乎破坏了格式,所以我只想说,我按照你的建议做了跨度> 关于网点的命名,IB试图让您的生活更轻松,在没有任何指定名称的情况下为您命名。但是有了这些额外的出口,它的默认算法就达不到要求了。您可以通过在“身份检查器”的“文档”部分中自己命名网点来解决此问题。 BINGO - 如果我能在这个答案上给你 2 票,我会的。奇怪的是它会混淆,但很高兴知道我可以自己修复它(很容易)

以上是关于网点更名?破坏 geocodeAddressString()?的主要内容,如果未能解决你的问题,请参考以下文章

geocodeAddressString 不能快速工作

geocoder.geocodeAddressString 今天不再适用于快速更新

来自 geocodeAddressString 的无法识别的选择器错误处理结果

如何从 CLGeocoder geocodeAddressString() 中的完成处理程序更新列表中的地址

测试 CLGeocoder geocodeAddressString 方法地标始终为零

按最近位置排序 CLGeoCoder geocodeAddressString 的结果