新普金娱乐网址


一个平常美国口,究竟会傻到什么水平?

地理消息之团伙形式

怎样创建一个诸如RunKeeper一样的App(一)swift版

  • 十月 12, 2018
  • 地理
  • 没有评论

怎么样创建一个像RunKeeper一样的App(一)swift版

</br>
本博将不期更新外网的iOS最新教程

简书: @西木

微博: @角落里的monster

本文翻译自raywenderlich,版权归原作者所有,转载请注明出处

原文地址为 http://www.raywenderlich.com/97944/make-app-like-runkeeper-swift-part-1

</br>

原博提供了两份示例代码,分别为刚开始项目配置时的、part 1完成时的,地址分别为:

http://cdn4.raywenderlich.com/wp-content/uploads/2015/05/MoonRunner-Starter.zip

http://cdn4.raywenderlich.com/wp-content/uploads/2015/05/MoonRunner-Part1-Final.zip

</br>
当即篇教程将为而显得,如何做一个近乎于RunKeeper一样,基于GPS的足记下你飞步轨迹的app.

本条新的app.我们不怕被它MoonRunner吧.

通下,你将完成这个动态轨迹记录app的装有机能

  • 追踪核心位置
  • 当你飞步时展示地图,并且实时更新行动路线
  • 以跑时连显示当前之平均速度
  • 基于距离不同设置徽章奖励系统
  • 当你这次跑步了之早晚显得这次跑步整体的运转轨道

0.jpg

Getting Started

求下充斥本课程对应之代码,路径为:
http://cdn4.raywenderlich.com/wp-content/uploads/2015/05/MoonRunner-Starter.zip

开辟并运行程序就可以看见一个杀简洁的布局:

  • 首页显示的是3独简单的领航按钮
  • 您得记录或开始同不善新的奔走记录之早晚所当的杀界面是NewRun界面
  • 在同一涂鸦跑步的详情页可以看见这次跑步的详细信息,包括彩色标注的地图

大别山在于中华安徽省、湖北省、河南省交界处,西接桐柏山,东延为霍山与张八岭,东西绵延约380公里,南北宽约175公里,一般海拔500~800米。山地主要有海拔1500米左右,是长江以及淮河底丘陵。独特的地理位置让那针对性民国都南京同主导城武汉持有重要性之行伍价值,这也是当下刘邓大军挺进大别山的地理前提。大别山区大凡我国知名的革命老区之一,土地革命战争时期全国第二大革命根据地——鄂豫皖革命根据地的中心区域。1947年夏天,刘邓大军挺进大别山,揭开全国性大进攻的开局。大别山区各异常,位于华东地区,靠近国民政府首都南京跟湖北要塞武汉,具有特有的战略地位。

Starting the Run

先是,我们得对品种举行有装

  • 点击MoonRunner的project navigator
  • 选择Capabilities tab
  • 打开Background Modes
  • 勾选Location Updates

本条设置好保证,即使你零时需要接听电话,程序推入后台时依然维持位置信息之换代

地理 1

属下,选择Info tab,打开Custom iOS Target
Properties,将下面两实行在plist

key type value
NSLocationWhenInUseUsageDescription String MoonRunner wants to track your run
NSLocationAlwaysUsageDescription String MoonRunner wants to track your run

它们的作用是,iOS会弹有提示框询问用户是否同意该app使用location data

注意
只要您的app要达标传App
Store,你用以App的discription中注明:在后台持续利用GPS会回落电池的寿

搭下去回去代码中,打开NewRunViewController.swift加入

import CoreLocation
import HealthKit

以你用过多之基于位置信息之API和Health模块的method

下一场,你还待以文书尾加入class
extension,来遵守CLLocationManagerDelegate合计

// MARK:- CLLocationManagerDelegate
extension NewRunViewController:CLLocationManagerDelegate{

}

跟着而用贯彻有摄方,完成对位置信息更新的监听

