Swift中如何创建UIBezierPath数组?求Swift数组特性讲解
理解Swift数组并创建10×10 UIBezierPath网格
嘿,我完全懂你现在的困惑——从Objective-C转Swift数组确实会有点摸不着头脑,毕竟两者的语法和底层特性差别不小。我来一步步给你拆解,帮你搞清楚怎么创建那个10×10的UIBezierPath网格,顺便把Swift数组的关键特性讲明白~
先搞懂Swift数组和OC数组的核心区别
咱们先对比你熟悉的OC,把Swift数组的关键特性理清楚:
- 类型安全:Swift数组是强类型的,你声明
[UIBezierPath]就只能放UIBezierPath实例,不能混其他类型(OC的NSArray默认可以放任意对象,除非用泛型限制)。 - 值类型 vs 引用类型:Swift的
Array是值类型,而OC的NSArray是引用类型。这意味着当你把Swift数组赋值给另一个变量时,会复制整个数组(不过数组里的引用类型元素,复制的是引用,但数组本身是独立的);OC里赋值NSArray只是传递引用,两个变量指向同一个数组。 - 可变/不可变的声明方式:Swift里用
var声明可变数组,let声明不可变数组;OC是靠NSMutableArray和NSArray区分的。 - 初始化的坑(重点!):OC里你可以用
initWithCapacity:预分配空间,但Swift的Array(repeating:count:)如果用来初始化引用类型(比如UIBezierPath),会让所有元素指向同一个实例,这是很多新手踩的坑!
创建10×10 UIBezierPath网格的正确姿势
因为UIBezierPath是类(引用类型),所以我们不能直接用Array(repeating:)来创建10×10的数组——那样所有路径都会是同一个对象,修改一个就会影响所有。正确的做法是逐个创建独立的实例,用嵌套循环或者嵌套map实现:
方法1:嵌套循环(直观易懂)
// 初始化一个空的二维数组,明确类型是[[UIBezierPath]] var bezierGrid: [[UIBezierPath]] = [] // 循环创建10行 for _ in 0..<10 { // 初始化当前行的空数组 var currentRow: [UIBezierPath] = [] // 每行创建10个独立的UIBezierPath for _ in 0..<10 { let path = UIBezierPath() // 这里可以添加你的路径绘制逻辑,比如画一个小正方形 path.move(to: CGPoint(x: 0, y: 0)) path.addLine(to: CGPoint(x: 20, y: 0)) path.addLine(to: CGPoint(x: 20, y: 20)) path.addLine(to: CGPoint(x: 0, y: 20)) path.close() currentRow.append(path) } // 把当前行加入二维数组 bezierGrid.append(currentRow) }
方法2:嵌套map(更简洁的Swift风格)
如果你熟悉Swift的高阶函数,可以用map来简化代码,逻辑和循环是一样的:
// 外层map创建10行,内层map每行创建10个独立路径 let bezierGrid = (0..<10).map { _ in (0..<10).map { _ in let path = UIBezierPath() // 同样添加你的路径绘制代码 path.move(to: .zero) path.addLine(to: CGPoint(x: 20, y: 0)) path.addLine(to: CGPoint(x: 20, y: 20)) path.addLine(to: CGPoint(x: 0, y: 20)) path.close() return path } }
为什么不能直接用Array(repeating:)?
举个反例,如果你这么写:
// 错误写法!所有UIBezierPath都是同一个实例 let badGrid = Array(repeating: Array(repeating: UIBezierPath(), count: 10), count: 10)
因为UIBezierPath是引用类型,repeating: UIBezierPath()只会创建一个实例,然后把这个实例的引用复制100次。这时候你修改任意一个path,其他99个都会跟着变,完全不是你想要的10×10独立网格。
访问网格里的路径
创建好之后,你可以通过下标访问任意位置的路径,比如获取第3行第5列的路径(注意Swift下标从0开始):
let path = bezierGrid[2][4] // 对这个path进行操作,不会影响其他路径 path.lineWidth = 2 path.stroke()
内容的提问来源于stack exchange,提问作者Andrew Savage
相关产品推荐
相关产品推荐

