XZ_Swift之苹果原生自动布局的使用

本文介绍自动布局的核心公式与构造函数,并通过实例演示如何使用自动布局进行界面设计,包括视图定位及大小设定。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 自动布局核心公式
    “view1.attr1 = view2.attr2 * multiplier + constant”
    核心概念:即 任何一个视图 的 属性 都可以 参照 其他视图 的 某一个属性 乘以 乘积 加上一个 常数
    relatedBy relation (等于/大于等于/小于等于)
    constant(在x轴:负数向左,正数向右;在y轴:负数向上,正数向下)
  • 自动布局构造函数
self.addConstraint(NSLayoutConstraint.init(item: 视图,
attribute: 约束属性,
relatedBy: 约束关系,
toItem: 参照视图,
attribute: 参照属性,
multiplier: 乘积,
constant: 约束数值))
  • 如果指定 宽 / 高 约束
    -参照视图设置为 nil
    -参照属性选择 .notAnAttribute
  • 自动布局类函数
self.addConstraint(NSLayoutConstraint.constraints(withVisualFormat: VFL公式,
options: [],
metrics: 约束数值字典[String: 数值],
views: 视图字典[String: 子视图]))
  • VFL 可视化格式语言
    · H 水平方向
    · V 水平方向
    · I 边界
    · [ ] 包含控件的名称字符串,对应关系在 views 字典中定义
    · ( ) 定义控件的宽/高,可以在 metrics 中指定
    提示:VFL 通常用于连续参照关系,如果遇到居中对齐,通常直接使用参照;
    居中对齐使用VFL不好表示,居中很难说怎么居中,居中使用构造函数比较合适

注意:代码的原生的自动布局,需要取消 autoresizing;
autoresizing 和 autolayout 是不能共存的,纯代码的使用 autoresizing, xib 布局使用 autolayout;先使用下列代码取消autoresizing,自动布局才会起作用。

// 取消自动布局
    for subview in subviews {
            subview.translatesAutoresizingMaskIntoConstraints = false
    }

使用原生代码实现下图布局
这里写图片描述

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        //
        setupUI()
    }

    // MARK: - 私有控件
    // 圈
    private lazy var imgIcon = UIImageView(image: UIImage.init(named: "visitordiscover_feed_image_smallicon"))
    // 主页图片
    private lazy var imgHouse = UIImageView(image: UIImage.init(named: "visitordiscover_feed_image_house"))
    // 注册按钮
    private lazy var btnRegister = UIButton(title: "注册", font: 16, normalColor: .orange, highlightedColor: .black, bgImg: "common_button_white_disable")
    // 登录按钮
    private lazy var btnLogin = UIButton(title: "登录", font: 16, normalColor: .darkGray, highlightedColor: .black, bgImg: "common_button_white_disable")
}

