iOSUIKit和Swift | 青训营笔记

1,164 阅读4分钟

这是我参与「第四届青训营 -iOS场」笔记创作活动的的第4篇笔记

UIKit

UIApplication

  • app入口
int main(int argc, char * argv[]) {
    NSString * appDelegateClassName;
    @autoreleasepool {
        // Setup code that might create autoreleased objects goes here.
        appDelegateClassName = NSStringFromClass([AppDelegate class]);
    }
    return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}
  • 单例模式,一个应用程序只会有一个
  • 应用实例,负责监听应用级时间
  • AppDelegate,应用级时间代理,管理应用程序的生命周期、通知事件、外部调用

在发生不同事件,调用不同的回调方法

App生命周期

  • Not Running,未运行
  • Inactive,前台非活动状态,处于前台,但是不能接受事件处理
  • Active,前台活动状态,能接受事件处理
  • Background,后台状态,如果有可执行代码就进行执行,否则挂起
  • Suspended,挂起状态,如果内存不足,会被杀死 image.png

视图

  • UIKit,提供基础视图类库
  • UIView,所有视图的根类
  1. 实际上是CALayer的封装
  2. UIView,处理布局和触摸事件;CALayer,负责绘图、动画、变化
  3. 为了职责分离,但是UIView灵活性差,需要进入CALayer层进行处理
  • UIViewController,所有视图控制器的基类,负责视图显示、界面跳转
  1. 生命周期 init -> loadView -> viweDidLoad -> viewWillAppear -> viewDidAppear -> 开始退出 -> viewWillDisappear -> viewDidDisappear -> viewWillUnload -> viewDidUnload -> dealloc
  2. init进行数据初始化,不要出现创建view
  3. loadView进行view创建和初始化
  4. viweDidLoad,附加的view和空间
  5. viewWillAppear,显示前处理,键盘弹出或特殊动画
  6. viewDidAppear,显示动画后的操作

图形几何学

  • UIView重要属性,frame,bounds,center,只是一个存取的接口,最终是改变CALayer的frame、bounds、position
  1. frame,外框的界面大小
  2. bounds,长宽
  3. center,中心
  • 锚点,图形移动的中心点/把柄
  • 坐标系,一个图层的position依赖于父图层,相对于父图层建立的直角坐标系
  • 布局,设置(x, y, height, width),放在界面上
  1. 自动布局,关心视图之间的约束,多个视图之间的相对位置
  2. masonry/snapkit
  • zPosition,前后位置,只是将绘制顺序放在最上方,实际的view层还是在下方,那么实际上触摸的还是根据add顺序,需要调用bringSubviewToFront
  • 仿射变化,利用transform属性,再二维空间做旋转、缩放、平移 image.png
  • 3D变化,使用矩阵的各个元素进行变化,增加对z轴的变化 image.png
  • 视觉效果,圆角、边框、阴影,修改layer的属性;阴影会影响子视图,边框不会
  1. cornerRadius
  2. borderWidth
  3. shadow

Swift

优势

  • nil值
  1. OC,nil代表空对象的指针
  2. swift,有optional的概念,如果是nil,不会进行任何处理
  • 类型安全
  1. OC 隐氏转换,会导致精度缺失
  2. swift 显氏转换,在类型转换时需要指出
  • 运行快

基础知识

  • 变量定义,存在类型自动推断
// 不可变
let a = 10
// 可变
var b = 20
// 数组
var names: [String] = ["Tom"]
// 字典
var classes: [String : String] = ["class" : "Tom"]
// 合集,无序set
var id: Set<String> = ["1", "2", "3"]
  • 可选值
var name: String?
  • 循环
for idx in 0..<10 {}
while(condition) {}
  • 函数
// inout 表示参数传递为引用传递,调用时传入地址
// 参数前面加 _,表示参数名可以省略
func funcName(argName: aryType, ...) -> returnType {code...}
class ClassName: FatherClass  {}
  • 类的扩展,增加方法
extension ClassName {}
  • 协议
protocol ProrocalName: NSObjectProtocal {}
// 定义变量
var name: String {get set}
// 定义函数,不用实现
func funcName(argName: aryType, ...) -> returnType
  • 协议修饰
  1. mutating,该方法可以改变协议中的变量
  2. required,实现指定初始化器,满足协议的初始化要求,子类必须要实现
  3. required & override,父类和协议有相同的构造器,且父类的构造器没有用required修饰,那么重写的子类构造器就要使用required override修饰;如果子类带final,就不需要用required,final表示不会被任何类继承,也就不会有子类是否需要继承的问题
  • 泛型
// 函数
func swap<T>(_  a: **inout** T, _ b: **inout** T) {
    let temp = a
    a = b
    b = temp
}
// 类
class ClassName<Element> {}
  • 闭包
  1. 利用上下文推断形式参数和返回值类型 {(s1: String, s2: String) -> Bool in} -> {s1, s2 in return s1 > s2}
  2. 单表达式闭包隐式返回 {arg1, arg2 in arg1 > arg2} 类似java的lmabda表达式,闭包中只有单条语句,直接写
  3. 简写实际参数名 {arg1, arg2 in arg1 > arg2} -> {0>0 > 1}
  4. 简写实际参数名 {0>0 > 1} -> ( > )
  5. 尾随闭包,作为函数参数值传递,需要写在函数参数列表外边
var block: (argType, ...) -> returnType = {arg... in
    //code...
    return ...
}
// 简写
var block: (String) -> String = {
    print($0)
    return $0 + "1232"
}
// sort
let s1 = Student(name: "Tom", score: 300)
let s2 = Student(name: "Anna", score: 100)
let s3 = Student(name: "Aana", score: 100)
var students = [s2, s1, s3]
students = students.sorted {
    if $0.score != $1.score {
        // 大于降序
        return $0.score > $1.score
    }
    // 小于升序
    return $0.name < $1.name
}

swfitUI

  • 只是一个工程形式,与storyboard是平级的
  • contentView,管理页面布局
  • PreviewProvider,声明视图预览
  • 手动设置样式

image.png

栈视图

  • 三种布局形式
// 垂直
VStack {
}
// 水平
HStack {
}
// 覆盖布局
ZStack {
}
  • 嵌套布局
VStack {
    Text("Hello, world!")
        .padding()
    HStack {
        Text("Hello, world!")
            .font(.headline)
            .foregroundColor(Color.red)
            .padding()
        Text("Hello, world!")
            .padding()
    }
}

Button

struct CaseView: View {
    @State var change = false
    var body: some View {
        VStack {
            Text(change ? "欢迎关注" : "下次再来")
                .padding()
            Button {
                // 取反change
                self.change.toggle()
            } label: {
                Text("button")
                    .padding()
            }

        }
    }
}

页面push跳转

  • 第一个页面
struct ContentView: View {
    var body: some View {
        NavigationView() {
            VStack {
                Text("Hello, world!")
                    .padding()
                HStack {
                    Text("Hello, world!")
                        .font(.headline)
                        .foregroundColor(Color.red)
                        .padding()
                    Text("Hello, world!")
                        .padding()
                }
                NavigationLink(destination: NextView()) {
                    Text("go to next")
                        .foregroundColor(.yellow)
                }
            }
            
        }
    }
}