连接下加入一些成员属性

var seconds = 0.0
var distance = 0.0

lazy var locationManager:CLLocationManager = {
    var _locationManager = CLLocationManager()

    _locationManager.deledate = self
    _locationManager.desiredAccuracy = kCLLocationAccuracyBest
    _locationManager.activityType = .Fitness

    // Movement threshold for new events
    _locationManager.distanceFilter = 10.0
    return _locationManager
}()

lazy var locations = [CLLocation]()
lazy var timer = NSTimer()

这些性的意

  • seconds : 记录轨道的事件间隔,单位凡秒
  • distance : 截止当前时时跑了大半远,单位凡米
  • locationManager : 对象,在start或者stop的随时记录用户之职
  • timer : 记录时刻,更新UI

刘邓.jpg

CLLocationManager和它们的部署

当懒加载的时节,你就是会也NewRunViewController设置代理CLLocationManagerDelegate

就设置了精确性为best(_locationManager.desiredAccuracy =
kCLLocationAccuracyBest),在您活动的时,你可好纯粹地朗诵博好的岗位信息,同样,你呢会消耗比较多的电量

activityType属性设置为.Fitness的用途:
例如当你过街道或者已的早晚,它见面只能的变更配置崩你省电量

distanceFilter设置为10米,相对于desireAccuracy,这个特性不见面影响电量,它是福利显示任何性能之值的

苟您做个细的测试你就是会意识,你的各类移信息不是一模一样条直线而是发生不少锯齿状

愈精度之distanceFilter就得减少锯齿,给你一个还准地轨道,但是,太强之精度值会让你的轨迹像素化(看到许多马赛克),所以10m凡是一个相对比适合的价

连通下去,在viewWillAppear(animated: BOOL)方法的末段加上这等同履

locationManager.requestAlawayAuthorization()

这个方法是iOS8才有,用来求用户授权允许下位置信息,如果您想为您的App兼容iOS8前的本,还索要测试兼容性

通下当实现中参加这个措施

override func viewWillDisappear(animated: Bool) {
   super.viewWillDisappear(animated)
   timer.invalidate()
}

以此方式的意思是,当导航控制器不形该页面时,时间的记录为会告一段落

复补充加斯点子

func eachSecond(timer:NSTimer) {
        seconds++
        let secondsQuantity = HKQuantity(unit: HKUnit.secondUnit(), doubleValue: seconds)
        timeLabel.text = "Time: " + secondsQuantity.description
        let distanceQuantity = HKQuantity(unit: HKUnit.meterUnit(), doubleValue: distance)
        distanceLabel.text = "Distance: " + distanceQuantity.description

        let paceUnit = HKUnit.secondUnit().unitDividedByUnit(HKUnit.meterUnit())
        let paceQuantity = HKQuantity(unit: paceUnit, doubleValue: seconds / distance)
        paceLabel.text = "Pace: " + paceQuantity.description
    }

是主意各一样秒都见面调用,在调用的早晚,你有所的数据值都见面从时间别而创新

在你开始跑前为,还有最后一个办法而调用

func startLocationUpdates() {
        // Here, the location manager will be lazily instantiated
        locationManager.startUpdatingLocation()
    }

此办法会报告manager,需要开更新位置信息了

在真奔跑之前也,还需在startPressed(sender:
AnyObject)方法吃参加这些代码

    seconds = 0.0
    distance = 0.0
    locations.removeAll(keepCapacity: false)
    timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "eachSecond", userInfo: nil, repeats: true)
    startLocationUpdates()

地理 2

以此界面会不停更新具有数据

编译运行,如果您start你就可以看见时间价值开始当连追加

但是,distance和pace文本框不见面更新,因为您还从来不绘制位移轨迹,接下去我们做这有

