快速上手iOS UIKit

UIKit是苹果官方的framework, 其中包含了各种UI组件, window和view, 事件处理, 交互, 动画, 资源管理等基础设施支持.

按照前面的介绍, 用UIKit写UI可以用storyboard(Interface Builder)和代码两种方式.

大体的思路都是添加组件后, 设置属性, 设置尺寸位置约束, 处理响应事件.

这里主要介绍用代码写的情形.

希望这篇文章, 可以帮你快速上手UIKit, 熟悉常用的组件, 完成一些简单的UI界面相关任务.

在代码中写UI的基本步骤

在代码中写UI的步骤大致是:

  • 初始化.
  • addSubview添加到当前view, 或hierarchy中的其他可达view.
  • 设置约束.

比如:

class ViewController: UIViewController {
var myLabel: UILabel! override func loadView() {
view = UIView()
view.backgroundColor = .white // 创建实例
myLabel = UILabel()
myLabel.translatesAutoresizingMaskIntoConstraints = false
myLabel.text = "Hello" // 添加到view中
view.addSubview(myLabel) // 设置约束
NSLayoutConstraint.activate([
myLabel.topAnchor.constraint(equalTo: view.layoutMarginsGuide.topAnchor),
myLabel.trailingAnchor.constraint(equalTo: view.layoutMarginsGuide.trailingAnchor),
])
}
}

这里有几点说明:

  • var** myLabel: UILabel! 组件字段这样声明有lateinit的作用, 如果不带!会报错, 说controller没有init方法.
  • 如果在代码中设置UI组件的constraints, 那么这个属性经常要设置为false: translatesAutoresizingMaskIntoConstraints = **false**. 如果组件的位置是通过frame来设置的, 则不用设置这个属性.
  • 约束有多种写法, 这里只是其中一种, 用anchor的方式.

常用组件

文字: UILabel

设置文字等属性:

myLabel = UILabel()
myLabel.translatesAutoresizingMaskIntoConstraints = false
myLabel.font = UIFont.systemFont(ofSize: 24)
myLabel.text = "Hello"
myLabel.numberOfLines = 0
myLabel.textAlignment = .right

给UILabel设置点击事件:

myLabel.isUserInteractionEnabled = true
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(userDidTapLabel(tapGestureRecognizer:)))
myLabel.addGestureRecognizer(tapGesture)

点击事件处理方法:

@objc func userDidTapLabel(tapGestureRecognizer _: UITapGestureRecognizer) {
print("label clicked!")
}

这里有#selector, 对应的userDidTapLabel方法要加上@objc. 便于OC的代码调用能找到swift的方法.

给UILabel设置点击事件和UIButton不同, 这点我们后面说继承关系的时候解释一下.

按钮: UIButton

设置文字:

submitButton = UIButton(type: .system)
submitButton.translatesAutoresizingMaskIntoConstraints = false
submitButton.titleLabel?.font = UIFont.systemFont(ofSize: 36)
submitButton.setTitle("SUBMIT", for: .normal)
submitButton.setTitleColor(.black, for: .normal)

设置点击事件:

submitButton.addTarget(self, action: #selector(submitTapped), for: .touchUpInside)

@objc func submitTapped(_ sender: UIButton) {

}

这里使用@objc的理由同上.

基本上我们在iOS代码中用到#的时候, 对应的方法都要加上@objc.

输入框: UITextField

myTextField = UITextField()
myTextField.translatesAutoresizingMaskIntoConstraints = false
myTextField.placeholder = "What's your name?"
myTextField.textAlignment = .center
myTextField.font = UIFont.systemFont(ofSize: 44)

想要禁用输入框可以这样:

myTextField.isUserInteractionEnabled = false

弹框

在app里简单的交互我们经常需要弹出一个对话框:

let alert = UIAlertController(title: "title", message: "message", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Ok", style: .default))
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))
present(alert, animated: true)

其中preferredStyle有.alert.actionSheet两种.

.alert是中心的对话框, 一般用于信息提示或者确认操作; .actionSheet是底部的bottom sheet, 一般用来在几个选项中做选择.

其他

  • view中比较常用的属性isHidden, 控制view是否需要隐藏.
  • 所有的UIView都有一个layer属性.

    设置border的宽度和颜色就在layer上设置.

    CALayer在UIView之下. 所以不知道UIColor, 只知道CGColor.

本文仅列出几个常用组件, 更多的请看官方示例.

这里可以下载

继承关系

NSObject是所有Cocoa Touch class的基类. 所有UIKit中的类都是它的子类.

这里有一个类关系的图:

我们这里不展开讲述所有了, 只解答一下前面提出的关于UILabel点击事件的问题.

这里可以看到UILabelUIButton虽然都继承了UIView, 但是UIButton的继承层次更深一些, 它还继承了了UIControl.

可以看到和UIButton平级的还有好几个子类.

Controls使用的是target-action机制, 所有的action都通过方法: addTarget(_:action:for:) 添加.

约束Constraints

当在代码中设置约束时, 有三种选择:

  • 使用layout anchors.
  • 使用NSLayoutConstraint类.
  • 使用Visual Format Language.

上面我们提到过的就是其中Layout Anchors的写法:

初级单个写法:

buttonsView.topAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
buttonsView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
buttonsView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
buttonsView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true

放进数组里批量激活写法:

NSLayoutConstraint.activate([
buttonsView.topAnchor.constraint(equalTo: view.centerYAnchor),
buttonsView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
buttonsView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
buttonsView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
])

感觉是对新手比较直观的一种写法.

其他写法文末有参考文档.

PS: 项目中更流行用 SnapKit.

