怎么着创立三个像RunKeeper一样的App

By admin in 亚洲必赢app在哪下载 on 2019年2月17日

怎么着创立一个像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>
那篇教程将向您来得,咋办1个近似于RunKeeper一样,基于GPS的可以记下您跑步轨迹的app.

其一新的app.我们就叫它MoonRunner吧.

接下去,你就要完结这些动态轨迹记录app的具备功用

  • 追踪宗旨地方
  • 当您跑步时显得地图,并且实时更新行动路线
  • 在跑步时不停展现当前的平分速度
  • 依据距离不相同设置徽章奖励系统
  • 当您本次跑步为止的时候显得这一次跑步全体的运行轨迹

Getting Started

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

打开并运行程序就足以看见一个要命简短的布局:

  • 首页突显的是一个简单的导航按钮
  • 您可以记录或然发轫一遍新的奔走记录的时候所在的拾叁分界面是NewRun界面
  • 在一回跑步的详情页可以瞥见这一次跑步的详细信息,包含彩色标注的地图

Starting the Run

第1,我们要求对项目做一些装置

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

其一设置可以保障,尽管你零时须求接听电话,程序推入后台时还是维持地点音信的更新

亚洲必赢app在哪下载 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

CLLocationManager和它的安顿

当懒加载的时候,你就会为NewRunViewController设置代理CLLocationManagerDelegate

随后设置了精确性为best(_locationManager.desiredAccuracy =
kCLLocationAccuracyBest),在你活动的时候,你可以格外规范地读取本人的岗位新闻,同样,你也会费用相比多的电量

activityType属性设置为.Fitness的用途:
例如当你过马路或然终止的时候,它会只好的转移配置崩你节省电量

distanceFilter设置为10米,相对于desireAccuracy,这一个天性不会影响电量,它是有利于突显任何品质的值的

如果您做个小小的的测试你就会发现,你的位移新闻不是一条直线而是有那些锯齿状

高精度的distanceFilter就足以收缩锯齿,给你二个更精确地轨道,不过,太高的精度值会让你的轨道像素化(看到众多罗利克),所以10m是一个针锋绝对相比较适宜的值

接下去,在view威尔Appear(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
    }

本条格局每一秒都会调用,在调用的时候,你拥有的数据值都会尾随时间变化而创新

在你开始跑步前呢,还有最终3个主意要调用

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()

亚洲必赢app在哪下载 2

其一界面会不停立异具有数据

编译运营,如若你start你就足以瞥见时间值初始在不断扩大

然而,distance和pace文本框不会更新,因为你还从未绘制位移轨迹,接下去我们做那部分

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这么些数组唯有2个因素,即便有三个,它们会安份守己时间先后排序

CLLocation中隐含了比比皆是消息,包含经纬度等等。可是在读取这几个新闻在此之前,会有三个horizonAccuracy的审查,尽管设备觉得这项数据在20米之内的值不是很准确的时候,会自动的将这项数据从数额汇总移除。那几个核查功能在奔跑的时候极其紧要,用户在首先次运营开展校准的时候,这几个时候,它或者会更新一些不可信的数据

比方CLLocation通过了检测,就会起来盘算距离。那时候distaFromLocation(_location:
CLLocation)方法就很便利了,它亦可考虑到各样光怪陆离的关系到地球曲面的动静

末段,添加那几个岗位对象生成贰个一段时间内位爆发的带有三个职分对象的数组

注意
CLLocation对象也暗含了相对应的VerticalAccuracy的海拔的数值,每1个runner都了然,小山坡会给跑步进度添加很多不均等的感想,因为海拔中度会影响你对氟气的须求量,它会给您有的不大的挑衅,当然,这些数据也会引用在App里

Send the Simulator on a run

自小编期望那么些科目和App的绽开能让您对移动与健身暴发巨大的热忱,然而你付出的时候不需求依据字面意思逐字地去领悟它

