如何用 Parse 和 Swift 搭建一个像 Instagram 那样的应用?(3)

【编者按】本篇文章作者是 Reinder de Vries,既是一名企业家,也是优秀的程序员,发表多篇应用程序的博客。本篇文章中,作者主要介绍了如何基于 Parse 特点,打造一款类似 Instagram 的应用,完整而清晰的步骤,为开发者提供一次绝佳的学习体验。本文系 OneAPM 工程师编译整理,这是本系列的第 3 篇文章。

使用 Swift 和自定义表视图单元格

现在让我们再次回归代码——已经有足够的接口。打开 CatsTableViewController.swift 并找到指定初始化 init(风格:类名:)。

在这个方法中,我们可以在 self.parseClassName = className;下添加以下两行代码:

self.tableView.rowHeight = 350
self.tableView.allowsSelection = false

第一行设置合适的行高,第二行禁止单元格选择。
然后添加下列代码到 viewDidLoad just above super.viewDidLoad(): 方法

tableView.registerNib(UINib(nibName: "CatsTableViewCell", bundle: nil), forCellReuseIdentifier: cellIdentifier)

该行很可能引发错误。为了尽量不出错,将下面代码从 tableView 的 cellForRowAtIndexPat 方法移动到类的顶部,并重新将其值命名为「CatCell」。

let cellIdentifier:String = "Cell"

类的定义应该类似这样:

 class CatsTableViewController: PFQueryTableViewController  
{
    let cellIdentifier:String = "CatCell"

    override init!(style: UITableViewStyle, className: String!)
}

我们刚刚将 cellIdentifier 常量从局部方法范围扩展成类范围,使得它在整个类中均可用,包括 tableView 的 cellForRowAtIndexPath 和 viewDidLoad。
接下来,我们用下面代码替换 tableView 的 cellForRowAtIndexPath 的内容:

var cell:CatsTableViewCell? = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as? CatsTableViewCell

if(cell == nil) {
    cell = NSBundle.mainBundle().loadNibNamed("CatsTableViewCell", owner: self, options: nil)[0] as? CatsTableViewCell
}

if let pfObject = object {
    cell?.catNameLabel?.text = pfObject["name"] as? String

    var votes:Int? = pfObject["votes"] as? Int
    if votes == nil {
        votes = 0
    }
    cell?.catVotesLabel?.text = "\(votes!) votes"

    var credit:String? = pfObject["cc_by"] as? String
    if credit != nil {
        cell?.catCreditLabel?.text = "\(credit!) / CC 2.0"
    }
}

return cell

你不禁疑惑,这与我们以前使用的旧代码相比有什么区别?主要体现在:

  1. 单元格类型从 PFTableViewCell 改为 CatsTableViewCell
  2. 当单元格为空,新单元格从我们刚才创建的 XIB 文件中得到。我们将从集合中检索,赋予所有当前类所有权,然后将它转换为 catstableviewcell。
  3. 然后,我们检查对象是否存在,并尝试将 Parse 对象的列名赋给它的文本属性,就像之前那样。
  4. 然后,catVotesLabel 和文本属性也一样。Parse 每列的票数是 String 类型,但不是 int,所以要转换成 int 类型吗?如果票数恰好是空值,那么我们就将其设置为零。然后,使用一种称为字符串插值的骚亮技术,设置标签文本。

最后,我们返回单元格。

让我们再次运行应用程序。一切看上去太完美了!没有 Bug 和死机!但是...图像在哪儿?

从 Parse 异步下载图像

图像不见了,这怎么可以!让我们加上它。在 TableView 的 cellForRowAtIndexPath 添加如下代码「在最后一个 if 语句(用于信用标签)之后,在返回语句之前」。

var cell:CatsTableViewCell? = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as? CatsTableViewCell

if(cell == nil) {
    cell = NSBundle.mainBundle().loadNibNamed("CatsTableViewCell", owner: self, options: nil)[0] as? CatsTableViewCell
}

