开始用Swift开发iOS 10 - 8 Table View和UIAlertController的交互


继续上一部分开始用Swift开发iOS 10 - 7 定制Table Views项目FoodPin的代码,添加两个功能:

  • 点击cell时,产生弹框,弹框中有两个功能选项 CallCheck-in
  • 当点击Check-in选项时,为cell加上对号

理解UITableViewDelegate协议

代理模式在iOS编程中非常常见的。每个代理负责特定的角色或任务,维持系统的简单和干净。当一个对象需要完成特定任务时,可以依靠另一个对象完成。这在软件设计模式中通常叫做"separation of concerns"
UITableViewController就应用了代理模式。两个协议完成不同的任务。UITableViewDataSource协议负责提供和管理table的数据。UITableViewDelegate协议负责设置table的section headings 和 footers,以及操作cell selections和cell recording。

阅读文档

怎么知道UITableViewDelegate中有那些方法呢?

阅读Apple的官方iOS开发文档(https://developer.apple.com/library/ios/))。作为iOS开发者,需要经常阅读API 文档。目前没有单个的书籍可覆盖所有iOS SDK。 Xcode中提供方便的查看文档的方法,在相关代码处option+点击,出现弹框展示文档简介,再在弹框上点击相关代码就直接进入详细文档处。
文档对不同方法进行了分类,比如UITableViewDelegate的文档就有上面提到的Managing Selections

func tableView(UITableView, willSelectRowAt: IndexPath)
func tableView(UITableView, didSelectRowAt: IndexPath)

实现协议中管理列选项方法

  • RestaurantTableViewController类中实现tableView(_:didSelectRowAt:)方法:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath:
IndexPath) {
    // 1
    let optionMenu = UIAlertController(title: nil, message: "What do you want
to do?", preferredStyle: .actionSheet)
    // 2
    let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler:
nil)
    optionMenu.addAction(cancelAction)
    // 3
    present(optionMenu, animated: true, completion: nil)
}
  • 1 创建了UIAlertControllerUIAlertController是从iOS8被引入,用来替代以前的UIAlertViewUIActionSheet,向用户弹出警示信息;preferredStyle参数有两个值:.actionSheet.alert,表示替代的两种样式。
  • 2 创建一个cancel样式的UIAlertActionUIAlertController的警示弹出框一般是由最上面的title+message(都不是非必须的)和一些Action组成,cancel action在最下面。
  • 3 presentUIViewController中的方法,用于展示。

添加Actions到ALert Controller中

  • Call action
let callActionHandler = { (action:UIAlertAction!) -> Void in
    let alertMessage = UIAlertController(title: "Service Unavailable", message:
"Sorry, the call feature is not available yet. Please retry later.",
preferredStyle: .alert)
    alertMessage.addAction(UIAlertAction(title: "OK", style: .default, handler:
nil))
    self.present(alertMessage, animated: true, completion: nil)
}
let callAction = UIAlertAction(title: "Call " + "123-000-\(indexPath.row)",
style: .default, handler: callActionHandler)
optionMenu.addAction(callAction)

callActionHandler是swift闭包结构的一种写法,关于闭包可查看以撸代码的形式学习Swift-7:Closure。这个代码块在Call action被点击是执行。

  • Check-in action
// Check-in action
let checkInAction = UIAlertAction(title: "Check in", style: .default, handler:
{
    (action:UIAlertAction!) -> Void in
    let cell = tableView.cellForRow(at: indexPath)
    cell?.accessoryType = .checkmark
})
optionMenu.addAction(checkInAction)

当用户点击“Check in”action时,为选中的cell增加一个对号,表明是用户喜欢的。accessoryType包括disclosureIndicator, detailDisclosureButton, checkmarkdetailButton

Call Action 和 Check-in Action

当cell被选中后,这个cell会一直灰色高亮。去掉:
tableView.deselectRow(at: indexPath, animated: false)

解决Bug

现在应用运行后,check-in某一cell时,可能会出现其他cell同时也被check-in。
这个问题是因为cell重复使用导致的。当一个屏幕滚动时,新进的cell就会利用滚出的得cell,以提高效率。解决方法:为每个cell创造一个是否被check-in的标志。

  • RestaurantTableViewController中创建一个Boolean类型的数组:
    var restaurantIsVisited = Array(repeating: false, count: 21)
  • check-in后就把对应的标志修改为true:
let checkInAction = UIAlertAction(title: "Check in", style: .default, handler:
{
    (action:UIAlertAction!) -> Void in
    let cell = tableView.cellForRow(at: indexPath)
    cell?.accessoryType = .checkmark
    self.restaurantIsVisited[indexPath.row] = true
}
  • 在每一次生成cell是也要检查是否check-in,在tableView(_:cellForRowAt:)放的return cell之前加入:
    cell.accessoryType = restaurantIsVisited[indexPath.row] ? .checkmark : .none

练习

当选中也被check-in的cell时,check-in Action的文本变成Undo Check in,点击后取消其对号。修一下check-in代码:

let cell = tableView.cellForRow(at: indexPath)
if cell?.accessoryType == .checkmark {
    let checkInAction = UIAlertAction(title: "Undo Check in", style: .default, handler:
    {
        (action:UIAlertAction!) -> Void in
        cell?.accessoryType = .none
        self.restaurantIsVisited[indexPath.row] = false
    })
    optionMenu.addAction(checkInAction)
} else {
    let checkInAction = UIAlertAction(title: "Check in", style: .default, handler:
    {
        (action:UIAlertAction!) -> Void in
        cell?.accessoryType = .checkmark
        self.restaurantIsVisited[indexPath.row] = true
    })
    optionMenu.addAction(checkInAction)
}

代码

Beginning-iOS-Programming-with-Swift

说明

此文是学习appcode网站出的一本书 《Beginning iOS 10 Programming with Swift》 的一篇记录

系列文章目录

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,651评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,468评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,931评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,218评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,234评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,198评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,084评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,926评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,341评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,563评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,731评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,430评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,036评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,676评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,829评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,743评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,629评论 2 354

推荐阅读更多精彩内容