你不必要在测试的时候确实的拿先河机去跑步,模拟器就足以帮您完结这些职责

在模拟器中运转程序,然后采用Debug ->Location ->City
Run,模拟器就会给您1个虚构的数目

亚洲必赢app在哪下载 3

自然,那样相比较便于也不需求花费精力去测试相对于其余的依据地点信息的App

然则,作者也会提议你实在拿起初机做三个如实测试,这样你才有机遇去微调你的职分管理的参数,去评估你获取的数目质量

并且也牵动你养成健康的生活习惯

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.你创立了3个新的笔录,记录了你运动的离开和消费的时刻

2.当把一三种的CLLocation对象保存到三个Location对象里面的时候,你就把跑步经过的那些坐标点都连接起来了

3.保存NSManagedObjectContext

说到底,当用户甘休奔跑并且要把这一次跑步的笔录封存下去的时候就会调用这一个办法。找到

extension NewRunViewController: UIActionSheetDelegate {
}

这个extension,在

if buttonIndex == 1

其一block里地第贰行写上

saceRun()

编译、运转,你就能够发轫一遍新的跑步记录同时把数量保存下去

亚洲必赢app在哪下载 4

不过,跑步详细音讯的界面依旧是空的,以往大家去落成它

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()

于今,编译运营,你就足以在模拟器上见到那般的地图彰显了

亚洲必赢app在哪下载 5

Finding the Right Color

本条App已经很cool了,可是你还是能显得用户跑的到底有多快,那样,他们就能够识别在区其他山势条件中,他们有没有保持在适合的速率上

要做那些效能的话,你需求增加polyline那么些类

新建五个类,叫做MulticolorPolylineSegment,打开,删除里面的始末,写入以下代码

import UIKit
import MapKit

class MulticolorPolylineSegment: MKPolyline {
  var color: UIColor?
 }

那么些自定义的polyline将用来渲染轨迹的每2个有的。颜色的深浅将代表速度的速度,如此以外,它和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)
  }

以此方法会再次回到二个数组,那么些数组装得是多元的职责点相对应的进程值,其中也就归纳了最大速度和纤维速度。重返的多少个值,你可以将它们放在2个元组里

第③,你应该注意的是输入的享有地点点是三个环。你须要将每壹个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
  }

那里,你定义了两种颜色分别代表慢速、中速、飞速。每个颜色,分别有它的GL450GB值得范围,最慢得一些是全浅灰,最快是全樱桃红,中速是纯茶青,别的时候颜色会基于速度大小在辛巳革命->品蓝->淡绿时间渐变,所以最后展现出来的结果必然会很灿烂

亚洲必赢app在哪下载 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)
    }

在此地,你可以得到事先统计的进程值、速度的界定,也就可以由速度变化的快慢程度来规定颜色变化的深浅程度

接下去,你可以依据八个像对应的坐标和颜色创设1个新的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都被渲染成了一定的水彩

再度编译运维,你就能见到那样三个情调丰裕的地形图突显了

亚洲必赢app在哪下载 7

Leaving a Trail Of Breadcrumbs

最一生成的地图看起来很灿烂,然则在跑步进度中它是何许的吧

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

亚洲必赢app在哪下载 8

下一场,为它丰盛约束

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

然后打开 NewRunViewController.swift 添加

import MapKit

接着,添加成员属性

@IBOutlet weak var mapView:MKMapView!

在 view威尔Appear 方法中添加

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,并且安装代理为近年来控制器

编译运转,将会看到地图实时更新

亚洲必赢app在哪下载 9

Where To Go From Here

此处有其一例子的共同体代码
http://cdn4.raywenderlich.com/wp-content/uploads/2015/05/MoonRunner-Part1-Final.zip

亚洲必赢app在哪下载,你可以看看哪些用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

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图
Copyright @ 2010-2019 亚洲必赢app官方下载 版权所有