相传大别山原是一样切开汪洋,根本没有山。孙悟空大闹天宫,将玉皇大帝灵宵宝殿的神鳖一骄人打下天宫。当时玉皇大帝命太白金星赴东海呼吁龙王商议降妖之业。太上老君行进途中,见玉帝的神鳖在大方中游动,想拘捕起带动回,哪能分晓神鳖见不过上老君提它,不思量退天宫,遂化作千里连连的群山,填满了海洋。太上老君搬它不动,只好作罢。玉帝降妖之后,太上老君禀报神鳖之务,玉帝与诸仙至南天门来看。只见巨鳖头朝南尾向北巍然不动。玉帝说:“它既在凡间成山,不乐意以天成仙,就以它失去吧。”一天,王母娘娘与七各仙女听说神鳖在人世变成大山,想看变成什么样模样。她们母女来到南天门,只见神鳖变成了绵延起伏的小山,磷峋怪石,奇岩峭壁,山涧溪水,飞瀑叠叠。山上光秃秃的,未显现一草一木。娘娘叹道:“此鳖山畸形怪状,若会种上花草树木,也不小于仙宫良苑。”仙女们说:“我们何不到花园里采些种籽来撒下去,不也不怕成为了人间花园了么!”七仙女便下到人间,遇上同样弟子姓董名永,因家贫无钱安葬死去之阿爸,只得卖身为奴。七姐深受感动,与董永结百年之好。七姐用巧手金梭织出了10配合锦绢赎出了董永,准备收拾门恩爱白头。不料玉皇大帝得知十分勃然大怒,急召七姐回天•••••所以这里是向天庭的“绿色通道”。董永的孝心感动了仙女下凡留于了人间,为了想这无异天上人间的爱情故事,随把这地方起名孝感,就是今底湖北孝感市。大鳖山即使改成了王母及七仙女分别的地方,因此“大鳖山”就改名为“大别山”。当地公民感恋这段惊天动地的情爱,就将当时段美好的机缘故事编写成了本土的戏曲,经久传唱,这就是闻名遐迩的经黄梅戏《天仙配》。

Recording the Run

汝早就创办了一个CLLocationManager对象,你应当去那边将到如创新的数目,这些可透过代理来落实

一如既往是NewRunViewController.swift这个文件,给咱们事先写的 class extension
实现 CLLocationManagerDelegate 代理方

func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
        for location in locations as! [CLLocation] {
            if location.horizontalAccuracy < 20 {
                // update distance
                if self.locations.count > 0 {
                    distance += location.distanceFromLocation(self.locations.last)
                }

                //sace location
                self.locations.append(location)
            }
        }
    }

要有职务更新的时候这主意就是会为调用,通常状况下,locations这个数组只来一个要素,如果来差不多独,它们会依照时间先后排序

CLLocation中包含了森消息,包括经过纬度等等。但是当读取这些信息之前,会来一个horizonAccuracy的查处,如果设备看这项数据在20米之内的价未是那个规范之时,会自行的拿这项数据由数据汇总移除。这个对功能于奔跑的下极其重要,用户以第一次启动开展校准的时候,这个时候,它可能会见更新一些请勿标准的数量

如CLLocation通过了检测,就会见初步算距离。这时候distaFromLocation(_location:
CLLocation)方法就是坏有益了,它能考虑到各种奇异的涉到地曲面的情

末了,添加这个岗位对象特别成一个一段时间内位产生的含有多个职务对象的数组

注意
CLLocation对象为饱含了彼此对应之VerticalAccuracy的海拔的数值,每一个runner都明白,小山坡会让跑步过程添加很多未一致的感想,因为海拔高度会影响您针对氧的需求量,它会给你有些很小的挑战,当然,这个数也会见用在App里

大别山林鸡.jpg

Send the Simulator on a run

本身想这个科目以及App的开放能够吃您对运动与健身产生极大的满腔热情,但是你开之早晚不待以字面意思逐字地失去解她

乃不欲在测试的时确实的将在手机去奔,模拟器就好扶持你成功这个职责

