// // //

大钟威武

从白痴到大师的点滴积累

在实践中快速成长

| Comments

我的这个博客的副标题叫从白痴到大师的点滴积累,不知道有多少小伙伴和我是一样的想法?

我们刚生下来时,都是白痴,懵懂地看着这个世界。随着一步步地成长,你有了一点一滴的积累,逐渐地,你在某些方面不再是白痴,甚至你成为了那方面的大师。 我们在接触一门新技术的时候,刚开始都是白痴,然后你开始成长,成长可能快、可能慢。最后你可能成为了大师,也可能成为了炮灰。每个人的精力有限,他最多也只能在有限的几个方面成为大师,选好方向很重要,别在每个方向上都成了炮灰。

我现在开始学习iOS开发技术,也就是开始做起了白痴。我想我会比其他人学得慢些,因为我基础相当差,我不是计算机科班出身,而且我只会纯C。没接触过C++、Java这两个打面向对象基础的语言。我还有2年的时间没有接触代码,这两年去做产品经理了。所以这次学习iOS开发技术的起点,算是和一个上过C语言课程的大二同学,差不多。

我想初学iOS开发技术的孩纸们,像我这种水平的还是很多的吧,不然不会有那么多培训公司的做广告了。

当然,培训公司做广告的另外一个原因是这技术简单,入门快,可以速成。这也是我选择这门技术入手的一个原因。我希望用最短的时间,学好一门工程技术,并且能学精通。我猴急,因为自己老大不小,自己还想做个高产的开发者,时间不等我,必须让自己快速成长起来。

我还对自己有个要求,就是要靠自学。这个要求有些过分是不是?又要自己成长得快,又要靠自己学,而且自己还没啥基础,这不是又让马儿跑又不给马儿吃草么?恩,是有难度。对我来讲,从产品转技术,是做了很大的决定,就像原来使用刀,现在决定使用剑,我能不能用好剑,还不是百分百的确定,怎么来确定?就是给我一把剑,舞一舞,上战场砍砍人,看看是胜是败。如果这个过程有人一直帮你拿着剑,你怎么能看出自己用剑的潜力呢?选个自己能做得好的方向很重要,不然小心成为炮灰。

在之前的学习中,我学习了几个控件的使用,也学习了几个OC概念,都做了demo,但觉得这样没法说自己啥时候就算是入了iOS技术的门。咋样能算入门呢?得系统地理解iOS的技术;能娴熟应用;能紧跟趋势。这就入门了。

想入门,首先还是得做一个完整的app,这个完整的app需要是个值得上架的产品。在做这么个产品的过程中,会涉及到iOS技术的方方面面,希望这些方面能较为系统地覆盖iOS技术的体系。

我的这个计划从8月上旬开始,在8月9日完成了产品的设计,8月10~18日对产品可能涉及到的技术点进行了预研,做了些测试,8月19日开始开始开发。在过去的这9天的开发工作中,收获实在是大!每天都要解决很多问题,很多问题的解决方法会让自己加深对iOS相关技术的理解。

这会儿正有个烦心的问题需要找原因和解决方案,我打算take a break,换换脑子,回头想想这几天的收获,会心一笑,于是打算唠叨几句写下来^_^。

想让自己快速进步,就是压迫自己亮亮剑。实际做个产品,对学习iOS技术来讲,非常有帮助。学习其他技术是不是也是一样?我猜可能是,这个等我学习其他技术的时候,再做体会。忽然觉得白眉大侠是挺酷的哈,这左手屠龙刀,右手倚天剑的。希望自己别熬到眉毛都白了,才成为大师……

从现在开始,大师之路,走起~

学习iOS传感器的使用

| Comments

iOS涉及到的传感器

不用查资料,用过iPhone的同学都知道。iphone中有加速度传感器,可以感知手机在哪个方向上有加速度,比如屏幕的翻转、飞行控制游戏等都是利用这个特征做的;有指南针(貌似叫陀螺仪?),可以知道你的方向;还有定位装置,可以知道你现在的位置在哪里。

加速度传感器相关功能是由CoreMotion提供;指南针、定位信息相关功能由CoreLocation提供。

