网点更名?破坏 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()?的主要内容,如果未能解决你的问题,请参考以下文章
geocoder.geocodeAddressString 今天不再适用于快速更新
来自 geocodeAddressString 的无法识别的选择器错误处理结果
如何从 CLGeocoder geocodeAddressString() 中的完成处理程序更新列表中的地址