在模拟器中启动程序,然后择Debug ->Location ->City
Run,模拟器就见面被你一个虚构的数量

地理 3

本来,这样比较便于啊无欲耗费精力去测试相对于其他的依据位置信息之App

而,我也会提议您实在将在手机召开一个属实测试,这样您才生机会错过微调你的职管理的参数,去评估你取的数码质量

同时为推动你养成健康之生活习惯

林下养殖01.jpg

Saving the Run

公之前已计划好了UI,那么现在安装数据吧

入这办法及NewRunViewController.swift中

func saveRun() {
    // 1
    let savedRun = NSEntityDescription.insertNewObjectForEntityForName("Run",
      inManagedObjectContext: managedObjectContext!) as! Run
    savedRun.distance = distance
    savedRun.duration = seconds
    savedRun.timestamp = NSDate()

    // 2
    var savedLocations = [Location]()
    for location in locations {
      let savedLocation = NSEntityDescription.insertNewObjectForEntityForName("Location",
        inManagedObjectContext: managedObjectContext!) as! Location
      savedLocation.timestamp = location.timestamp
      savedLocation.latitude = location.coordinate.latitude
      savedLocation.longitude = location.coordinate.longitude
      savedLocations.append(savedLocation)
    }

    savedRun.locations = NSOrderedSet(array: savedLocations)
    run = savedRun

    // 3
    var error: NSError?
    let success = managedObjectContext!.save(&error)
    if !success {
      println("Could not save the run!")
    }
  }

这边做了呀呢?如果你之前举行了Core Data
Flow的话语,这看起颇像是保存了千篇一律长长的新的跑记录:

1.你创造了一个新的笔录,记录了您活动的离开及花的流年

2.当把同密密麻麻的CLLocation对象保存及一个Location对象中的早晚,你便拿跑步经过的那些坐标点都连接起来了

3.保存NSManagedObjectContext

最后,当用户已奔跑又使将这次跑步的记录保留下来的时节即便会见调用这个方式。找到

extension NewRunViewController: UIActionSheetDelegate {
}

这个extension,在

if buttonIndex == 1

这个block里地第一实践写上

saceRun()

编译、运行,你虽可初步同不成新的跑记录同时将多少保存下去

地理 4

但,跑步详细信息的界面依然是拖欠的,现在我们失去完成它

公鸡03.jpg

Revealing the Map

今,需要我们错过调出地图,打开 DetailViewController.swift 并且导入
Healthkit

import HralthKit

接下来,将下面的代码写及configView()方法里

func configureView() {
    let distanceQuantity = HKQuantity(unit: HKUnit.meterUnit(), doubleValue: run.distance.doubleValue)
    distanceLabel.text = "Distance: " + distanceQuantity.description

    let dateFormatter = NSDateFormatter()
    dateFormatter.dateStyle = .MediumStyle
    dateLabel.text = dateFormatter.stringFromDate(run.timestamp)

    let secondsQuantity = HKQuantity(unit: HKUnit.secondUnit(), doubleValue: run.duration.doubleValue)
    timeLabel.text = "Time: " + secondsQuantity.description

    let paceUnit = HKUnit.secondUnit().unitDividedByUnit(HKUnit.meterUnit())
    let paceQuantity = HKQuantity(unit: paceUnit, doubleValue: run.duration.doubleValue / run.distance.doubleValue)
    paceLabel.text = "Pace: " + paceQuantity.description

  }

这边设置了驱的详细信息,可以来得在屏幕的文本框里

1.首先,要设置你所于的地理位置

2.设置了移动轨迹的起始点

3.装了进度之显得风格

以脚的法门在类中