CoreMotion

在CoreMotion.framework中,有下面这些类:

1
2
3
4
5
6
7
CMAccelerometerData
CMAttitude
CMDeviceMotion
CMGyroData
CMLogItem
CMMagnetometerData
CMMotionManager

每个是做什么的,可以在官方文档中阅读,就不在这翻译了。其中实现对设备加速度的识别,主要是使用CMMotionManager。

CMMotionManager

如何使用CMMotionManager?

Step1:产生一个CMMotionManager的实例mManager。

Step2:实例使用方法isAccelerometerAvailable判断加速度传感器是否可用。

Step3:如果可用,则通过方法setAccelerometerUpdateInterval设定采样频率。

Step4:最后使用startAccelerometerUpdatesToQueue:withHandler开始采样及对采样进行处理。

示例代码

我在下面的代码中,实现了一个小球在一个框中运动,运动的轨迹是根据手机的倾斜角度计算,运动的方向同倾斜的角度一致,并且倾斜角度越大运动速度越快。 代码下载 在代码的实现过程中,对view的层次有了更深的体会。此外,在给label供数的时候,发现刚好使用代理的方式,算是也对代理做了联系。

编码过程中遇到七七八八问题的记录

学习iOS手势开发 iOS Gestures 开发

| Comments

iOS手势简介

iOS的手势,就是程序识别到你在屏幕上做的一些手势动作,做出反应。常见的手势有

  • UITapGestureRecognizer
  • UISwipeGestureRecognizer
  • UIRotationGestureRecognizer
  • UIPanGestureRecognizer
  • UIPinchGestureRecognizer
  • UILongPressGestureRecognizer

其中tap还有单击、双击,Swipe还有向上、下、左、右等区分。

识别这些手势,对每种手势做个反应,没啥难度。下面总结了5个步骤,和几个特殊的地方。

使用过程分5步

step1: 声明和初始化一个手势识别器

1
2
3
4
5
6
7
8
9
    UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
    UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTap:)];
    UITapGestureRecognizer *twoFingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTwoFingerTap:)];
    UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipe:)];
    UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipe:)];
    UIRotationGestureRecognizer *rotation = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(handleRotation:)];
    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
    UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinch:)];
    UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)];

step2:对手势识别器进行属性设定

1
2
3
4
5
6
 [doubleTap setNumberOfTapsRequired:2];
    [twoFingerTap setNumberOfTouchesRequired:2];
    [swipeLeft setNumberOfTouchesRequired:1];
    [swipeLeft setDirection:UISwipeGestureRecognizerDirectionLeft];
    [swipeRight setNumberOfTouchesRequired:1];
    [swipeRight setDirection:UISwipeGestureRecognizerDirectionRight];

step3:把手势识别器加到view中去

1
2
3
4
5
6
7
8
9
    [self.view addGestureRecognizer:singleTap];
    [self.view addGestureRecognizer:doubleTap];
    [self.view addGestureRecognizer:twoFingerTap];
    [self.view addGestureRecognizer:swipeLeft];
    [self.view addGestureRecognizer:swipeRight];
    [self.view addGestureRecognizer:rotation];
    [self.view addGestureRecognizer:pan];
    [self.view addGestureRecognizer:pinch];
    [self.view addGestureRecognizer:longPress];

step4:出现冲突时,要设定优先识别顺序

1
2
3
4
    [singleTap requireGestureRecognizerToFail:doubleTap];
    [singleTap requireGestureRecognizerToFail:twoFingerTap];
    [pan requireGestureRecognizerToFail:swipeRight];
    [pan requireGestureRecognizerToFail:swipeLeft];

step5:去实现处理扑捉到手势之后的动作 填写各个处理函数,如:

