# iOS开发之如何制作番茄钟App

语言：zh-CN
原文：[iOS开发之如何制作番茄钟App](<https://allluckly.cn/%E6%8A%95%E7%A8%BF/tuogao37>)
中文：[中文 HTML](<https://allluckly.cn/%E6%8A%95%E7%A8%BF/tuogao37>)
English: [English HTML](<https://allluckly.cn/en/journal/2016-04-15-building-a-pomodoro-timer-app-for-ios/>)
发布于: 2016-04-15T00:00:00+08:00
内容更新于: 2016-04-15T00:00:00+08:00
署名：威權在B612等着那阵温柔的风

围绕番茄钟应用串起定时、通知提醒、音乐播放和 Today Widget，并整理卡片布局、转场、xib 与 URL Scheme 等实现入口，适合结合工程了解功能如何组合。

原文署名威權在B612等着那阵温柔的风，Bison 编辑收录。

[原文所列来源](<http://www.jianshu.com/p/7dedfd704008>)

**阅读前** 这是 2015–2017 年间的技术记录，本次整理未重新运行验证示例。原文发表于 2016 年，采用当时的 Today Widget、通知和 Swift 接口。

> "这是个番茄类的App，接着来我就展示这个App的功能。然后将功能的做法总结出来，将我查阅的资料整理出来。看中那个功能就直接自己动手为自己App添加。："

编辑：[Bison](<https://allluckly.cn/>)  
 投稿：[威權在B612等着那阵温柔的风](<http://www.jianshu.com/p/7dedfd704008>)

![1](<https://allluckly.cn/images/blog/tuogao/tougao37/1.gif>)

## 前言

---

这个App项目的地址：[点此下载](<https://github.com/PoBlue/25min>)

为了做这个App我调查了市面上的番茄钟App，总结写了 番茄钟App调查[文章](<http://www.jianshu.com/p/e997bb222409>)

## 本文章目录

- 定时功能
- 通知提醒
- 音乐播放
- Today Widget
- 自定义UICollectionView Layout
- 自定义转场动画
- lldb
- 读取文件路径
- xib开发
- 胶囊状Button
- Cocoapod的使用
- UILabel 和 URL Scheme

## 定时功能

### NSTimer

使用下面代码这就可以每一秒都执行函数timeUp

```
NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "timeUp:", userInfo: nil, repeats: true)
```

通过在函数timeUp用if语句判断就可以实现定时功能了。

### 能执行操作的通知

效果如图：

![1](<https://allluckly.cn/images/blog/tuogao/tougao37/2.gif>)

就是当收到通知时可以选择相应的选项。 这样可以快速地执行相应操作，避免进入App再点击操作这些繁琐步骤。

实现的文章在这里:[通知提醒 - iOS开发](<http://www.jianshu.com/p/c46b60f06880>)

这个 [项目](<https://github.com/PoBlue/25min/blob/master/README.md>) 这个[文件](<https://github.com/PoBlue/25min/blob/master/25%E5%88%86/AppDelegate.swift>)用到了这个技术

## 播放音乐

实现的文章在这里 [音乐播放器](<http://www.jianshu.com/p/3fb9a8c4b1b1>)

这个 [项目](<https://github.com/PoBlue/25min/blob/master/README.md>) 这个[文件](<https://github.com/PoBlue/25min/blob/master/25%E5%88%86/convinence.swift>)用到了这技术

## 通知栏的TODAY WIDGET

效果如下：

![1](<https://allluckly.cn/images/blog/tuogao/tougao37/3.gif>)

这个[文件](<https://github.com/PoBlue/25min/blob/master/25min/TodayViewController.swift>)用到了这个技术

[教程链接](<http://www.brianjcoleman.com/tutorial-today-widget-ios8/>)  
 [App Extension](<http://www.jianshu.com/p/6b6e74095ec4>)

## 轮转式的卡片效果

先上效果，如下：

![1](<https://allluckly.cn/images/blog/tuogao/tougao37/4.gif>)

由于教程比较长，我就另写了篇文章。  
 利用collectionView的layout 加一点点数学计算

通过以下这篇文章你会了解怎么创建自己喜欢的layout而不是使用UICollectionViewFlowLayout.

这个 [项目](<https://github.com/PoBlue/25min/blob/master/README.md>) 这个[文件](<https://github.com/PoBlue/25min/blob/master/25%E5%88%86/CircularCollectionViewLayout.swift>)用到了这技术

文章传送门:[如何做一个像轮子般旋转的UICollectionView](<http://www.jianshu.com/p/45f39b70263d>)

## 自定义Present ViewController

效果如下：

![1](<https://allluckly.cn/images/blog/tuogao/tougao37/5.gif>)  
 教程文章：[自定义Present 转场动画](<http://www.jianshu.com/p/23613f2679ef>)  
 这个 [项目](<https://github.com/PoBlue/25min/blob/master/README.md>) 这个[文件](<https://github.com/PoBlue/25min/blob/master/25%E5%88%86/CustomPresent.swift>)用到了这技术

## lldb

这次项目我比较常用的就expression命令，因为有它就可以断点App，然后修改一些数据做一些测试。

如图直接修改dimingView的alpha值：

![1](<https://allluckly.cn/images/blog/tuogao/tougao37/6.png>)

传送门:

[更多lldb命令](<http://www.dreamingwish.com/article/lldb-usage-a.html>)

## 读取目录下的所有文件路径

使用fileManager的enumeratorAtPath和nextObject()进行穷举

```
let appMainBundlePath = NSBundle.mainBundle().bundlePath

func filePathesInDir(dirPath:String) -> [String]{
    var filePathes = [String]()
    var fileURL:String


    let fileManager = NSFileManager.defaultManager()
    let enumerator = fileManager.enumeratorAtPath(appMainBundlePath + dirPath)


    while let element = enumerator?.nextObject() as? String{
        if let ext = ext {
                fileURL = appMainBundlePath + dirPath + "/" + element
                filePathes.append(fileURL)

    }

    return filePathes
}
```

有关文件路径访问的文章，[点击本链接](<http://www.hangge.com/blog/cache/detail_765.html>)

## 使用 xib 开发

这样做的效果就是能够快速弄好UI。

![1](<https://allluckly.cn/images/blog/tuogao/tougao37/7.jpg>)

教程是一个一个demo弄的，看完就会了，以下传送门  
 [教程链接](<http://www.ifun.cc/blog/2014/02/22/ioskai-fa-zhi-xibji-qiao-jie-shao/>)

## 胶囊形状Button

效果如图：

![1](<https://allluckly.cn/images/blog/tuogao/tougao37/8.png>)

原理：使用layer的radius，如下图

![1](<https://allluckly.cn/images/blog/tuogao/tougao37/9.png>)

然后只需令radius＝ 按钮高度 ／ 2

![1](<https://allluckly.cn/images/blog/tuogao/tougao37/10.jpg>)

代码如下：

```
func makeRadiusBtn(btn:UIButton,borderColor:CGColor){
    let btnH:CGFloat = CGRectGetHeight(btn.bounds)

    btn.layer.borderColor = borderColor
    btn.layer.borderWidth = 1.0
    btn.layer.cornerRadius = btnH / 2
}
```

关于button的更多效果，例如折角之类的，可以参考下面这个blog  
 传送门：

[button教程](<http://www.wutongwei.com/front/infor_showone.tweb?id=88>)  
 [timing Button](<https://robots.thoughtbot.com/designing-for-ios-taming-uibutton>)

## Cocoapod的使用

文章地址：[Cocoapod使用总结](<http://www.jianshu.com/p/0b6bc7d9b491>)

## 用16进制获取 UIColor

因为网络上大多数都是用16进制表示RGB的，令UIColor能够处理16进制还是挺有用的。

一行宏定义就能满足要求了

```
#define UIColorFromRGB(rgbValue) ［UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0] <br>
```

使用如下

```
self.view.backgroundColor = UIColorFromRGB(0xCECECE);
```

原理

```
#define UIColorFromRGB(rgbValue) \\\\\\\\\\\\\\\\
[UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 \\\\\\\\\\\\\\\\
                green:((float)((rgbValue & 0x00FF00) >>  8))/255.0 \\\\\\\\\\\\\\\\
                 blue:((float)((rgbValue & 0x0000FF) >>  0))/255.0 \\\\\\\\\\\\\\\\
                alpha:1.0]
```

其实就是利用掩码，获取RGB相应位置的数字，然后使用 »进行右移。

例如red，0xCECECE & 0xFF00000 = 0xCE0000 然后16进制中的1个0等于2进制中的4个0,所以0xCE0000 » 16 = 0xCE 接着除以0xFF(255)就可以得出百分比了。

## UILabel

[label的属性](<http://cnbin.github.io/blog/2015/10/15/ios-label-xiang-jie/>)  
 [大小自适应](<https://www.skyfox.org/uilabel-ajust-font-for-size.html>)

## 设置Url Scheme

譬如我有个叫25min的app

在25min app的info.plist设置，添加URL type，设置URL identifier，添加Url Schemes，然后URL Schemes的item 0就是你的Url scheme的开头。 ![1](<https://allluckly.cn/images/blog/tuogao/tougao37/11.png>)

接着在appDelegate添加处理Url Schemes的method

```
//return true 则启动app，false则不启动。
    func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool {
        return true
    }
```

这时使用25min://就可以打开25min app了。可以在Safari上测试打Url 试试能不能跳转。

这个 [项目](<https://github.com/PoBlue/25min/blob/master/README.md>) 这个[文件](<https://github.com/PoBlue/25min/blob/master/25min/TodayViewController.swift>)用到了这技术

(END And Thank U)

[这里](<https://github.com/PoBlue/25min/blob/master/README.md>)有完整的项目代码

---

好文推荐：[iOS开发之AES+Base64数据混合加密与解密](<https://allluckly.cn/aes/AES>)