func mapRegion() -> MKCoordinateRegion {
    let initialLoc = run.locations.firstObject as! Location

    var minLat = initialLoc.latitude.doubleValue
    var minLng = initialLoc.longitude.doubleValue
    var maxLat = minLat
    var maxLng = minLng

    let locations = run.locations.array as! [Location]

    for location in locations {
      minLat = min(minLat, location.latitude.doubleValue)
      minLng = min(minLng, location.longitude.doubleValue)
      maxLat = max(maxLat, location.latitude.doubleValue)
      maxLng = max(maxLng, location.longitude.doubleValue)
    }

    return MKCoordinateRegion(
      center: CLLocationCoordinate2D(latitude: (minLat + maxLat)/2,
        longitude: (minLng + maxLng)/2),
      span: MKCoordinateSpan(latitudeDelta: (maxLat - minLat)*1.1,
        longitudeDelta: (maxLng - minLng)*1.1))
  }

MKCoordinateRegion可以依据你提供的主干岗位,水平以及竖直范围来规定当前屏幕显示的是孰区域

诸如,当您想吃你的动轨迹的亮看起较舒适一点来说,可以拖拽或者缩放地图。这或多或少消肯定地报用户,这样他见到的门径才能够显在屏幕中心

进而,添加脚这主意

func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {
    if !overlay.isKindOfClass(MKPolyline) {
      return nil
    }

    let polyline = overlay as! MKPolyline
    let renderer = MKPolylineRenderer(polyline:polyline)
    renderer.strokeColor = UIColor.blackColor()
    renderer.lineWidth = 3
    return renderer
  }

其一措施表示当代表轨迹的曲线重合的上,你的轨道曲线的水彩会加重,让您看起再也直观,颜色加深的那么部分凡出于一系列的位置点产生的

连下去,你得也polyline定义一个coordinates,添加这个法

func polyline() -> MKPolyline {
    var coords = [CLLocationCoordinate2D]()

    let locations = run.locations.array as! [Location]
    for location in locations {
      coords.append(CLLocationCoordinate2D(latitude: location.latitude.doubleValue,
        longitude: location.longitude.doubleValue))
    }

    return MKPolyline(coordinates: &coords, count: run.locations.count)
  }

此地而用Location的多少传到了CLLocationCoordinate2D这个数组中

接下来,添加以下方式

func loadMap() {
    if run.locations.count > 0 {
      mapView.hidden = false

      // Set the map bounds
      mapView.region = mapRegion()

      // Make the line(s!) on the map
      loadMap()
    } else {
      // No locations were found!
      mapView.hidden = true

      UIAlertView(title: "Error",
        message: "Sorry, this run has no locations saved",
        delegate:nil,
        cancelButtonTitle: "OK").show()
    }
  }

这个方法吃,位置点绘制了,地图显示的区域也开跑前安设的区域,重合轨迹的有些做了火上浇油的颜色渲染

终极,将以此法上加到configView()的终极

loadMap()

如今,编译运行,你就是足以在模拟器上来看这么的地形图显示了

地理 5

林下养殖07.jpg

Finding the Right Color

此App已经非常cool了,但是你还足以显得用户跑的到底出多快,那样,他们即使好辨认在不同之山势条件面临,他们生没有发出保在合适的速率达到

比方开此职能的话,你用扩大polyline这个看似

新建一个好像,叫做MulticolorPolylineSegment,打开,删除里面的情,写副以下代码

import UIKit
import MapKit

class MulticolorPolylineSegment: MKPolyline {
  var color: UIColor?
 }

其一自定义的polyline将故来渲染轨迹的各一个有的。颜色的深浅将代表速度之速度,如此以外,它跟MKPolyline是相同的。它们还是故来形容连接两只位置点支架的线

连片下你如果规定,在怎样的线条上面运用什么的颜料。添加这个类似措施在MulticolorPolylineSegment
这个看似中

private class func allSpeeds(forLocations locations: [Location]) -> (speeds: [Double], minSpeed: Double, maxSpeed: Double) {
    // Make Array of all speeds. Find slowest and fastest
    var speeds = [Double]()
    var minSpeed = DBL_MAX
    var maxSpeed = 0.0