区域限制

  • safeAreaLayoutGuide : 去掉圆角和刘海.
  • layoutMarginsGuide : safe area的内部再加上一些额外的margin.

Bonus

  • 友情提示: 在xcode里就可以看官方文档, 快捷键是Cmd + Shift + 0.

References

[Android开发学iOS系列] 快速上手UIKit的更多相关文章

  1. [Android开发学iOS系列] iOS写UI的几种方式

    [Android开发学iOS系列] iOS写UI的几种方式 作为一个现代化的平台, iOS的发展也经历了好几个时代. 本文讲讲iOS写UI的几种主要方式和各自的特点. iOS写UI的方式 在iOS中写 ...

  2. [Android开发学iOS系列] Auto Layout

    [Android开发学iOS系列] Auto Layout 内容: 介绍什么是Auto Layout. 基本使用方法 在代码中写约束的方法 Auto Layout的原理 尺寸和优先级 Auto Lay ...

  3. [Android开发学iOS系列] 工具篇: Xcode使用和快捷键

    [Android开发学iOS系列] 工具篇: Xcode使用和快捷键 工欲善其事必先利其器. 编辑 Cmd + N: 新建文件 Option + Cmd + N: 新建文件夹 Cmd + / : 注释 ...

  4. [Android开发学iOS系列] 语言篇: Swift vs Kotlin

    Swift vs Kotlin 这篇文章是想着帮助Android开发快速学习Swift编程语言用的. (因为这个文章的作者立场就是这样.) 我不想写一个非常长, 非常详尽的文章, 只是想写一个快速的版 ...

  5. [Android开发学iOS系列] ViewController

    iOS ViewController 写UIKit的代码, ViewController是离不开的. 本文试图讲讲它的基本知识, 不是很深入且有点杂乱, 供初级选手和跨技术栈同学参考. What is ...

  6. Android开发—智能家居系列】(二):用手机对WIFI模块进行配置

    在实际开发中,我开发的这款APP是用来连接温控器,并对温控器进行控制的.有图为证,哈哈. 上一篇文章[Android开发—智能家居系列](一):智能家居原理的文末总结中写到: 手机APP控制智能温控器 ...

  7. android开发学习笔记系列(1)-android起航

    前言 在学习安卓的过程中,我觉得非常有必要将自己所学的东西进行整理,因为每每当我知道我应该是如何去实现功能的时候,有许多细节问题我总是会遗漏,因此我也萌生了写一系列博客来描述自己学习的路线,让我的an ...

  8. 【快学SpringBoot】快速上手好用方便的Spring Cache缓存框架

    前言 缓存,在开发中是非常常用的.在高并发系统中,如果没有缓存,纯靠数据库来扛,那么数据库压力会非常大,搞不好还会出现宕机的情况.本篇文章,将会带大家学习Spring Cache缓存框架. 原创声明 ...

  9. android开发学习笔记系列(2)-android应用界面编程

    前言 本篇博客将会简要介绍andriod开发过程中的一些界面元素和编程的实现,我将大家走进安卓的XML世界,当然可能会涉及到java代码,当然本文主要是介绍XML文件的界面布局. 那么我们的XML存在 ...

随机推荐

  1. 什么是WordPress

    首先,假设您没有WordPress的经验: 我将从基础开始. 在本教程中,我将回答问题:"什么是WordPress?" 在这篇文章中,我将说明您可以在哪里获得WordPress以及 ...

  2. 在阿里云Centos7.6上面配置Mysql主从数据库(master/slave),实现读写分离

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_85 在之前的一篇文章中,阐述了如何在高并发高负载的场景下使用nginx做后台服务的负载均衡:在阿里云Centos上配置nginx+ ...

  3. Java学习 (九)基础篇 包机制&JavaDoc

    包机制 为了更好地组织类,Java提供了包机制,用于区别类名的命名空间 包语句的语法为: package pkg[.pkg2[.pkg3...]]; 一般利用公司域名倒置作为包名:com.feng.x ...

  4. Markdown 常用语法精讲

    - #### 标题 (`# 跟标题名称一定要留空格`)> > # 一级标题> ## 二级标题> ### 三级标题> #### 四级标题> ##### 五级标题> ...

  5. Ceph 块存储 创建的image 映射成块设备

    将创建的volume1映射成块设备 [root@mysql-server ceph]# rbd map rbd_pool/volume1 rbd: sysfs write failed RBD ima ...

  6. 记录Java类型推断关键字var的一种特殊用法

    关于Java的var类型推断,有一种特殊用法,如下: 没有var类型之前声明一个匿名类对象,并调用它的方法. Object obj = new Object() { public void test( ...

  7. MybatisPlus核心功能——实现CRUD增删改查操作 (包含条件构造器)

    CRUD 官方文档:https://baomidou.com/ (建议多看看官方文档,每种功能里面都有讲解)[本文章使用的mybatisplus版本为3.5.2] 条件构造器 一般都是用service ...

  8. Linux 禁止root远程登录解决办法

    linux中root用户是超级管理员,可以针对root用户暴力破解密码,这样很不安全,工作中我们一般禁止root用户直接远程登陆,开设一个或多个普通用户,只允许登陆普通用户,如果有需要用root用户, ...

  9. KingbaseES where 条件解析顺序

    概述 KingbaseES 对于where 条件的解析严格遵守"从左到右"的原则,因此,对于选择性比较强的条件,进行最先过滤是有利于性能的. 一.KingbaseES 1.条件顺序 ...

  10. KingbaseES 导入导出blob列数据

    KingbaseES兼容了oracle的blob数据类型.通常是用来保存二进制形式的大数据,也可以用来保存其他类型的数据. 下面来验证一下各种数据存储在数据库中形式. 建表 create table ...