1
2
3
4
5
6
7
8
- (void)handleSingleTap:(UITapGestureRecognizer *)gestureRecognizer
- (void)handleDoubleTap:(UITapGestureRecognizer *)gestureRecognizer
- (void)handleTwoFingerTap:(UITapGestureRecognizer *)gestureRecognizer
- (void)handleSwipe:(UISwipeGestureRecognizer *)gestureRecognizer
- (void)handleRotation:(UIRotationGestureRecognizer *)gestureRecognizer
- (void)handlePan:(UIPanGestureRecognizer *)gestureRecognizer
- (void)handlePinch:(UIPinchGestureRecognizer *)gestureRecognizer
- (void)handleLongPress:(UILongPressGestureRecognizer *)gestureRecognizer

测试代码

在下面测试代码中,实现了六个手势的处理。 代码下载

在实现的时候,有几个需要注意的地方:

注意几个小地方

学习Apple的编码规范

| Comments

编码规范很重要,毕竟你的代码除了你,还有很多人可能需要阅读。遵守一个编码规范,可以使你的代码易于理解和维护。

使用编码规范是个基础技能,采用谁家的编码规范比较好呢?看你给谁工作了。对OC,苹果、google都有自己的一套编码规范,估计其他公司也都有自己成行的编码规范。

google家写过一个被广泛接受的C++编码规范,他家的oc编码规范是结合了苹果家的oc规范和他自家的c++规范。所以对于iOS新手,我觉得先了解一下苹果家的编码规范比较好。

苹果家的编码规范Coding Guidelines for Cocoa

简单翻译了下:

代码名称基础

基本原则

清晰

  1. 又清晰又简洁是最好的了,但简洁不如清晰重要
  2. 总的讲不要使用单词的简写,除了非常非常常用的简写以外(Acceptable Abbreviations and Acronyms),尽量使用单词全称,长点儿不要紧
  3. API的名称不要有歧义,一看你的API就知道是以什么方式做了什么事情,不要让人有疑问

一致性

做某个事情代码通常都叫这个名字,比如tag、setStringValue,那么你也这么叫。你在不确定怎么起名字的时候,可以参考一些常用的名字:Method Arguments

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
...action:(SEL)aSelector
...alignment:(int)mode
...atIndex:(int)index
...content:(NSRect)aRect
...doubleValue:(double)aDouble
...floatValue:(float)aFloat
...font:(NSFont *)fontObj
...frame:(NSRect)frameRect
...intValue:(int)anInt
...keyEquivalent:(NSString *)charCode
...length:(int)numBytes
...point:(NSPoint)aPoint
...stringValue:(NSString *)aString
...tag:(int)anInt
...target:(id)anObject
...title:(NSString *)aString

前缀

前缀一般是2到3个大写之母,可以用来给类、协议、函数、常量、typedef结构起名字时用。但不要给方法用,方法存在的命名空间是类定义的。也不要给结构体的字段使用(the fields of a structure)//没明白是啥意思?

Prefix Cocoa Framework
NS Application Kit
NS Foundation
AB Address Book
IB Interface Builder

Mac下的RSS阅读器

| Comments

学一门新技术,需要有多个条件放在一起,才能学好。都需要哪些条件,仁者见仁,淫者见淫……但至少有一条,就是你需要跟前辈们学。

很多前辈有技术博客,及时地阅读他们的著作是个不错的提升自己的方式。此外,很多网站资源也不错,订阅来看很方便。google reader不在了,在mac下,使用什么不花钱的工具阅读RSS呢?

尝试一番后我最后选择了使用免费版的fresh feed。 先后尝试过:

  1. 此外尝试了mac下的应用RSS Bot,这个也还成,不过预览的时候,不够方便,只能看到标题,之后就得点击链接在网页里看。
  2. 还尝试了Instant RSS Notifier(free版),这个免费版太烂了。
  3. mail里原来是支持RSS阅读的,和看邮件一样看RSS,多好啊,可现在也不支持了。RSS就这么不受待见么?

综合来看还是fresh feed好用些。

P.S. 在尝试过程中,安装了获取RSS feed的Safari插件subscribe-to-feed-1-0b4,安装插件后,会出现RSS图标RSS,点击图标后,会在地址栏得到当前safari页面的feed。

学习iOS的delegation的实现

| Comments

什么是delegation

delegation[ˌdelɪ’ɡeɪʃn],中文叫委托,是两个类之间传递信息的一种方式。也是一种设计模式。