    for i in 1..<locations.count {
      let l1 = locations[i-1]
      let l2 = locations[i]

      let cl1 = CLLocation(latitude: l1.latitude.doubleValue, longitude: l1.longitude.doubleValue)
      let cl2 = CLLocation(latitude: l2.latitude.doubleValue, longitude: l2.longitude.doubleValue)

      let distance = cl2.distanceFromLocation(cl1)
      let time = l2.timestamp.timeIntervalSinceDate(l1.timestamp)
      let speed = distance/time

      minSpeed = min(minSpeed, speed)
      maxSpeed = max(maxSpeed, speed)

      speeds.append(speed)
    }

    return (speeds, minSpeed, maxSpeed)
  }

此方法会返回一个反复组,这个累组装得是多样的职务点相对应的速度值,其中也就是概括了极致要命快跟无限小快。返回的基本上独价值,你得将它们放在一个元组里

率先,你该小心的凡输入的备位置点是一个环。你待将各国一个Location转换成CLLocation,这里您得运用
func distanceFromLocation(_ location: CLLocation!) ->
CLLocationDistance 这个方法

依据物理学常识,速度 = 路程 /
时,所以你就是可以得到用户以飞步着列一样时时速度的转情况

其一措施是个体方法,只能于看似中调用。然后,添加这个方式

class func colorSegments(forLocations locations: [Location]) -> [MulticolorPolylineSegment] {
    var colorSegments = [MulticolorPolylineSegment]()

    // RGB for Red (slowest)
    let red   = (r: 1.0, g: 20.0 / 255.0, b: 44.0 / 255.0)

    // RGB for Yellow (middle)
    let yellow = (r: 1.0, g: 215.0 / 255.0, b: 0.0)

    // RGB for Green (fastest)
    let green  = (r: 0.0, g: 146.0 / 255.0, b: 78.0 / 255.0)

    let (speeds, minSpeed, maxSpeed) = allSpeeds(forLocations: locations)

    // now knowing the slowest+fastest, we can get mean too
    let meanSpeed = (minSpeed + maxSpeed)/2

    return colorSegments
  }

此,你定义了三种颜色分别表示慢速、中速、快速。每一样种植颜色,分别有它们的RGB值得范围,最缓慢得有些凡是都红,最抢是全绿色,中速是纯黄色,其它时候颜色会基于速度大小在辛亥革命->黄色->绿色时渐变,所以最后显示出的结果自然会要命灿烂

地理 6

待专注的是公什么样从allspeeds这个元组中以到最好老价值、最小值和平均值

末,在刚刚底措施的尾到return colorSegments 之前参加这段代码

for i in 1..<locations.count {
      let l1 = locations[i-1]
      let l2 = locations[i]

      var coords = [CLLocationCoordinate2D]()

      coords.append(CLLocationCoordinate2D(latitude: l1.latitude.doubleValue, longitude: l1.longitude.doubleValue))
      coords.append(CLLocationCoordinate2D(latitude: l2.latitude.doubleValue, longitude: l2.longitude.doubleValue))

      let speed = speeds[i-1]
      var color = UIColor.blackColor()

      if speed < minSpeed { // Between Red & Yellow
        let ratio = (speed - minSpeed) / (meanSpeed - minSpeed)
        let r = CGFloat(red.r + ratio * (yellow.r - red.r))
        let g = CGFloat(red.g + ratio * (yellow.g - red.g))
        let b = CGFloat(red.r + ratio * (yellow.r - red.r))
        color = UIColor(red: r, green: g, blue: b, alpha: 1)
      }
      else { // Between Yellow & Green
        let ratio = (speed - meanSpeed) / (maxSpeed - meanSpeed)
        let r = CGFloat(yellow.r + ratio * (green.r - yellow.r))
        let g = CGFloat(yellow.g + ratio * (green.g - yellow.g))
        let b = CGFloat(yellow.b + ratio * (green.b - yellow.b))
        color = UIColor(red: r, green: g, blue: b, alpha: 1)
      }

      let segment = MulticolorPolylineSegment(coordinates: &coords, count: coords.count)
      segment.color = color
      colorSegments.append(segment)
    }

