第七章:table单元格的选择和UIAlertController

第七章:table单元格的选择和UIAlertController

译者注:由于本人英语水平有限,尽可能描述出作者的本意。如有错误,及时指出。文中会省略部分技术无关的赘述

处理cell选择

到目前为止 , 我们集中于在table view中展示数据 。 我们怎么处理cell的点击呢? 这个就是我们本章要讨论的一个问题 。

我们继续打磨我们的FoodPin app 。

我们将要增进一些功能

  • 当点击cell的时候 , 弹出一个菜单显示两个选项 电话 和 我已经在附近了

  • 用户点击”我已经能够在附近”的时候 显示一个心行图标

理解 UITableViewDelegate

我们在第五章第一次构建一个简单的tableview app的时候 ,我们实现了两个协议 UITableViewDelegate 和 UITableViewDataSource 。

前面已经讨论过UITableViewDataSource 而只是仅仅提了一下UITableViewDelegate 。

如前所述 , 代理模式是IOS中非常常用的一个设计模式 。 每一个代理都表示一个具体的角色或者具体的任务保证系统简单和干净 。当一个对象要执行固定的任务 ,依赖另一个对象去处理 。 这在软件设计中叫做”关注点分离”

UITableView也应用了这个概念 。 哪两个协议用作不同的目的 。UITableViewDataSource 中的方法用来管理表数据 。 依靠代理去提供数据 。另一方面 , UITableViewDelegate处理header 、 footer 、row 选择 、cell的重新排序等等

这个代理就有些方法是用来处理row选择的 。 我们这里将会实现一些方法处理row选择 。

处理表的行选择

在实现具体方法之前 , 你也许会想 :

我们怎么知道UITableViewDelegate有哪些方法可以实现呢 ?

答案是“阅读文档” 。 你可以去官网查看 官网

作为一名IOS开发者 ,你需要经常读api文档 。 没有任何其他的书能涵盖所有的IOS SDK 。 大多数时候 ,特别是SDK有新的变化的时候 ,你需要参考API 文档 。苹果提供一个简单的方式在xcode中访问文档 。 把鼠标放在类或者协议上 按住“control-command-?” 它将会弹出一个显示这个class实现了哪些协议 。 点击UITableViewDelegate 会出新一个更深层次的文档浏览器 。在那里你可以找到所有协议中定义的方法

扫视下文档 , 你会发现下面两个用于处理row 选择的方法
• tableView(_:willSelectRowAtIndexPath:)
• tableView(_:didSelectRowAtIndexPath:)

这两个方法都是用来处理row选择的 ,不同点是 tableView(_:willSelectRowAtIndexPath:)一个指定的行被选择的时候调用 。 使用此方法组织特定区域的cell被选择 。一般情况下 ,我们使用tableView(_:didSelectRowAtIndexPath:) 方法处理row选择时间,当用户选择后调用

代码中管理行选择

OK ,上面已经解释的够多了 , 我们开始coding

在xcode中,打开RestaurantTableViewController.swift ,添加下面方法

override func tableView(tableView: UITableView,didSelectRowAtIndexPath indexPath:
NSIndexPath) {
    // Create an option menu as an action sheet
    let optionMenu = UIAlertController(title: nil,message: "What do you want to do?",preferredStyle: .ActionSheet)
    // Add actions to the menu
    let cancelAction = UIAlertAction(title: "Cancel",style: .Cancel,handler: nil)
    optionMenu.addAction(cancelAction)
    // display the menu
    self.presentViewController(optionMenu,animated: true,completion: nil)
}

上面的代码使用UIAlertController 创建了一个选择菜单 。当我们点击没行的时候 , 都会弹出一个sheet 展示”What do you want to do” 信息 和一个cancel 按钮 。运行app ,自己试试选择cell

更多关于UIAlertController

再继续研究之前 , 我们需要更多的了解一下UIAlertController 。我们前面已经用过它了,但是并没有深入的讨论 。UIAlertController是在iOS 8 引入用来替代UIAlertView 和 UIActionSheet 的 。用来显示弹出框的 。

参照上面的代码片段 , 我们可以指定UIAlertController的preferredStyle 。 可以设置为“.ActionSheet” 或者 “.Alert”.

下图显示出两种弹出框的风格 。

此外,给用户显示信息的同时还可以连接一些动作(Actions) 提供一个用户交互的方式 。为了那么做 ,你需要创建一个UIAlertAction对象 (起一个你喜欢的标题 , 风格) 。代码块去处理这个动作执行的操作 。在上面的代码片段中 ,我们创建了一个取消动作 。我们这里并没有处理任何事情,所以handler设置位nil 。创建好动作后可以使用addAction将动作和UIAlertController连接起来 。