if let pfObject = object {
    cell?.catNameLabel?.text = pfObject["name"] as? String

    var votes:Int? = pfObject["votes"] as? Int
    if votes == nil {
        votes = 0
    }
    cell?.catVotesLabel?.text = "\(votes!) votes"

    var credit:String? = pfObject["cc_by"] as? String
    if credit != nil {
        cell?.catCreditLabel?.text = "\(credit!) / CC 2.0"
    }
}

return cell

哇!这里发生了什么?我们将 Parse 的 URL 列转成了 NSURL 类型的实例。

我们用它在主操作队列中启动异步 NSURLConnection,其中下载图像作为 NSData 对象。当下载完成时关闭执行。它分配下载得到 UIImage 的数据,分配到 catImageView 的图像属性中。

在这里无需钻研太深,因为上面代码的复杂性与我们的应用程序无关。但是,请注意以下几点:

  • 使用 NSURLConnection 很方便,但有点枯燥。当你使用互联网上的数据源做更复杂的事情,请选择优秀的 AFNetworking (Objective-C)或 alamofire (Swift)库。
  • Parse 允许你将图像存储在云端,并能直接使用。它是 ParseUI 的组成部分,但它不允许外部 URL(猫图片源自 Flickr)的调用。
  • 在开始另一个异步连接之前,我们首先要明确主队列中的所有操作。这是有点枯燥:它从队列中移除 pending-and-unfinished 下载。尝试删除该行并运行程序,你会看到所有图像混合成一堆。当它重新使用单元格时,出列机制不会重置任何挂起连接,因此图像可以加载成功。

让我们再运行应用,看看是否有效。

加码 : Instagram 的类似功能

进行到这一步了,真不容易!还有一些终极功能有待完善。接下来就让我们来添加这些功能:类似「Instagram」的功能——你在图片上双击,一个「赞+1」被添加到该猫的图片上,并显示一个干净的小猫爪动画。

首先,为爪子图像到表视图单元格添加出口。添加下面一行代码到 CatsTableViewCell 类(在其他四个出口的下面):

@IBOutlet weak var catPawIcon:UIImageView?

在 Interface Builder 中添加一个 UIImageView 到 CatsTableViewCell.xib。还记得怎么做的吗?

  1. 在对象库中查找 UIImageView 类。
  2. 将它从对象库中拖放到表视图单元格。

确保将其向右拖动到其他图像视图的中心。调整新图像,宽高均为 100 点,它的 X 和 Y 均为大约110点。然后,当图像视图已选中时,添加以下限制。

  1. Editor → Pin → Width
  2. Editor → Pin → Height
  3. Editor → Pin → Top Space To Superview
  4. Editor → Align → Horizontal Center In Container

正如下图所示,使图像视图水平居中,固定宽度和高度为100点,并保持它与顶部有固定的空间,有效地将其居中的猫图像的放在正中心。

Imgur

现在,通过从文档的顶部选择猫的表格视图单元格,创建出口连接。再选择 Connections Inspector 选项卡,从 catpawicon 单元格图像视图中绘出一条蓝色的线。

接下来,下载 paw.zip。该文件包含三个图形文件,是一个图像的三种分辨率。在使用之前需要将它们导入。

首先,解压缩文件;然后,打开 Xcode 中 Images.xcassets 文件;接着右键单击左侧列表(一个写着 APPICON 的列表),然后单击新建图像集,或使用左下方的「加号」按钮。重命名刚才创建的图像集,打开其属性。

现在,将刚才解压的文件从 Finder 拖至打开的文件集。确保文件匹配:

  • paw.png 是 1x.
  • paw@2x.png 是 2x.
  • paw@3x.png 是 3x.

看不到文件也不用担心,因为它们都是白色。

Imgur

然后,返回 CatsTableViewCell.xib 并选择小图像视图。找到属性检查器,然后从在图像下拉列表中选择合适的爪子图像。白色的爪子应该像下图这样显示在单元格视图。

Imgur

最后,请记住连接与 catPawIcon 出口和小图像视图。
现在,让我们回到编码。打开 Xcode 中的 CatsTableViewCell。将下面的代码添加到 awakeFromNib 方法中(在super.awakeFromNib() 之前)。

