遍历子视图及其子视图(递归和迭代遍历)

递归遍历

含义

递归遍历是指在函数的定义中使用函数自身的方法来实现遍历。在遍历视图层次结构时,一个函数会检查当前视图的子视图,然后对每个子视图递归调用自身,以继续遍历该子视图的子视图,依此类推,直到没有更多的子视图为止。

示例代码(Swift 遍历视图)

swift

scss 复制代码
func recursiveTraverseSubviews(_ view: UIView) {
    for subview in view.subviews {
        print(subview)
        recursiveTraverseSubviews(subview)
    }
}

在这个示例中,recursiveTraverseSubviews 函数遍历当前视图的所有子视图,打印每个子视图,并对每个子视图再次调用 recursiveTraverseSubviews 函数,从而实现递归遍历。

迭代遍历

含义

迭代遍历是使用循环结构(如 forwhile 等)来重复执行特定操作,从而实现遍历的目的。在遍历视图层次结构时,通常会使用一个数据结构(如栈或队列)来存储待处理的视图,然后在循环中不断从数据结构中取出视图进行处理,并将其未处理的子视图添加到数据结构中,直到数据结构为空。

示例代码(Swift 遍历视图)

swift

swift 复制代码
func iterativeTraverseSubviews(_ view: UIView) {
    var stack = [UIView]()
    stack.append(view)
    while !stack.isEmpty {
        let currentView = stack.removeLast()
        for subview in currentView.subviews {
            print(subview)
            stack.append(subview)
        }
    }
}

在这个示例中,使用一个栈 stack 来存储待处理的视图。首先将根视图添加到栈中,然后在 while 循环中,不断从栈中取出视图,打印其所有子视图,并将这些子视图添加到栈中,直到栈为空。

区别

实现方式

  • 递归:通过函数自身调用实现,代码简洁,易于理解,尤其是对于具有递归结构的问题(如树的遍历)。
  • 迭代:使用循环结构和数据结构(如栈、队列)来实现,代码相对复杂,但对于某些问题,迭代实现可能更高效。

内存使用

  • 递归:每次递归调用都会在调用栈上分配新的栈帧,当递归深度很大时,可能会导致栈溢出错误。
  • 迭代:通常只需要固定大小的额外内存(如栈或队列),不会受到递归深度的影响。

性能

  • 递归:由于函数调用的开销和栈帧的分配,递归实现的性能可能不如迭代。
  • 迭代:循环结构的执行效率通常较高,尤其是在处理大规模数据时。

可读性和可维护性

  • 递归:对于简单的递归问题,代码可读性高,易于理解和维护。但对于复杂的递归逻辑,可能会使代码难以理解。
  • 迭代:代码结构相对复杂,但对于熟悉循环和数据结构的开发者来说,也具有较好的可读性和可维护性。
js 复制代码
import UIKit

// 递归方式遍历子视图
func recursiveTraverseSubviews(_ view: UIView) {
    for subview in view.subviews {
        print("递归遍历: \(subview)")
        recursiveTraverseSubviews(subview)
    }
}

// 迭代方式遍历子视图
func iterativeTraverseSubviews(_ view: UIView) {
    var stack = [UIView]()
    stack.append(view)

    while !stack.isEmpty {
        let currentView = stack.removeLast()
        for subview in currentView.subviews {
            print("迭代遍历: \(subview)")
            stack.append(subview)
        }
    }
}

// 示例使用
let mainView = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
let subview1 = UIView(frame: CGRect(x: 10, y: 10, width: 50, height: 50))
let subview2 = UIView(frame: CGRect(x: 70, y: 10, width: 50, height: 50))
let subsubview = UIView(frame: CGRect(x: 10, y: 10, width: 20, height: 20))

subview1.addSubview(subsubview)
mainView.addSubview(subview1)
mainView.addSubview(subview2)

print("开始递归遍历")
recursiveTraverseSubviews(mainView)

print("\n开始迭代遍历")
iterativeTraverseSubviews(mainView)    
相关推荐
酒鼎16 分钟前
学习笔记(12-02)事件循环 - 实战案例 —⭐
前端·javascript
Bigger21 分钟前
第一章:我是如何剖析 Claude Code 整体架构与启动流程的
前端·aigc·claude
竹林81827 分钟前
从“连接失败”到丝滑登录:我用 ethers.js v6 搞定 MetaMask 钱包连接的全过程
前端·javascript
oi..31 分钟前
《Web 安全入门|XSS 漏洞原理、CSP 策略与 HttpOnly 防护实践》
前端·网络·测试工具·安全·web安全·xss
UXbot41 分钟前
2026年AI全链路产品开发工具对比:5款从创意到上线一站式平台深度解析
前端·ui·kotlin·软件构建·swift·原型模式
一拳不是超人1 小时前
前端工程师也要懂的服务器部署知识:从 Nginx 到 CI/CD
服务器·前端
AlkaidSTART1 小时前
TanStack Query 技术指南:异步状态管理核心实践
前端·react.js
种花家的强总1 小时前
前端项目开发/维护中降低成本的方式之一:降低耦合度
前端
Palpitate_LL1 小时前
从XSS到“RCE“的PC端利用链构建
前端·xss
qq_334466861 小时前
Edge 浏览器不要提示还原页面
前端·edge