当这个UIAlertController配置好了以后,你就可以简单的使用presentViewController方法来展示这个弹出框了。

这就是使用UIAlertController的方法 。最为一个新手 ,我应该有一些问题:

  • 我怎么知道在创建UIAlertController时需要给preferredStyle提供哪些可用的value

  • 为啥不写成UIAlertControllerStyle.ActionSheet?
    两个都是好问题 。

一个问题 ,答案还是“参考文档” 。在xcode中 ,你可以将鼠标放在preferredStyle上然后按control-command-? ,xcode将会展示方法声明 你可以点击UIAlertControllerStyle深入查看UIAlertControllerStyle的API ,你会发现UIAlertControllerStyle是一个枚举 ,有两个值ActionSheet 和 Alert.

所以你可以这样创建一个UIAlertController

let optionMenu = UIAlertController(title: nil,message: "What do you want to do?",preferredStyle: UIAlertControllerStyle.ActionSheet)

上面的代码没有一点错 。swift帮我们让我们写更少的代码 ,preferredStyle参数已经知道是UIAlertControllerStyle 类型 ,所以UIAlertControllerStyle可以省略

let optionMenu = UIAlertController(title: nil,preferredStyle: .ActionSheet)

为Alert Controller 添加动作

现在我们为Alert Controller再添加连个动作 :

  • Call

  • I’ve been here

tableView(_:didSelectRowAtIndexPath:)方法添加以下代码添加到Cancel动作后面:

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.presentViewController(alertMessage,animated: true,completion: nil)
    }
    let callAction = UIAlertAction(title: "Call " + "123-000-\(indexPath.row)",style:
    UIAlertActionStyle.Default,handler: callActionHandler)
    optionMenu.addAction(callAction)

这部分代码对你来说比较生疏的部分就是callActionHandler 。当创建一个UIAlertAction对象的时候我们可以指定一个闭包 ,闭包代码用户选择row的时候调用 。这里只是弹出一个显示电话功能不能用。

闭包是一个自我包含有一定功能代码块 。可以在代码中传递 。跟Objective - C 中的block非常类似 。如上面代码所示 , 提供闭包参数的一种方式是声明一个闭包常量或者变量 。第一部分使传入的参数 ,in关键字说明参数和返回值类型已经完成 ,主体将要开始 。下图说明了闭包的语法

UIAlertAction的title是假的电话号码,是用123-000-和行号产生的 。swift允许开发之使用两种方式连接字符串

"Call " + "123-000-\(indexPath.row)"

在call action后面添加下面的代码

let isVisitedAction = UIAlertAction(title: "I've been here",style: .Default,handler: {
(action:UIAlertAction!) -> Void in
let cell = tableView.cellForRowAtIndexPath(indexPath)
cell?.accessoryType = .checkmark
})
optionMenu.addAction(isVisitedAction)

上面的代码展示了另一种使用闭包的方式 。你可以把闭包当一个内嵌的参数去使用 。这种方式也是最常用的一种比较清晰和可读 。

Swift中的可选类型(Optionals)

你可能会疑惑那个问号是干啥用得 ?cell在swift中被声明为一个可选类型 。可选类型是swift中心引入的一个类型 。一个可选类型简单的意味着”有值” 或者 “没有值 ” . cell是通过tableView.cellForRowAtIndexPath方法得到的。有可能没有值。这里使用?表示如果有值就执行它的方法 ,如果没有值就不执行

一个用户选择“I’ve been here” , 我们添加一个对选择的cell添加一个checkmark标记 。 对一个table view cell , 右边的部分是为一些小附件保留的 。有四种内建的附件包括

disclosure indicator,detail disclosure
button,checkmark and detail.

第一行代码使用indexPath来检索正在使用的cell 。第二行更新了accessoryType属性checkmark

运行app ,应该如下图

现在 ,当你选择一行,那行会高亮成灰色保持那样。将下面代码添加tableView(_:didSelectRowAtIndexPath:) 方法后面 去取消选择一行

tableView.deselectRowAtIndexPath(indexPath,animated: false)

我们有一个Bug

app 看起来不错 ,如果你详细的看 ,然而 app中有一个bug 。你mark“Cafe Deadend”。然后滚动下去,你会发现另一个餐馆被mark了 。什么情况 ?