let gesture = UITapGestureRecognizer(target: self, action:Selector("onDoubleTap:"))
gesture.numberOfTapsRequired = 2
contentView.addGestureRecognizer(gesture)
catPawIcon?.hidden = true

这里会发生两种情况。

  • 第一,我们建立一个 UITapGestureRecognizer,这样我们便可以跟任何视图互动。在这种情况下,我们将其添加到 contentView 查看,这个视图包括单元格的两个标签和两个图像视图。它为 onDoubleTap: 初始化一个 target、self、一个动作和一个选择器。所以,当检测到连续双击时,方法 onDoubleTap:of self(当前类)被执行。此外,我们设置连续数目为 2,使得它为双击响应。

  • 第二,我们隐藏 catPawIcon 出口。

其次,添加 onDoubleTap 方法到当前类(在 awakeFromNib():函数之后)。

func onDoubleTap(sender:AnyObject) {
    catPawIcon?.hidden = false
    catPawIcon?.alpha = 1.0

    UIView.animateWithDuration(1.0, delay: 1.0, options:nil, animations: {

        self.catPawIcon?.alpha = 0

        }, completion: {
            (value:Bool) in

            self.catPawIcon?.hidden = true
    })
}

这种方法被称为一个动作,始终需要一个参数:AnyObject。在该方法中,可以实现以下动画代码:

  1. 首先,通过设置隐藏为 false,使 catPawIcon 可见。
  2. 然后,将 alpha 即透明度设置为1.0,完全可见。需要重置图像状态,也就是当动画完成时 alpha 通道为0。
  3. 动画的设置需要编程。UIView 的类方法被使用,这需要五个参数:动画时间、动画前延迟、基本选项、动画属性的关闭,以及动画完成时关闭的指令。

这时你会看到:

  1. 为了使图像可见,我们可以设置它的 alpha 通道为可见。
  2. 稍等一下动画延迟。
  3. 动画 alpha 通道从1到0的时间不到一秒,这就是动画周期。
  4. 动画完成,隐藏图像。

这个解决方案的最大好处在于它易于使用:代码将完全管理动画。我们只需要设置它的初始状态、结束状态、持续时间,以及动画框架插补状态和动画步骤。从技术上来讲,我们使用两个属性:一个连续的值 α,一个用来隐藏管理爪子图像可见性的布尔值。

最后,运行应用,看看新功能能否正常适用。你可以双击一个单元格,简要展示爪子图标,双击然后淡出消失。

如何用 Parse 和 Swift 搭建一个像 Instagram 那样的应用

能运行了吗?太棒了!

用 Parse 整合投票

剩下要做的事就是给 Parse 猫对象增加投票数列,通过双击响应投票动作。

那么我们怎么去实现呢?

首先,我们要改变的对象叫做 PFObject 类型的对象,在 CatsTableViewController 的 tableView 的 cellForRowAtIndexPath 方法中。我们不能从表视图单元访问它,因为它在双击动作的方法内。

我们不能移动 onDoubleTap 方法,所以我们需要在表视图对象和表视图单元之间创造引用。

我们采取以下步骤来实现:

1.在 CatsTableViewCell 中,在类的顶部和网点下,编写下列代码创建一个新的属性:

var parseObject:PFObject?

2.然后,在 tableView 里的 cellForRowAtIndexPath,编写下面代码(就在单元格 == nill 语句结束的大括号后面),如下:

cell?.parseObject = object

现在,我们已建立一个机制,将 cellForRowAtIndexPath 的对象复制到我们的表视图单元,使得在 CatsTableViewCell 类的对象实例可用。
然后,调整 CatsTableViewCell的onDoubleTap 方法。在该方法的开始处添加下面代码:

if(parseObject != nil) {
    if var votes:Int? = parseObject!.objectForKey("votes") as? Int {
        votes!++

        parseObject!.setObject(votes!, forKey: "votes");
        parseObject!.saveInBackground();

        catVotesLabel?.text = "\(votes!) votes";
    }
}