其作用和实现过程可以这么理解:

A类:A正在工作中发现,有的工作自己做不方便,需要委托别人帮忙做。A要制定个协议,委托的人要遵守这个协议,按照协议中的方法把工作给做了。A的属性有遵守这个协议的delegate,A知道这个delegate会帮助完成协议中的工作。

B类:B会受A委托,B类需要接受这个协议,把协议中的必须执行的方法给执行了。B有个属性是A的对象,在B类中把A的对象的delegate设置成B。

这里提到的协议,即protocol,不熟的孩纸可以仔细阅读协议(Protocol)的用法和代码例子

什么时候使用delegation

类之间传递信息可以有多种机制,除了delegation还有notification、observer等方式。一般两个类之间有点儿关系(比如view和subview,view和controller之间,使用delegate)的时候,经常使用delegation;两个模块之间没有啥关系,可能使用notification会更好。有兴趣的孩纸推荐阅读一下When to use Delegation, Notification, or Observation in iOS

在我们使用控件如textField、textView等时,都会碰到他们的delegation,这是非常好的delegation的例子,要好好去理解delegation的功效。

delegation实践

模拟场景

张老师在外地开会,她会发短信告诉学生代表什么时候让学生们放假,学生代表承诺老师会准确传达。张老师发了短信给学生代表,说7月26日周五大家放假。

设计

张老师是委托人,学生代表是受委托人,她和学生代表定的协议中的方法:由学生代表告诉学生们什么时候放假。 张老师发短信给学生代表这个时候会触发他们之间协议的方法。

测试代码

测试代码中有老师和学生代表两个类,输出的结果见NSLog。代码下载

学习iOS的单例模式实现

| Comments

为什么学习iOS的单例模式实现

从设计模式开始说起。设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。

单例模式是设计模式中的一种,并且比较简单,在iOS开发中会常用到,所以新手可以先学习使用单例模式。

新手想了解更多设计模式,可以先了解一下类之间的关系,然后看看设计模式一般遵循的6个原则,之后可以了解下23个设计模式。这里23个设计模式,作者是针对java讲的,但对ios程序设计也一样非常有意义。设计模式本身就是最佳实践的一些总结,新手不必一口气把每个设计模式的奥义都搞清楚,只要了解有这种设计模式,在实践中逐步研究和理解,会更有效率。

对于iOS常用的设计模式,推荐阅读破船之家写的三篇iOS设计模式文章,此外,可以参考iOS的一些基本设计模式

什么是单例模式

单例模式,英文名叫Singleton。规定这个类只能同时存在一个实例,这个实例可以全局调用。

什么情况下使用

有个事你只想让一个人去做,这个人把这个事儿做怎么样,你又希望大家都知道,这种时候可以使用单例模式。这个模式可以用来做一些比较“专注”的任务,同时方便的把资源共享出来。

什么情况下不使用

有人说当这个单例类非常频繁会扩展时,单例模式不适用1

还有违反了单一职责的设计原则,使代码之间耦合度变强,无法进行有效的单元测试2。 所以使用的时候要避免这些情况,尽量让单例不存在过于复杂的依赖性和继承,保证其松耦合等3

单例模式实现

破船之家iOS设计模式(02):单例模式文章中写得很清楚,分为使用ARC情况和非ARC情况。我尝试了其中ARC+GCD的方法,it works fine。

测试代码

在下面测试代码中,实现了2个viewController都从单例类实例中拿数据,第1个viewController的按钮更改了单例类实例的内容,在第2个viewController中可以看到更改。 代码下载


  1. 使用单例模式需要注意的几个问题——这篇文章我看得一头雾水,应该怎么理解?

  2. What is so bad about Singletons?,这个问题的被采纳答案

  3. Singletons in Cocoa, are they evil?推荐大家看这个,这个里面援引了stackflow中有人提到的单例的4个缺点。

学习使用code实现iOS界面

| Comments

为什么要学习使用code实现iOS界面?

iOS界面三种实现方式