// MARK: - 设置页面
extension ViewController {
    func setupUI() {
        view.backgroundColor = .white
        // 1.添加到视图
        view.addSubview(imgIcon)
        view.addSubview(imgHouse)
        view.addSubview(btnRegister)
        view.addSubview(btnLogin)

        // 2.取消自动布局
        for subview in view.subviews {
            subview.translatesAutoresizingMaskIntoConstraints = false
        }

        // 3.给图片添加自动布局
        // 1>圈
        view.addConstraint(NSLayoutConstraint.init(item: imgIcon,
                                                   attribute: .centerX,
                                                   relatedBy: .equal,
                                                   toItem: view,
                                                   attribute: .centerX,
                                                   multiplier: 1,
                                                   constant: 0))
        view.addConstraint(NSLayoutConstraint.init(item: imgIcon,
                                                   attribute: .centerY,
                                                   relatedBy: .equal,
                                                   toItem: view,
                                                   attribute: .centerY,
                                                   multiplier: 1,
                                                   constant: 0))
        // 2> 主页
        view.addConstraint(NSLayoutConstraint.init(item: imgHouse,
                                                   attribute: .centerX,
                                                   relatedBy: .equal,
                                                   toItem: view,
                                                   attribute: .centerX,
                                                   multiplier: 1,
                                                   constant: 0))
        view.addConstraint(NSLayoutConstraint.init(item: imgHouse,
                                                   attribute: .centerY,
                                                   relatedBy: .equal,
                                                   toItem: view,
                                                   attribute: .centerY,
                                                   multiplier: 1,
                                                   constant: 0))
        // 3> 登录
        view.addConstraint(NSLayoutConstraint.init(item: btnRegister,
                                                   attribute: .right,
                                                   relatedBy: .equal,
                                                   toItem: view,
                                                   attribute: .centerX,
                                                   multiplier: 1,
                                                   constant: -30))
        view.addConstraint(NSLayoutConstraint.init(item: btnRegister,
                                                   attribute: .top,
                                                   relatedBy: .equal,
                                                   toItem: imgIcon,
                                                   attribute: .bottom,
                                                   multiplier: 1,
                                                   constant: 30))
        view.addConstraint(NSLayoutConstraint.init(item: btnRegister,
                                                   attribute: .width,
                                                   relatedBy: .equal,
                                                   toItem: nil,
                                                   attribute: .notAnAttribute,
                                                   multiplier: 1,
                                                   constant: 100))
        view.addConstraint(NSLayoutConstraint.init(item: btnRegister,
                                                   attribute: .height,
                                                   relatedBy: .equal,
                                                   toItem: nil,
                                                   attribute: .notAnAttribute,
                                                   multiplier: 1,
                                                   constant: 35))
        // 登录
        view.addConstraint(NSLayoutConstraint.init(item: btnLogin,
                                                   attribute: .left,
                                                   relatedBy: .equal,
                                                   toItem: view,
                                                   attribute: .centerX,
                                                   multiplier: 1,
                                                   constant: 30))
        view.addConstraint(NSLayoutConstraint.init(item: btnLogin,
                                                   attribute: .top,
                                                   relatedBy: .equal,
                                                   toItem: btnRegister,
                                                   attribute: .top,
                                                   multiplier: 1,
                                                   constant: 0))
        view.addConstraint(NSLayoutConstraint.init(item: btnLogin,
                                                   attribute: .width,
                                                   relatedBy: .equal,
                                                   toItem: btnRegister,
                                                   attribute: .width,
                                                   multiplier: 1,
                                                   constant: 0))
        view.addConstraint(NSLayoutConstraint.init(item: btnLogin,
                                                   attribute: .height,
                                                   relatedBy: .equal,
                                                   toItem: btnRegister,
                                                   attribute: .height,
                                                   multiplier: 1,
                                                   constant: 0))
    }
}

VFL布局格式代码示例

