今天的工作相当的艰苦卓绝,因此过了零点才开始写记录。

    我计划周一周二提交第三个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()

        
    }