这段代码可以实现以下工作:

  1. 检查 parseObject 是否为空;
  2. 从 parseObject 得到票数,并将它放在可选的 Int 中;
  3. 如果票数不为空,用 ++ 操作增加票数变量,与 votes = votes! + 1 有相同功能;
  4. 用 setObject 函数将票数变量返回给 parseObject 集;
  5. 调用 parseObject 的 saveInBackground() 方法!它在后台将保存当前对象,可能的时候将其写入 Parse 云端;
  6. 更新文本以反馈新的票数,一切就是这么简单,用 Command-R 或 Play 按钮运行程序,验证新功能是否实现。

运行成功了吗?太赞了!

小结:

通过本篇文章,我们学习了以下内容:

  • 用 Parse 实现检索,存储数据到云端;
  • Cocoapods整合一个调用 Objective-C 框架的 Swfit 程序;
  • 建立视图和有接口的自定义表视图单元;
  • 从零开始,用 Swift 编写一个完整的 App;
  • 使用自动布局和约束;
  • 使用手势识别、可选类型、条件、闭包、属性、出口和动作。

你可以在这里下载整个爪子项目文件。使用 Xcode6.3(或以上)版本运行项目。请注意,你必须改变 AppDelegate.swift 中的应用程序键和客户端密钥。另外也要记住,如果你自己动手编写这个完整的 App,对自己是个很好的提升机会。(完结)

原文地址:http://www.appcoda.com/instagram-app-parse-swift/


本文由OneAPM工程师编译 ,想阅读更多技术文章,请访问OneAPM官方技术博客


OneAPM 官方技术专栏
OneAPM 官方技术分享平台

Software makes the world run. OneAPM makes the software run.

11.4k 声望
509 粉丝
0 条评论
推荐阅读
Cloud Alert 实现告警智能降噪,成功规避告警风暴
睿象云前段时间发表了一篇《 Zabbix 实现电话、邮件、微信告警通知的实践分享》的技术文章。它帮助我们非常轻松地支持了各种告警通知方式,但是存在一个严重的问题,我们经常接到各种相类似或者相关联告警,短信...

OneAPM蓝海讯通1阅读 2.1k

提高 Xcode 编译速度方法大总结
在最新版本的 Xcode 中,编译后查看 Report Navigator 面板,点击刚刚的那次编译,即可查看到整个编译流程,以及每一步的耗时。右键点击任意一个步骤,选择 Show In Timeline 可打开一个时间线面板,在实现面板中...

SwiftFun阅读 884

全面掌握 Swift 包依赖管理工具 —— 命令行、Manifest API、Xcode、二进制包、集合、插件
Swift 包管理工具,即 Swift Manager Package,简称 SwiftPM,是 Swift 开源项目的一部分,提供了包依赖管理的功能。相对于 CocoaPods、Carthage 等第三方管理工具,SwiftPM 是苹果自己研发,并和苹果平台和 Xcod...

SwiftFun阅读 761

swift 第二节课学习笔记 字符串连接
{代码...} 输出结果HelloWorld,asdhjdh,200请按任意键继续. . .

风口的猪会飞阅读 687

【iOS逆向与安全】系统推送服务(APNS)拦截
经过之前的分享,相信大家已经掌握了用户级的插件开发。勤奋好学的你是否对系统级的插件也有着浓厚的性趣,本篇文章将和大家一起学习如何分析并编写一款系统级的插件。

小陈阅读 381

【iOS】字符串NSString转换为emoji表情的方式
emoji的表情存成uint32的形式,如0x1f60d、0x1f603等,可以通过系统方法转换为emoji的表情,emoji表情可以直接复制到其他地方打开。正常存储往往以字符串的形式保存。以下为Swift及oc版本的字符串转emoji表情的方...

Lynx阅读 340

云音乐 Swift 混编 Module 化实践
云音乐 iOS App 经历多年的迭代,积累了大量的 Objective-C(以下简称 OC) 代码,目前已经完成主工程壳化,各层组件关系如下:

云音乐技术团队阅读 330

封面图

Software makes the world run. OneAPM makes the software run.

11.4k 声望
509 粉丝
宣传栏