// views: 定义 VFL 中的控件名称和实际名称映射关系
// metrics: 定义 VFL 中 () 指定的常数映射关系
let views = ["imgMask": imgMask, "btnRegister": btnRegister] as [String : Any]
let metrics = ["spacing": -35]
// imgMask设置水平方向距离左边界和右边界都是0       addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[imgMask]-0-|",
options: [],
metrics: nil,
views: views))
// imgMask设置竖直方向距离上边界0、底部和btnRegister的top向下35,       addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[imgMask]-(spacing)-[btnRegister]",
options: [],
metrics: metrics,
views: views))
`xz_dec_run` 是 XZ 解压缩库中的一个关键函数,用于执行实际的解压缩操作。在某些情况下,调用 `xz_dec_run` 时可能会遇到错误,例如返回 `XZ_DATA_ERROR` 或 `XZ_BUF_ERROR`,这通常表示输入数据损坏、缓冲区不足或解压缩流程配置不当。这类问题在嵌入式系统中尤为关键,尤其是在使用 MTD(Memory Technology Device)设备时,如 NAND 或 NOR Flash 存储器,数据完整性问题可能导致解压缩失败 [^3]。 ### 常见问题与解决方法 #### 1. **输入数据损坏或不完整** 如果输入流在传输或存储过程中被损坏,`xz_dec_run` 会返回 `XZ_DATA_ERROR`。这通常发生在固件更新失败、文件系统损坏或存储介质错误的情况下。 **解决方法:** - 确保输入数据完整无损,可以通过校验和(如 CRC32)验证数据完整性。 - 在嵌入式系统中,启用 MTD 层的 ECC 校正功能,确保数据读取过程中能够自动修复位翻转问题 [^3]。 #### 2. **缓冲区大小不足** `xz_dec_run` 需要足够的输入和输出缓冲区来处理数据。如果缓冲区太小,可能导致 `XZ_BUF_ERROR`。 **解决方法:** - 确保输入缓冲区 (`in` 指针) 和输出缓冲区 (`out` 指针) 足够大,建议使用 4KB 或更大的缓冲区。 - 动态分配缓冲区以适应不同大小的数据块。 #### 3. **解压缩器未正确初始化** 调用 `xz_dec_run` 前必须正确调用 `xz_dec_init()` 初始化解压缩器。如果跳过此步骤或初始化失败,可能导致运行时错误。 **解决方法:** - 在调用 `xz_dec_run` 之前,确保 `xz_dec_init()` 成功执行。 - 检查返回值,如果初始化失败,应释放资源并返回错误码。 #### 4. **流式处理不当** `xz_dec_run` 支持流式解压缩,但如果未正确处理输入/输出指针和缓冲区状态,可能导致解压缩不完整或死循环。 **解决方法:** - 正确管理 `in_pos` 和 `out_pos` 指针,确保每次调用 `xz_dec_run` 时更新缓冲区偏移量。 - 在读取完所有输入数据后,检查是否所有输出数据都已处理完毕。 #### 5. **内存分配失败** `xz_dec_run` 可能依赖动态内存分配,如果内存不足,可能导致解压缩失败。 **解决方法:** - 使用自定义内存分配器(如 `ISzAlloc` 接口)来管理内存分配,确保在资源受限的环境中也能正常工作 [^2]。 - 在嵌入式系统中预留足够的内存用于解压缩操作。 ### 示例代码:使用 xz_dec_run 解压缩 ```c #include <stdio.h> #include <stdlib.h> #include "xz.h" #define BUF_SIZE 4096 int decompress_xz(const char *in_file, const char *out_file) { FILE *fin = fopen(in_file, "rb"); FILE *fout = fopen(out_file, "wb"); if (!fin || !fout) { return -1; } struct xz_dec *state; struct xz_buf buf; uint8_t in[BUF_SIZE]; uint8_t out[BUF_SIZE]; state = xz_dec_init(XZ_DYNALLOC, 0); if (!state) { fclose(fin); fclose(fout); return -1; } buf.in = in; buf.in_size = 0; buf.out = out; buf.out_size = BUF_SIZE; while (1) { size_t in_read = fread((void *)buf.in + buf.in_pos, 1, BUF_SIZE - buf.in_pos, fin); buf.in_size = buf.in_pos + in_read; enum xz_ret ret = xz_dec_run(state, &buf); fwrite(out, 1, buf.out_pos, fout); buf.out_pos = 0; if (ret == XZ_STREAM_END) { break; } else if (ret != XZ_OK) { xz_dec_end(state); fclose(fin); fclose(fout); return -1; } if (in_read == 0 && buf.in_pos == buf.in_size) { break; } } xz_dec_end(state); fclose(fin); fclose(fout); return 0; } ``` ### 调试建议 - 使用日志记录每次调用 `xz_dec_run` 的返回值和缓冲区状态,有助于定位问题。 - 在嵌入式设备中,可以尝试使用 `xz` 工具链在主机端验证压缩文件的完整性。 ---
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值