这个问题是根重用cell相关, UITableview 有30行需要展示 ,我们也许只创建了10个cells 然后重用他们 。在这种情况下 ,UITableview使用第一个cell去显示其他餐馆的信息 ,在我们的代码中 ,我们只是去改变了imagview 和 labels 。病名有该表accessory view 。所以后面重用的会带着前面的checkmark

那么我们怎么解决这个bug呢 ?

我们需要找个方法记住这些checked元素 。我们这里创建了一个数组 。

var restaurantIsVisited = [Bool](count: 21,repeatedValue: false)

上面代码的意思和下面的一样

var restaurantIsVisited = [false,false,false]

首先我们在餐馆被check的时候贯标array对应的值 。

let isVisitedAction = UIAlertAction(title: "I've been here",handler: {
    (action:UIAlertAction!) -> Void in
    let cell = tableView.cellForRowAtIndexPath(indexPath)
    cell?.accessoryType = .checkmark
    self.restaurantIsVisited[indexPath.row] = true
    })

添加一行代码

然后在tableView(_:cellForRowAtIndexPath:) 方法的return前添加如下代码

if restaurantIsVisited[indexPath.row] {
    cell?.accessoryType = .checkmark
} else {
    cell?.accessoryType = .None
}

这里我们检查了餐馆是否被checked 。

现在运行app 。bug已经解决

其实这里还可以用三元运算符

cell?.accessoryType = restaurantIsVisited[indexPath.row] ? .checkmark : .None

你的作业

目前app还不能取消check 。想想怎么去实现 。你还可以不用系统的对勾 , 用一个心形的图片之类的表示mark。

总结

在此刻,你应该对责备他不过创建一个table view有个固定的了解 ,自定义table view cells 和处理row选择 ,你可以尝试做表视图的简单app , 比如展示一些景点或者你喜欢的别的东西 。反正就是多写 。不要怕犯错 , 犯错解决问题才能更快的成长 。

下一章将继续探索tableview。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