每当此地,你可拿到先计算的速度值、速度的限,也即足以由速度变化之快程度来规定颜色变化的浓度程度

对接下去,你可以根据两独如对应的坐标和颜料创建一个初的MulticolorPolylineSegment。最后,你收集到持有的颜料部分后,就可以准备开渲染了

寒冬季节,不要光是想在吃牛羊肉火锅。要论养生食补,有同一是少不了的,那就是是——鸡。吃鸡,有酷多种吃法。如果想使极其滋补,那自然要吃炖鸡。每次放假返家,奶奶总是会逮一独最肥沃的家养老母鸡,炖上等同大锅鸡汤。时过境迁,现在想如果在外喝上同碗纯正的鸡汤,都并非易事,更别说若吃上鲜嫩的鸡肉!

Applying the Multicolored Segments

怀念要于detail View Controller使用新的 multicolor polyline
很简短,打开DetailViewController.swift,找到 loadMap() 方法,将

mapView.addOverlay(polyline())

替换成

let colorSegments = MulticolorPolylineSegment.colorSegments(forLocations: run.locations.array as! [Location])

mapView.addOverlays(colorSegments)

此地开创了一个segments地理的屡屡组,并且把富有overlays加到了map上

说到底,你只要未雨绸缪让polyline上面每个segment渲染成特定的颜料,所以,用底的代码重写你的mapView方法

func mapView(mapView:MKMapView!, rendererForOverlay Overlay:MKOverlay!)->NKOverlayRenderer!{
    if !overlay.isKindOfClass(MulticolorPolylineSegment) {
      return nil
    }

    let polyline = overlay as! MulticolorPolylineSegment
    let renderer = MKPolylineRenderer(polyline: polyline)
    renderer.strokeColor = polyline.color
    renderer.lineWidth = 3
    return renderer
}

扣押起与之前的不胜像,但是本,每一个segment都被渲染成了一定的颜料

还编译运行,你就能望如此一个情调丰富的地形图显示了

地理 7

鸡汤01.jpg

Leaving a Trail Of Breadcrumbs

最终生成的地形图看起颇灿烂,但是当奔跑过程中她是什么样的啊

打开Main.storyboard 找到New Run Scene,拖一个MapKit View进来到“Ready to
launch” label和start button之间

地理 8

下一场,为它丰富约束

  • 顶部离开label 20 point
  • 地步距离button 20 point
  • 左右离开superView都为0

下一场打开 NewRunViewController.swift 添加

import MapKit

继而,添加成员属性

@IBOutlet weak var mapView:MKMapView!

当 viewWillAppear 方法中上加

mapView.hidden = true

若地图开始时处于hidden状态,在startPressed 方法末尾添加

mapView.hidden = false

点击start的时节地图出现

于文件末尾添加 class extension 实现代理方

// MARK: - MKMapViewDelegate
extension NewRunViewController: MKMapViewDelegate {
  func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {
    if !overlay.isKindOfClass(MKPolyline) {
      return nil
    }

    let polyline = overlay as! MKPolyline
    let renderer = MKPolylineRenderer(polyline: polyline)
    renderer.strokeColor = UIColor.blueColor()
    renderer.lineWidth = 3
    return renderer
  }
}

此跟 run details screen 里地非常像,但是这里的stroke color仍然是蓝色之

连着下,你用写代码去创新地图的示区域,并且以各级出一个卓有成效地Location的时候写轨迹,将你的locationManager(_:didUpdateLocations:)方法的实现创新成为

