A running App iOS complete implementation (with source code and instructions)

A record of running applications, can record the motion path and process data, functions more complete, by the end of 15 years of doing was added to the project, the developer account expired AppStore has not found, but some Android market can find the Android version.

Source code as a learning exchange. See github.

Application screenshot

Application about this long, cut off some of the interface

A running App iOS complete implementation (with source code and instructions)
1.jpg

A running App iOS complete implementation (with source code and instructions)
2.jpg

A running App iOS complete implementation (with source code and instructions)
3.jpg

A running App iOS complete implementation (with source code and instructions)
4.jpg

Project file structure

The file structure of the project is as follows

A running App iOS complete implementation (with source code and instructions)
5.jpeg

Interface related implementations are all in View, and other files are implementations that are more independent and related to the entire project.

Personal preference is to divide files into function modules, such as running related functions that can be dedicated to a file, and user related functions that can be placed in another file. See some other open source projects, such as the MVVM architecture for the project, will be specifically divided into Model, ViewController, ViewModel three folder, then all the relevant documents both functional division of the whole heap to the corresponding file in. Here there will be a problem when using more complex, each folder will have a lot of documents, from go to modify the file is very troublesome, but also modify the same function but also across the working folder.

There is also a way to folder is divided by function, and then in each file to achieve the corresponding function, and then press MVVM or MVC schema division of the corresponding folder, to see personal preferences.

The realization of the interface, personal habits is associated with the close part of the interface, to separate out as an independent control, provide to modify the data interface, the view controller directly from the control, and through the external interface to modify the control display, without attention to internal control, such as layout related settings of a specific UI to achieve. Sometimes the controls contain other controls. In short, in order to encapsulate external irrelevant code into a class, external operations control only needs to focus on logical implementation.

Before the company’s project, seen a view controller class that contains all the settings to generate layout view, processing and related business logic, the result is a UIViewController class file code line number nearly 30 thousand, it is the nightmare of maintenance personnel. So, individual biases separate independent code into a single file, whether it’s interface layout, or business process processing, and try to ensure that each file’s code is within hundreds of lines.

Layout mode

Most view control uses Xib to do automatic layout, not to do with storyboard page Jump, because most of the time with a laptop to do development, small screen to see a bunch of storyboard together with the interface experience bad. At that time, or at the end of 15 years of development, iOS9’s reference has just come out, the project needs to be compatible with iOS8.

Some of the layout of the view, the need for very small calculation, too lazy to build a new Xib, directly through the calculation of frame way to achieve.

Some places that use Xib, but need to do layout changes, refer to the layout constraint NSLayoutConstraint, which adjusts the layout constraints in a code way.

There are also places that try to implement automatic layout using pure code defined NSLayoutConstraint, which means that the amount of code implemented is too large to facilitate subsequent maintenance changes.

Take some code and feel it.. This code is actually in the Xib, which is to add a view to the upper and lower left and right edge constraints and the corresponding spacing, the interface can be achieved a few points, and replaced by code will use a lot of lines. So the layout in the project can be basically Xib using Xib, and I’m lazy.

[self addConstraint:[NSLayoutConstraint constraintWithItem:_contentView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual... ToItem:self attribute:NSLayoutAttributeTop multiplier:1.0 constant:0.0]] [self addConstraint:[NSLayoutConstraint constraintWithItem:_contentView attribute:NSLayoutAttributeBottom; RelatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0.0]] [self addConstraint:[NSLayoutConstraint constraintWithItem:_contentView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual; toItem:self attribute:NSLayoutAttributeLeading Multiplier:1.0 constant:0.0]]; [self addConstraint:[NSLayoutConstraint constraintWithItem:_contentView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:0.0]];...

If you really want to use code to implement automatic layout, recommend a framework Masonry that encapsulates the NSLayoutConstraint and implements a layout constraint in a more intuitive and elegant coding style. The framework has a corresponding version of SnapKit, Swift, and is maintained by the same team. Specific to view the official document.

Third party Library

Third party libraries are mainly used:

  • High moral map SDK: used to do path mapping and positioning
  • ShareSDK: third party sharing and login
  • FMDB: local database operations
  • AFNetworking: network request
  • Alliance SDK: do point count and user feedback

The third party libraries used are placed in the project Vendors folder, where the source and resources of the third parties are directly dragged into the project and manually added the required system library to the project target. This is not a good way of doing things. Do you recommend managing third parties or recommend using CocoaPods?. Of course, this approach also has a benefit, that is, it is convenient for others to project download down, nothing can be directly run. 🙂

Bluetooth connectivity

Applications can access data via Bluetooth peripherals. We have matching sports underwear, you can collect heart rate after you wear it. Data is obtained by scanning nearby Bluetooth devices and connecting them to the heart rate.

The whole Bluetooth related process is the standard Bluetooth protocol, and iOS comes with the framework &lt: CoreBluetooth/CoreBluetooth.h&gt, which deals with the process.

Code specific implementation in the Bluetooth folder under the YSBluetoothConnect class.

The corresponding agent is used for Bluetooth event callback processing, such as device connection, disconnection, and heart rate data acquisition.

CBCentralManagerDelegate CBPeripheralDelegate

The heart rate data seems to have a fixed standard field in the Bluetooth device, the constant of this field inside the code.

Static NSString *ServiceHeartRateUUIDStr = @ 180D '; static NSString *CharacteristicHeartRateUUIDStr = @ 2A37'";

So it should be as long as the Bluetooth device that can send heart rate can transmit data to this application. Code inside the Bluetooth device name of the prefix to determine the processing, if you want to try their own, and even other Bluetooth devices can judge the prefix notes.