软件简介:蓝湖辅助工具,减少移动端开发中控件属性的复制和粘贴.待开发的功能:1.支持自动生成约束2.开发设置页面3.做一个浏览器插件,支持不需要下载整个工程,可即时操作当前蓝湖浏览页面4.支持Flutter语言模板生成5.支持更多平台,如Sketch等6.支持用户自定义语言模板
现实生活中,我们听到的声音都是时间连续的,我们称为这种信号叫模拟信号。模拟信号需要进行数字化以后才能在计算机中使用。目前我们在计算机上进行音频播放都需要依赖于音频文件。那么音频文件如何生成的呢?音频文件的生成过程是将声音信息采样、量化和编码产生的数字信号的过程,我们人耳所能听到的声音频率范围为(20Hz~20KHz),因此音频文件格式的最大带宽是20KHZ。根据奈奎斯特的理论,音频文件的采样率一般在40~50KHZ之间。奈奎斯特采样定律,又称香农采样定律。...............
前言最近在B站上看到一个漂亮的仙女姐姐跳舞视频,循环看了亿遍又亿遍,久久不能离开!看着小仙紫姐姐的蹦迪视频,除了一键三连还能做什么?突发奇想,能不能把舞蹈视频转成代码舞呢?说干就干,今天就手把手教大家如何把跳舞视频转成代码舞,跟着仙女姐姐一起蹦起来~视频来源:【紫颜】见过仙女蹦迪吗 【千盏】一、核心功能设计总体来说,我们需要分为以下几步完成:从B站上把小姐姐的视频下载下来对视频进行截取GIF,把截取的GIF通过ASCII Animator进行ASCII字符转换把转换的字符gif根据每
【Android App】实战项目之仿抖音的短视频分享App(附源码和演示视频 超详细必看)
前言这一篇博客应该是我花时间最多的一次了,从2022年1月底至2022年4月底。我已经将这篇博客的内容写为论文,上传至arxiv:https://arxiv.org/pdf/2204.10160.pdf欢迎大家指出我论文中的问题,特别是语法与用词问题在github上,我也上传了完整的项目:https://github.com/Whiffe/Custom-ava-dataset_Custom-Spatio-Temporally-Action-Video-Dataset关于自定义ava数据集,也是后台
因为我既对接过session、cookie,也对接过JWT,今年因为工作需要也对接了gtoken的2个版本,对这方面的理解还算深入。尤其是看到官方文档评论区又小伙伴表示看不懂,所以做了这期视频内容出来:视频在这里:本期内容对应B站的开源视频因为涉及的知识点比较多,视频内容比较长。如果你觉得看视频浪费时间,可以直接阅读源码:goframe v2版本集成gtokengoframe v1版本集成gtokengoframe v2版本集成jwtgoframe v2版本session登录官方调用示例文档jwt和sess
【Android App】实战项目之仿微信的私信和群聊App(附源码和演示视频 超详细必看)
用Android Studio的VideoView组件实现简单的本地视频播放器。本文将讲解如何使用Android视频播放器VideoView组件来播放本地视频和网络视频,实现起来还是比较简单的。VideoView组件的作用与ImageView类似,只是ImageView用于显示图片,VideoView用于播放视频。...
采用MATLAB对正弦信号,语音信号进行生成、采样和内插恢复,利用MATLAB工具箱对混杂噪声的音频信号进行滤波
随着移动互联网、云端存储等技术的快速发展,包含丰富信息的音频数据呈现几何级速率增长。这些海量数据在为人工分析带来困难的同时,也为音频认知、创新学习研究提供了数据基础。在本节中,我们通过构建生成模型来生成音频序列文件,从而进一步加深对序列数据处理问题的了解。
基于yolov5+deepsort+slowfast算法的视频实时行为检测。1. yolov5实现目标检测,确定目标坐标 2. deepsort实现目标跟踪,持续标注目标坐标 3. slowfast实现动作识别,并给出置信率 4. 用框持续框住目标,并将动作类别以及置信度显示在框上
数字电子钟设计本文主要完成数字电子钟的以下功能1、计时功能(24小时)2、秒表功能(一个按键实现开始暂停,另一个按键实现清零功能)3、闹钟功能(设置闹钟以及到时响10秒)4、校时功能5、其他功能(清零、加速、星期、八位数码管显示等)前排提示:前面几篇文章介绍过的内容就不详细介绍了,可以看我专栏的前几篇文章。PS.工程文件放在最后面总体设计本次设计主要是在前一篇文章 数字电子钟基本功能的实现 的基础上改编而成的,主要结构不变,分频器将50MHz分为较低的频率备用;dig_select
1.进入官网下载OBS stdioOpen Broadcaster Software | OBS (obsproject.com)2.下载一个插件,拓展OBS的虚拟摄像头功能链接:OBS 虚拟摄像头插件.zip_免费高速下载|百度网盘-分享无限制 (baidu.com)提取码:6656--来自百度网盘超级会员V1的分享**注意**该插件必须下载但OBS的根目录(应该是自动匹配了的)3.打开OBS,选中虚拟摄像头选择启用在底部添加一段视频录制选择下面,进行录制.
Meta公司在9月29日首次推出一款人工智能系统模型:Make-A-Video,可以从给定的文字提示生成短视频。基于**文本到图像生成技术的最新进展**,该技术旨在实现文本到视频的生成,可以仅用几个单词或几行文本生成异想天开、独一无二的视频,将无限的想象力带入生活
音频信号叠加噪声及滤波一、前言二、信号分析及加噪三、滤波去噪四、总结一、前言之前一直对硬件上的内容比较关注,但是可能是因为硬件方面的东西可能真的是比较杂,而且需要渗透的东西太多了,所以学习进展比较缓慢。因为也很少有单纯的硬件学习研究,总是会伴随着各种理论需要硬件做支撑,所以还是想要慢慢接触理论学习。但是之前总找不到切入点,不知道从哪里开始,就一直拖着。最近稍微接触了一点信号处理,就用这个当作切入点,开始接触理论学习。二、信号分析及加噪信号处理选用了matlab做工具,选了一个最简单的语音信号处理方
腾讯云 TRTC 实时音视频服务体验,从认识 TRTC 到 TRTC 的开发实践,Demo 演示& IM 服务搭建。
音乐音频分类技术能够基于音乐内容为音乐添加类别标签,在音乐资源的高效组织、检索和推荐等相关方面的研究和应用具有重要意义。传统的音乐分类方法大量使用了人工设计的声学特征,特征的设计需要音乐领域的知识,不同分类任务的特征往往并不通用。深度学习的出现给更好地解决音乐分类问题提供了新的思路,本文对基于深度学习的音乐音频分类方法进行了研究。首先将音乐的音频信号转换成声谱作为统一表示,避免了手工选取特征存在的问题,然后基于一维卷积构建了一种音乐分类模型。
C++知识精讲16 | 井字棋游戏(配资源+视频)【赋源码,双人对战】
本文主要讲解如何在Java中,使用FFmpeg进行视频的帧读取,并最终合并成Gif动态图。
在本篇博文中,我们谈及了 Swift 中 some、any 关键字以及主关联类型(primary associated types)的前世今生,并由浅及深用简明的示例向大家讲解了它们之间的奥秘玄机。