• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >ios > iOS开发tips-神奇的UITableView

iOS开发tips-神奇的UITableView

作者:Kenshin Cui's Blog 字体:[增加 减小] 来源:互联网 时间:2017-07-22

Kenshin Cui's Blog通过本文主要向大家介绍了ios,uitableview等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

概述

UITableView是iOS开发中使用频率最高的UI控件,在前面的文章中对于UITableView的具体用法有详细的描述,今天主要看一些UITableView开发中的常见一些坑,这些坑或许不深,但是如果开发中注意不到的话往往比较浪费时间。

神奇的section header

事情的起因是一个网友说要实现一个类似下图界面,但是不管是设置sectionHeaderHeight还是代理方法中实现func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int)都无法调整Section Header的默认高度。而且他还试过通过func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?自定义一个header也是无济于事。
Blog_iOS_tTps_UITableView_UITableViewDemo1?

其实这个问题解决起来并不复杂,只要设置sectionFooterHeight为0即可(当然对应通过代理方法也是可以的)。默认情况下分组样式UITableView的section header和section footer是由一个默认高度的,并不为0。

import UIKit

private let ProfileTableViewControllerCellReuseIdentifier = "ProfileTableViewCell"
class ProfileTableViewController: UIViewController {

    // MARK: - Nested type
    struct ProfileData {
        var title:String!
        var content:String!
    }

    // MARK: - TableView life cycle
    override func viewDidLoad() {
        super.viewDidLoad()
        self.setup()
        self.loadData()
    }

    // MARK: - Private method
    private func setup() {
        self.view.backgroundColor = UIColor.gray
        self.tableView.register(ProfileTableViewCell.self, forCellReuseIdentifier: ProfileTableViewControllerCellReuseIdentifier)
        self.tableView.dataSource = self
        self.tableView.delegate = self

        self.view.addSubview(self.tableView)
        self.tableView.snp.makeConstraints { (make) in
            make.edges.equalTo(0.0)
        }

    }

    private func loadData() {
        self.data.removeAll()

        let row1 = ProfileData(title: "Name", content: "Kenshin Cui")
        let row2 = ProfileData(title: "ID", content: "kenshincui")
        let section1 = [row1,row2]

        let row3 = ProfileData(title: "Gender", content: "Male")
        let row4 = ProfileData(title: "Region", content: "China")
        let section2 = [row3,row4]


        let row5 = ProfileData(title: "What's Up", content: "We're here to put a dent in the universe。 Otherwise why else even be here?")
        let section3 = [row5]

        self.data.append(section1)
        self.data.append(section2)
        self.data.append(section3)

        self.tableView.reloadData()
    }

    // MARK: - Private property
    private lazy var tableView:UITableView = {
        let temp = UITableView(frame: CGRect.zero, style: .grouped)
        temp.estimatedRowHeight = 50
        temp.sectionFooterHeight = 0
        return temp
    }()

    fileprivate var data = [[ProfileData]]()

}


extension ProfileTableViewController:UITableViewDataSource, UITableViewDelegate{
    // MARK: - Table view data source
    func numberOfSections(in tableView: UITableView) -> Int {
        return self.data.count
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        let sectionData = self.data[section]
        return sectionData.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if let cell = tableView.dequeueReusableCell(withIdentifier: ProfileTableViewControllerCellReuseIdentifier, for: indexPath) as? ProfileTableViewCell {
            let dataItem = self.data[indexPath.section][indexPath.row]
            cell.title = dataItem.title
            cell.content = dataItem.content
            return cell
        }
        return UITableViewCell()
    }

    // MARK: - Table view delegate
    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        if section == 0 {
            return CGFloat.leastNormalMagnitude
        }
        return 8.0
    }
}

数据源和代理方法的自动调用

同样是上面的代码,如果去掉loadData()方法后面的reloadData()调用你会发现整个界面不会有任何异常现象,数据可以照样加载,也就是说数据源方法和代理方法会正常调用加载对应的数据。这是为什么呢?
事实上类似于func numberOfSections(in tableView: UITableView) -> Int等方法并不是只有reloadData()等方法刷新的时候才会调用,而是在已经设置了dataSource和delegate后布局变化后就会调用。因此即使注释掉上面的reloadData()方法界面仍然不会有变化。
要验证这个结论可以延迟设置数据源和代理(注意:手动更新界面布局setNeedsLayout、layoutIfNeeded),或者最简单的方式就是旋转屏幕会发现func numberOfSections(in tableView: UITableView) -> Int、func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat等方法都会调用。除此之外,你也会发现func numberOfSections(in tableView: UITableView) -> Int其实并不止一次调用,系统内部为了确定整个布局本身对它就存在着调用。