code、IB、Storyboard这三种方式都可以实现iOS界面,哪种实现方式合适呢?众说纷纭,合理的答案是依情况而定——嘿,废话。作为iOS的初学者,该如何选择呢?

发展趋势

最早时候,大家都用code,后来出现了IB(interface builder),再后来出现了Storyboard。现在的初学者们,上来接触的就是Storyboard,因为苹果现在的官网教材也好、stanford有名的CS193P课程(2013年叫做Coding Together: Developing Apps for iPhone and iPad, 可以在iTunesU中免费下载)都在推Storyboard。

优缺点1

简单对比一下,更多优缺点比较,请搜搜看2

方法 优点 缺点
code 可以对界面掌控得非常精确;代码容易管理和追踪,很干净,控件属性等有修改可以非常容易看到 代码量大,略显麻烦;接手项目的新人不容易看清楚模块之间的关系
ib 较容易地把界面设计出来 界面在ib中体现一部分,在code中体现一部分,阅读和维护起来有难度
Storyboard 较为清晰的体现各模块之间的关系;较容易把界面设计出来 也会借助code来实现一些界面;多人协作开发时,不好管理

可见,使用code实现界面是最基础的方式,ib和storyboard是希望减少工作量。学习使用code开发界面有助于新手理解其中的原理。

新手要熟练使用code,也会Storyboard

真正干活的时候,大家可能会哪个用得熟就用哪个了。对于我们新手,有精力的话,三种方式都要精通。如果没有那么多精力,至少要熟练使用code实现,同时也要会使用Storyboard。因为Storyboard在快速实现demo时,或小项目你自己开发时,效率是非常高的,可以节约你大量时间。并且从发展角度看,Storyboard会做得越来越完善。

如何用code设置控件

推荐这篇文章:IOS开发之纯代码界面—基本控件使用篇,学习的时候,从第一课开始,一节一节仔细阅读。全是干货,非常容易的你就学会了。

Octopress发表blog文章和管理blog

| Comments

octopress的官方文档

octopress的官方文档写得非常清晰和简洁,你需要的,基本他都教给你了。虽然中文的大家写的octopress的使用博文非常非常多,但还是建议你先阅读一遍octopress的官方文档,你可以从全貌上了解octopress都能做哪些。

Octopress Documentation

发表文章的过程

  1. 本地建立一个新文章。rake new_post[“new post title”],在“source/_posts/”目录下生成一个markdown文件
  2. 编辑这个markdown文件,你可以改名字,也可以改文件的内容
  3. 使用命令rake generate,这时在本地把你添加的新文章做了生成
  4. 使用命令rake preview,这时在浏览器中输入localhost:4000来在本地查看效果
  5. 效果ok,使用命令rake deploy,把本地的部署到github服务端
  6. 过一会儿之后,你的服务端的blog就更新成最新的啦

管理和配置界面

管理和配置界面,就是修改你本地的若干配置文件,之后rake generate成功后,再deploy,就完成了修改。

拿增加页面为例

搭建好的octopress,默认只有blog和achieve两个页面,要增加页面需要两步:

  1. 本地建立个新文件夹。位置没关系,命令使用rake new_page[new-page-title],这个文件夹内应该会包含一个index.markdown的文件,如果没有这个文件,请新建一个
  2. 在blog主页的导航栏上还需要新建个页面名称,否则在blog上是看不到你新建的页面的,这需要编辑

    source/_includes/custom/navigation.html

编辑后的结果类似:

Mac下搭建octopress

| Comments

准备工作

安装Ruby(1.9.3)

mac自带的Ruby版本低,不能适用。mac安装Ruby1.9.3的过程参见Mac安装Ruby on Rails,讲的非常清楚。现在有Ruby2.0.0,具体安装方式请google。

你的系统还应该装有git,rvm

开始搭建

搭建过程参考使用Octopress + Github管理blogRuby开源项目介绍(1):octopress——像黑客一样写博客,这第二篇有些标题党哈。这两篇都可参考。

注意:参考这两篇文章前,需要先安装Ruby1.9.3,否则按照他们说的步骤来,你可能遇到很多个步骤无法执行完全成功。

安装过程中可能遇到的问题