func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
    for location in locations as! [CLLocation] {
      let howRecent = location.timestamp.timeIntervalSinceNow

      if abs(howRecent) < 10 && location.horizontalAccuracy < 20 {
        //update distance
        if self.locations.count > 0 {
          distance += location.distanceFromLocation(self.locations.last)

          var coords = [CLLocationCoordinate2D]()
          coords.append(self.locations.last!.coordinate)
          coords.append(location.coordinate)

          let region = MKCoordinateRegionMakeWithDistance(location.coordinate, 500, 500)
          mapView.setRegion(region, animated: true)

          mapView.addOverlay(MKPolyline(coordinates: &coords, count: coords.count))
        }

        //save location
        self.locations.append(location)
      }
    }
  }

现今,你时之职务一直当地图的极端基本,同时,蓝色之移动轨迹就你的移动在不停延伸

打开Main.storyboard找到NewRunScene,连接mapView 到map
View,并且安装代理为即控制器

编译运行,将会见看出地图实时更新

地理 9

鸡汤02.jpg

Where To Go From Here

这里发生其一事例的整代码
http://cdn4.raywenderlich.com/wp-content/uploads/2015/05/MoonRunner-Part1-Final.zip

乃可看如何用Core
Data存储数据,怎么样当地图上显得详细的奔跑信息,这是者App最基本之有的

苟您的技术比较好的语句,你可以试试怎么样使用海拔高度信息,怎么样改变轨道宽度,怎么样使用同一聊段的平均速度要颜色变化比较之前更为流畅

in any
case,这首教程还见面发生次片,为汝介绍为每个用户定制的徽章奖励体制

注:

1.本文翻译自
http://www.raywenderlich.com/97944/make-app-like-runkeeper-swift-part-1

2.原博part 2 已更新,着急的同桌可先查看
http://www.raywenderlich.com/97945/make-app-like-runkeeper-swift-part-2

  • 莫定期送及iOS最新教程,但力量有限,翻译不准的地方还望指正

简书:@西木

微博:@角落里的monster

鸡汤03.jpg

闷独鸡,就是牵动吃您大别山区的散养鸡,喝最纯正无添加的鸡汤。在大别山区散养的土鸡,与日常的拱卫养鸡不同。散养鸡可以当山野里任意走动,这样虽能够取得充分的运动量,不仅可给小鸡更加正规快速的成材,又能够吃该肉质更加美味。这才是极端本生态的鸡,营养价值也是环绕养鸡没法比的。

1.jpg

2.jpg

3.jpg

破除养鸡的生活条件特别关键,无论是生长空间,还是基本,都一定要是杜绝污染之。饿了就算吃周围的各种植物和小虫子,渴了就是喝附近的山泉水。这样不错的生态环境,超低密度之繁育,鸡本长得跟别人家的匪一样。在此处,母鸡至少要通过300天散养,公鸡则至少要经过150上散养。足天的散养鸡,体型紧凑,腿、胸大强壮。不光长得好,就连死下的鸡蛋宝宝还和别人家的匪雷同~

4.jpg

5.jpg

6.jpg

7.jpg

9.jpg

部分人未爱好喝汤,那可就此红烧的做法。加上喜欢的食材,做成自己好的味道~目前极度盛的便是板栗烧鸡,香酥的栗子搭配鲜嫩的鸡肉,一下子会吃少一老大碗米饭。
好之食材,做下的才是好的含意,这是有所调味料都未可知取代的。就像是当下等同单单排养鸡,拒绝人工喂养,才能够做出好味道~

红烧01.jpg

红烧02.jpg

不论春夏秋冬,一年四季,游览大别山红色革命圣地,都足以尝试到这美味的土鸡。这里有老的新民主主义革命革命历史,这里吧是自我之故园。我吧自身的家门感到骄傲,我啊家乡代言。欢迎您来逛大别山,品尝可口,我乐意吗汝为于导哦。

相关文章

No Comments, Be The First!
近期评论
    分类目录
    功能
    网站地图xml地图