分割线左侧对齐

貌似苹果的设计分割就建议你将分割线左侧留出一定的间距,但在实际开发过程中却很少见设计师会这么做。要让分割线左侧对齐对于当前iOS 10来说应该是再简单不过,只要设置UITableView的separatorInset = UIEdgeInsets.zero即可(如果仅仅想要控制器某个UITableViewCell的分割线则直接设置UITableViewCell的separatorInset,当然这种方式对于.grouped风格的UITableView而言无法修改Section顶部和底部分割线)。不过低版本的iOS就要复杂一些,例如iOS 7除了以上设置还要设置UITableViewCell的separatorInset;而iOS 8、9还要再设置UITableView的layoutMargins等。

当然,如果你希望控制右侧的间距,仍然可以调整separatorInset的right即可,不过调整top、bottom应该不会生效。

移除多余的行

不妨将上面代码修改为.plain风格的UITableView,此时会发现由于数据后面多了很多多余的空行。移除这些空行的方法也很简单,那就是设置tableFooterView = UIView()即可(如果设置view的高度为CGFloat.leastNormalMagnitude则不显示最后面的一条分割线)。当然,默认情况下style为.plain则每个section的上下均不存在分割线。

注意:.plain风格的UITableView设置sectionFooterHeight不起作用,必须通过func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat代理方法设置。

.plain下禁用section header悬停

有时候你不得不用.plain Style,因为这样一来默认Section Header就有悬停效果,但是有时候你只是想要使用.plain样式却不想显示悬停效果,这时你必须禁用这个效果。
当然可以使用很多黑科技来禁用悬停效果,但是最简单的方式应该是直接将header隐藏起来:通过设置tableViewHeader高度等同于section header的高度,然后设置tableView的contentInset让它偏移到上方,这样一来当滚动到section header悬浮时出现的位置不是0而是被隐藏起来的偏移位置。

import UIKit

private let ProfileTableViewControllerCellReuseIdentifier = "ProfileTableViewCell"
class ProfileTableViewControllerWithPlain: UIViewController {

    // MARK: - Nested type
    struct ProfileData {
        var title:String!
        var content:String!
    }

    // MARK: - TableView life cycle
    override func viewDidLoad() {
        super.viewDidLoad()
        self.setup()
        self.loadData()
    }

    // MARK: - Private method
    private func setup() {
     



 
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 代码持续更新tableview与用户滑动tableview冲突?
  • 为什么NSMutableArray继承于NSArray
  • 制作的framework项目含masonry,如何处理避免冲突
  • IOS有没有类似安卓的AccessibilityService功能
  • UITableViewCell加载多张图片导致内存异常暴增
  • iOS,我在Githubfork别人的仓库后更改了代码,可以用CocoaPods把我的仓库加入项目里吗?
  • iOS根视图切换到一个新的根视图时,该如何释放之前的根视图?
  • 关于时间戳转换为NSDate和标准格式
  • iOSAPP后台运行收到推送语音播报无效急急急!!!
  • 黑屏屏保ios横屏偶尔一半黑屏的bug是可以解决的吗

相关文章

  • 2017-06-05 iOS上传文件IOS上传视频PHAsset不支持分段上传
  • 2017-06-05 绿瘦有没有效果#ifndef没有起效果?
  • 2017-06-05 能把SecKeyRef转换成NSData或者字符串么
  • 2017-06-05 ios开发中json数据解析模型属性description冲突问题。
  • 2017-06-05 iOS开发,使用masonry布局,如何让控件动态调整布局???e
  • 2017-06-05 http与https的区别https使用自签名证书的问题
  • 2017-06-05 关于七牛视频实时转码的问题
  • 2017-06-05 无法验证应用程序iOS企业级应用无法验证
  • 2017-06-05 如何修改在编辑状态下选中cell时左侧选中图标的颜色?
  • 2017-06-05 ios7通知栏天气小程序怎么推送通知消息到通知栏

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • 中国首届撸管大赛参加首届中国iOS应用开发大赛不要太看重奖金
    • 如何利用闹钟做一个提醒功能
    • ios开发遇到的内存过大的问题
    • iOS跳转到非好友聊天界面
    • xcode81编译时,一直不动,也没有出现错误信息
    • 错错错一错再错ios访问本地php接口报错
    • 搞iOS开发很久了,却一直没有看到github等开源网站有牛逼的iOS架构,求各位大大分享下~~
    • http与https的区别https使用自签名证书的问题
    • xcodearchiveXcode中自带的崩溃数据收集怎么样设置
    • ios夜间模式

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有