今天的工作相当的艰苦卓绝,因此过了零点才开始写记录。
我计划周一周二提交第三个Demo,周三周四提交第四个Demo,然后周五周六闭门练习算法,周日晚上去南京大学报道。
言归正传,第三个Demo是My Location,关于GPS定位的。
工作里程碑如下:
01 GPS Coordinates
02 Tagging Locations
03 Core Data
04 Locations Tab
05 Map View
06 Photo Picker
07 Finished App
__________________________
简单过目一下,会发现这个demo是需要绑定GPS服务的。
事实上,Swift中有3种方式实现Location定位,一种是Wi-Fi,一种我忘了,最后一种就是GPS了。
对于没有GPS模块的设备,就只有两种定位方式了,比如老旧的iPod。
这一demo中我们首先使用了iOS SDK : CoreLocation
最后完成的App可以采集当前的经纬度信息,显示具体到街道名的定位(误差10米以内?5米以内?),
可以拍照采集,可以显示地图。
-------------------------------------------------------------------------------------------------------------------------------------------
01部分我们完成了基本的定位工作,记得应该是精确到5米以内,但是定位总是在美国,也是很奇葩。
首先创建了一个Tabbed Application,这个template包含一个根控制器,和两个视图控制器(First,Second),一个tab Bar Item。
tap按钮开启定位,定位过程中,经纬度的Label会不断更新,直到误差小于阈值。
我们也设置了time out。 如果定位时间过长还是达不到阈值,那就超时强停。
如果定位过程中出现故障,也会报Error。可以说交互信息是很齐备的。
// 更新 lables
func updateLabels() {
if let location = location {
latitudeLabel.text =
String(format: "%.8f", location.coordinate.latitude)
longitudeLabel.text =
String(format: "%.8f", location.coordinate.longitude)
tagButton.isHidden = false
messageLabel.text = ""
if let placemark = placemark {
addressLabel.text = string(from: placemark)
} else if performingReverseGeocoding {
addressLabel.text = "Searching for Address..."
} else if lastGeocodingError != nil {
addressLabel.text = "Error Finding Address"
} else {
addressLabel.text = "No Address Found"
}
} else {
latitudeLabel.text = ""
longitudeLabel.text = ""
addressLabel.text = ""
tagButton.isHidden = true
// new code
let statusMessage: String
if let error = lastLocationError as? NSError {
if error.domain == kCLErrorDomain &&
error.code == CLError.denied.rawValue {
statusMessage = "Location Services Disabled"
} else {
statusMessage = "Error Getting Location"
}
} else if !CLLocationManager.locationServicesEnabled() {
statusMessage = "Location Services Disabled"
} else if updatingLocation {
statusMessage = "Searching..."
} else {
statusMessage = "Tap 'Get My Location' to Start"
}
messageLabel.text = statusMessage
}
}
02部分开始前,指导书讲了关于类的继承、类与对象这些基础知识,以及重写超类方法的问题。
注意到,在table view delegate和datasource方法中,通常不需要call super(IOS API文档会告诉你为什么)。
然后讲了一些Cast的知识。
注意到,as有3种转化方式: 普通, 感叹号, 问号。
as as! as?
as? 允许nil的存在,会跳过代码块。 as! 某种意义上相当于向下转型。。
Xcode会提示你应该用哪种,但是十有八九是 as!
然后又介绍了一些关于结构体 Struts的知识。
之前我理解错了,以为Swift的类不是传统面向对象的类,而是类似于C++结构体的东西,
其实Swift既有类又有结构体,struts are more lightweight than classes.
最后贴一下今天的几点代码吧,指导书完成进度: 112/279。才40%。。。。。
// string(from)
func string(from placemark: CLPlacemark) -> String {
var text = ""
if let s = placemark.subThoroughfare {
text += s + " "
}
if let s = placemark.thoroughfare {
text += s + ", "
}
if let s = placemark.locality {
text += s + ", "
}
if let s = placemark.administrativeArea {
text += s + " "
}
if let s = placemark.postalCode {
text += s + ", "
}
if let s = placemark.country {
text += s
}
return text
}
// ask DateFormatter 将data转换为String
func format(date: Date) -> String {
print(" dateFormatter.string(from: date)")
return dateFormatter.string(from: date)
}
getLocation算是今天的核心代码了:
// getLocation()
@IBAction func getLocation() {
// clear state
placemark = nil
lastGeocodingError = nil
let authStatus = CLLocationManager.authorizationStatus()
if authStatus == .notDetermined {
locationManager.requestWhenInUseAuthorization()
return
}
if authStatus == .denied || authStatus == .restricted {
showLocationServicesDeniedAlert()
return
}
// startLocationManager()
// what state the app is in
if updatingLocation {
stopLocationManager()
} else {
location = nil
lastLocationError = nil
startLocationManager()
}
updateLabels()
configureGetButton()
}