求人不若求己——用Swift访问iOS系统通讯录

之所以起这么个题目——求人不若求己,实在是有感而发。不管是论坛、问答网站、QQ群,还是各路视频教程,“怎么用Swift访问系统通讯录”这个问题,我问了n遍,n遍石沉大海……

后来在国外的网站上终于找到了几个关键地方相关的问题,才终于突破了这个现在看来不怎么算得上瓶颈的问题。

其实也难怪,现在大部分用Swift的程序员,原本就很熟悉iOS开发,从OC迁移到Swift只是语法和语言特性上的变化。而对于我这样的菜鸟,连框架怎么引入都不会……虽然有热心老鸟的指点,但是依然快要疯掉了。

尝试一天,试了三种方法:直接桥接现成的类库;写一个简单的OC类库,不同在于不用OC解析数据,而在相对熟悉的Swift种进一步解析;以及最后用Swift重写所有语句,打包成方法,直接调用。

最终写完的SwiftContactTool:

输出示例:

_$!<Home>!$_Phone: 555-610-6679
FirstName: David
FirstNamePhonetic:
_$!<Home>!$_Address_Contrycode: us
Department:
_$!<Home>!$_Address_City: Tiburon
_$!<Home>!$_Address_State: CA
_$!<Home>!$_Address_Country: USA
Note: Plays on Cole’s Little League Baseball Team

twitter_SNS_URL: http://twitter.com/aaaaa
LirstNamePhonetic:
Organization:
Nikename:
_$!<Home>!$_Address_Street: 1747 Steuart Street
LastName: Taylor
JobTitle:
twitter_SNS_Serves: twitter
twitter_SNS_Username: aaaaa
_$!<HomePage>!$_URL: www.net.com
_$!<Anniversary>!$_Date: 2011-12-05 12:00:00 +0000
———

PS. 无论用哪种方法,在Swift下,ViewDidLoad函数中请求通讯录访问权限时,对话框总是被遮挡在加载界面之后,进程如果等待请求结果,应用就会卡在加载界面上;而要是不设置等待,首次启动就跳过了加载通讯录内容的过程…… 暂时,这大概会一直是个无解的问题咯……

Swift学习笔记——访问网络数据、NSURL、解析JSON

访问网络数据

今天用Swift完成了给定地址的邮编查询,代码如下:

Swift语言中,想要访问网络上的API,仍然需要调用ObjC中的一些内容,比如NSData。

NSData的构造函数在Xcode6.1中进行了更新,现在可以直接通过下面的语句获取网络数据(其中nsURL时NSURL格式的地址变量)

let resultNSData: NSData = NSData(contentsOfURL: nsURL)!

NSURL

NSURL是一个专门用来表示url网址的数据类型,在构造中,编译器会要求传入的字符串是utf-8格式的。因此,如果想要访问的网址中含有中文,必须要首先把unicode格式的中文字符,转换成utf-8代码。

似乎Swift的String类型并不自带这样的转换方法,这个转换过程仍然需要NSString的 stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding) 方法来完成:

let nsURL: NSURL = NSURL(string: nsstrURL.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!)!

解析JSON

在NSData中得到了服务器返回的JSON数据后,需要对其进行解析才能输出。NSData自带了JSON的序列化方法,即NSJSONSerialization.JSONObjectWithData 方法。这个方法输出的数据可以保存到一个AnyObject 对象中,接下来的解析需要视数据结构而定了。这次的邮编查询返回的数据,在序列化后就已经可以通过下标进行访问。

但是这个自带的解析方法不是很便于使用,为了简化解析,可以使用一些第三方库,比如SwiftJSON

下面是用两种方式解析一个行政区划json文件的代码,显然前者繁复很多:

用Swift写个2048


【20140828update】项目现在丢在了Github上面:https://github.com/JoeMartini/2048bySwift ,欢迎围观讨论。之前有提到我自己琢磨了个算法来实现数字的移动、叠加。这个算法的重点在于,按照移动方向的反方向遍历当前行或列中各个格子,因为方向相反,可以把检测、叠加和移动在一次循环中完成。今天把它又优化了一下,现在可以检测空行和空列了,对于空列在第一次遍历之后就会跳过,不会一次次遍历咯。算法示意图大概如下:algorithm

 


屏幕快照 2014-08-26 下午8.29.43屏幕快照 2014-08-26 下午8.30.26屏幕快照 2014-08-26 下午8.30.44

写的腰酸背痛啊,不过终于能完整的搞出来一个App了……

虽然是一个“超低难度”的纯本地App,但是涉及到的事件还是蛮丰富的。虽然网上现在已经有很多Swift语言教程,但是面向开发经验比较少的纯菜鸟的却很少,看起来大神们哗哗哗就写完了,新手们完全看不懂写了些啥。虽然Swift语言本身语法很简洁,但是实际的应用开发不可避免的需要各种复杂的调用、托管,我只捡了看懂了的部分方法使用,所以写得异常繁琐。虽然知道MVC因该把Model、View、Controller分开布置,但是xCode不断报错,各种跨文件调用的奇怪问题(比如谁告我一下为什么viewcontroller里面可以访问model里的字典,但是model不能访问view里的函数呢……),搞得我头晕眼花之后毅然决定把所有model们丢到一个文件里了。

找了很久没有找到中意的wordpress代码插件,决定直接截图丢上来嘿嘿


viewController.swift

2014-08-26_20-15-43

models.swift

2014-08-26_20-15-30

Swift笔记20140819update

    1. swift 是大小写敏感的 —— 包括变量名、变量类型、语句关键词……
    2. swift 中,两个整型变量相除,得到的仍是整型,小数部分被无情抛弃了
    3. 两个整型变量相除的结果(整型数)无法直接赋值给一个浮点型或双精度型变量,因为 swift 不允许变量类型隐式转换 average = Float ( Sum ) / Float ( number )
    4. 对于 String 型变量,可以用 string.hasPrefix(“”) 检测开头字符,用 string.hasSuffix 检测结尾字符
    5. String变量有.toInt方法强制转变为Int变量
    6. Double精确到小数点后16位,Float精确到小数点后8位
    7. 可选型?可以用!解包,必须被解包后才能操作
    8. 条件运算符——question?answer1:answer2  question为真取answer1,否则取answer2
    9. 字典所包含的数据对是“无序”的,不需要也无法排序,只能查询
    10. switch xxx case xxx default xxx 语句中可以用 where 语句检测额外的条件 (没懂……)
    11. for 循环中,可以直接用 for ( kind , numbers ) in Dictionary 创建二重循环遍历字典全部元素;之中可用 for number in numbers 遍历数组全部元素
    12. 数组的元素个数用 .count 获得
    13. super.init 语句用于设置父类的初始化属性
    14. 类( Class )的读写属性( var )的 set 语句、willSet 语句中,新属性值的名字可以通过 set( xxxx )的形式指定,不指定时,默认为 newVlaue;newValue 也可以是类的实例的名字
    15. 可以使用一个实例作为新类的一个属性
    16. 枚举其实就是自定义的“组合变量类型”,且其可以有通过函数定义的方法;枚举的赋值范围有限,顺序赋值,可单独赋值,单独赋值后,剩下的原始值会继续、顺序赋值

Movie A Dog’s Purpose (2017)