Swift:动态定位UI对象 - UILabels,UIImageViews

时间:2016-05-03 19:30:22

标签: ios swift

我在Swift(XCode 6.4)中编写了一个包含许多UILabel和UIImageViews的应用程序,例如:

@IBOutlet weak var image1: UIImageView!
@IBOutlet weak var image2: UIImageView!
@IBOutlet weak var image3: UIImageView!

@IBOutlet weak var label1: UILabel!
@IBOutlet weak var label2: UILabel!
@IBOutlet weak var label3: UILabel!
//many more

我希望能够通过传递参数来编写可以动态定位标签或图像视图的函数:

func setImage (num: Int) {
let imageView = "image" + String(num)
imageView.image = "myGraphicName"
}

显然这不会起作用,因为imageView常量只是一个字符串,例如" image3"。那么如何根据UI名称定位UI对象呢? ActionScript中有一些东西:

eval["nameofobject"].width = 125;

这允许字符串名称链接到对象,从而访问其方法和参数。

非常感谢您的帮助。

千瓦。

3 个答案:

答案 0 :(得分:2)

最接近你问的是Swift和Objective-C key-value observing(@rmaddy提到这一点)和Objective-C selectors。既然你说你有很多类似的视图,为什么不把它们放在一个数组中,只需要遍历数组并为每个数组做你需要的。您可以直接从故事板创建此类数组。只需在数组中选择所需的视图,然后转到Connections inspector并按住Ctrl +拖动Referencing outlet collection为视图创建一个新数组,然后按住Ctrl键并拖动其余视图在同一个数组中以同样的方式。

答案 1 :(得分:1)

如果您需要按编号定位特定项目,一种方法是设计编号方案,并使用标记而不是名称。

例如,您可以将所有UIImageView的编号从1000开始,所有UILabel从2000开始,所有UIButton从3000开始,依此类推。< / p>

使用这些标签,按如下方式重写您的功能:

func setImage (tag: Int) {
    let imageView = self.view.viewWithTag(tag) as! UIImageView
    imageView.image = UIImage(named:"myGraphicName")
}

如果要在循环中处理一组项目,可以使用@IBOutletCollection代替。制作出口集合,并将所需的UIImageView对象添加到其中。当您需要对所有UIImageView个对象执行相同的操作时,使用for-each循环遍历@IBOutletCollection中的所有项目。

答案 2 :(得分:0)

除了Cocoa KVC和其他答案中提到的标签之外,还有用于查询Objective-C运行时可见类型的实用方法,您还可以使用属于标准库的Swift reflection type Mirror在运行时查询对象的属性。

使用Swift反射方法的好处在于它适用于Swift代码中可见的Objective-C类型,但也适用于纯Swift类型(我的示例使用任意结构ABC来证明这一点。)

struct A {
    let state:String
}

struct C {}

struct B {
    let x1:A
    let y1:A
    let z2:C

    var propertyValuesOfTypeC:[C] {
        let mirror = Mirror(reflecting: self)
        return mirror.children.filter({ $0.value is C }).map({ $0.value as! C })
    }

    func propertyValues(suffix s:String, type:Any.Type) -> [Any] {
        let mirror = Mirror(reflecting: self)
        return mirror.children.filter({ $0.label!.hasSuffix(s)}).map({ $0.value as! A })
    }
}

let b = B(x1:A(state:"foo"), y1:A(state:"bar"), z2:C())

print(b.propertyValues(suffix:"1", type: A.self))
print(b.propertyValuesOfTypeC)

打印出来:

[A(state: "foo"), A(state: "bar")]
[C()]