Some interfaces require Bluetooth data to display. In order to obtain analog Bluetooth data, this field is directly set to YES.

Static simulationMode = BOOL / / generation rate of YES simulation is set to YES;

Voice prompt

Voice folder under the YSVoicePrompt class, movement tips per kilometer, if you connect the heart rate device, will be based on whether the heart rate in a specific range to do the corresponding prompts. Prompted to set up male voice female, resource files in Audio.bundle, audio resources or at that time specifically Taobao to find someone to do.

Database operation

The main implementation under the Database file. FMDB encapsulates the system’s own SQLite, making it possible to operate the database directly with OC.

The database primarily stores user information and each running data, such as the GPS path coordinates for each run record, and the heart rate data collected during exercise. When displaying information about the interface, you need to query from the database.

A record of running applications, can record the motion path and process data, functions more complete, by the end of 15 years of doing was added to the project, the developer account expired AppStore has not found, but some Android market can find the Android version.

请求相关的处理实现在 Network 文件下。如用户的注册时的验证码,登录注销,云端数据同步和本地数据上传等。具体接口可看 YSNetworkManager.h 文件注释。

租用的服务器已过期,所以现在的请求基本都返回超时,只能看着接口自行脑补过程了。

地图功能

整个应用最核心的功能就是和地图相关的路径记录了。使用的是高德SDK。具体的功能实现在 Manager/Map 文件下。

主要的实现类为 YSMapManager

运动开始结束时调用的接口

- (void)startLocation;
- (void)endLocation;

MAMapView 为显示地图的视图,用来显示地图和绘制运动路径。

实现MAMapView的代理MAMapViewDelegate,定位实时更新时会收到对应的回调

- (void)mapView:(MAMapView *)mapView didUpdateUserLocation:(MAUserLocation *)userLocation updatingLocation:(BOOL)updatingLocation

回调参数里会包含新的定位的信息,将新获取到的定位数据保存,并重新绘,即可看到实时的运动轨迹。

实时路径的绘制具体可看代码,也可看这篇文章,高德地图实时路径绘制代码实现,忽略其他的代码。

YSMapPaintFunc 类实现了将获取到的定位点依次连成一条路径显示在地图上。GPS定位有时候会存在一定的误差,绘制到地图上会显示毛刺,实现的时候用了个小算法将这些毛刺点做了平滑处理,具体自己看代码啦。

记录路径的过程中还需要计算一些其他的值,如总距离,平均速度,当前速度,配速等。这些东可以通过搜集到的定位数据和时间来进行计算。YSMapPaintFunc类用来做相应的计算。

计时器

Manager/Time 中实现。YSTimeManager 主要用了一个Runloop通过一定的时间间隔来不断刷新界面和时间相关的信息。需要注意的是NSRunLoop在主线程和子线程使用的区别。

Manager/CaptchaTimer 中的实现为倒计时,用户手机注册时会发送验证码,发送验证码按钮点击之后会有一定的时间将按钮置灰,以防止频繁的发送验证码。

应用配置

Manager/ConfigYSConfigManager 类用来记录应用的配置,通过系统的NSUserDefaults进行保存。需要配置的信息较少,也就语音提示选择男声或女声,界面上时候显示实时心率数据的面板,蓝牙默认连接。配置的选项不多。

Models

Models文件加下有很多model,当时初衷是将一些相关的数据保存在一个类里,方便作为参数进行数据传递。如单次跑步相关的数据保存到一个model里,传递给专门展示这些数据的视图做为界面的显示。现在回过头看感觉处理得有点乱,也许不是个好的实践,读者请自行斟酌参考。

应用的界面实现

界面相关的代码实现全在View文件夹下。

A running App iOS complete implementation (with source code and instructions)

6.jpeg

文件夹对应的功能实现

login

用户相关功能的实现,如注册登录,修改重置密码等。

Settings

设置界面,提示音设置,打开关闭心率面板,用户反馈。

Calendar

tabBar左边的日历界面,当时想用UICollectionView来实现个日历控件,后面调试的时候发现有些日期cell之间的左右间隔在设为0之后还是会出现细线,不得以只能强行用一个UIScrollView在上面自己贴UIView的方式来实现了这控件。性能还有待优化,左右滑动切换日期时有时会有卡顿现象。

Run

主要的几个界面:

  • The YSRunViewController:tabBar intermediate interface displays the recorded population data and begins the movement of the entrance
  • YSRunningRecordViewController: in the process of moving, the interface mainly contains two views, which display the map view of the real-time moving track and the view without displaying the map
  • YSResultRecordView: the interface that displays the results after the end of the movement

User

tabBar右边的用户界面,显示当前用户信息,登录注销,修改用户资料的入口。

SportRecord

记录单次运动具体信息和数据分析的界面。

几个文件实现的功能:

  • Detail: details of the interface, the movement of the distance, time, speed, etc.
  • HeartRate: the heart rate data interface analyzes the proportion of heart rate across the range of motion
  • Locus: the trajectory of motion
  • Pace: calculate the speed of each course
  • Share: social sharing, the track generated picture sent

General

一些可以单独抽出来,或者几个界面都会用到的控件。大部分也都是xib实现。

xib实现可复用控件时需要考虑一个问题,使用时是直接用在另一个xib中,还是在代码中通过nibWithNibName的方式加载,两种使用方式设定Custom Class的地方不一样,具体参考源码。

其他

项目的大体情况如上所述,具体的一些细节实现请自行查看源码。:)

最后

源码可以随便使用,不用经过允许。有问题可提issues。

偶然发现腾讯部落小伙伴还在运营,关注数量还挺多,喜欢运动跑步的小伙伴可关注易瘦跑步腾讯部落,每天都会分享运动跑步相关的小知识。:)

完。