2017-08-03 61 views
1

我是新来的Swift(我在一个月前了解它),我创建了一个自定义的UICollectionViewCell类,并且我还需要三种类型的UIButtons和其他对象,但我不想写每一个,所以我正在创建一个函数。但是,由于我有三个按钮,函数必须为每个参数准确地使用三个数组。有人可以帮我解释一下包含评论的代码吗?谢谢!如何检查作为UDF参数的数组中的值的数量?

var buttonArray: [UIButton] = [] 
var checkBoxArray: [UIView] = [] 
var labelArray: [UILabel] = [] 

func initializeStuff(objectType: AnyObject, xOriginCgFloat: [CGFloat], yOriginCgFloat: [CGFloat], width: [CGFloat], height: [CGFloat]) { 

    if xOriginCgFloat != Array() || yOriginCgFloat != Array() || width != Array() || height != Array() { 
     fatalError("Each CgFloat parameter must be an array.") 
    } else { 
     if AnyObject.self == UIButton.self { 
      if condition { //condition: each array must contain exactly three values 
       for index in 0..<3 { 
        var button = UIButton(frame: CGRect.init(origin: CGPoint.init(x: xOriginCgFloat[index], y: yOriginCgFloat[index]), size: CGSize.init(width: width[index], height: height[index]))) 

        buttonArray.append(button) 
       } 
      } else { 
       fatalError("Each array for a button object must have exactly three values.") 
      } 

     } else if AnyObject.self == UIView.self { 
      if condition2 { //condition2: each array must contain exactly two values 
       for index in 0..<2 { 
        var checkBox = UIView(frame: CGRect.init(origin: CGPoint.init(x: xOriginCgFloat[index], y: yOriginCgFloat[index]), size: CGSize.init(width: width[index], height: height[index]))) 

        checkBoxArray.append(checkBox) 
       } 
      } else { 
       fatalError("Each array for a view object must have exactly two values.") 
      } 

     } else if AnyObject.self == UILabel.self { 
      if condition3 { //condition3: each array must contain exactly two values 
       for index in 0..<2 { 
        var label = UILabel(frame: CGRect.init(origin: CGPoint.init(x: xOriginCgFloat[index], y: yOriginCgFloat[index]), size: CGSize.init(width: width[index], height: height[index]))) 

        labelArray.append(label) 
       } 
      } else { 
       fatalError("Each array for a view object must have exactly two values.") 
      } 

     } else { 
      fatalError("Incorrect type of object; AnyObject parameter must be a UIButton, UIView, or UILabel.") 


     } 
    } 
} 

回答

1

有很多怎么回事。

if xOriginCgFloat != Array() { 

Array()声明Array类型和检查的新对象,如果xOriginCgFloat等于它:首先,如果你的参数数组就无法工作,你正在检查的方式。相反,你要检查xOriginCgFloat是Array类型,你可以这样做的:

if xOriginCgFloat is Array { 

但是!你不需要这样做。您的函数声明指定xOriginCgFloat: [CGFloat],这意味着要运行该函数,传递的值为xOriginCgFloat必须为ArrayCGFloat s。无需检查。

OK下一步:当你说

if AnyObject.self == UIButton.self { 

你可能认为你检查是否通过了ObjectTypeUIButton。但你不是。这实际上是检查类AnyObject是否与UIButton类相同,但不是。所以这总是会返回错误。相反,你可以执行你在寻找这样的检查:

if objectType === UIButton.self { 

如果传递UIButton.selfobjectType当你调用该函数,我以为是你的意图,这将取得成功。

最后,您的实际问题:如果你想知道你xOriginCgFloat数组有多少个元素了,你可以使用xOriginCgFloat.count

if xOriginCgFloat.count == 2 { 

这是可行的,但它不是一个理想的方法,因为它不” t支持编译时检查;如果你的程序中的某个地方传递了一个数值错误的数组,编译器就无法捕捉它。直到程序运行,你才会发现,也许在一个非常糟糕的时间。相反,如果您知道要查找的值的数量,请使用元组。你可以声明这样的函数:

func initializeStuff(xOriginCgFloat: (CGFloat, CGFloat)) { 

,并调用它是这样的:

initializeStuff(xOriginCgFloat: (5.0, 6.7)) 

该公司预计正好用两个CGFloats里面一个元组,所以它会在IDE中显示一个错误,如果你尝试与其他任何东西打电话。当你的函数被调用时,你不需要检查你所保证的值。

元组的缺点是你不能真正用for循环迭代它们(实际上you can,但它很混乱),所以你必须手动完成。因为你的元组中只有两个或三个元素,所以这可能不是一个坏的方法。例如:

let xOriginCgFloat:(CGFloat, CGFloat) = (4, 6) 
var floats = [CGFloat]() 
floats.append(xOriginCgFloat.0) 
floats.append(xOriginCgFloat.1) 
for float in floats { 
    // process xOriginCgFloat member here 
} 

您可以在Apple's documentation的元组中阅读。

+0

当你说'if objectType == UIButton.self {'应该将等号运算符改为身份运算符(===),因为Xcode给我一个错误信息==。另外,因为我想为UIButton调用三个值,并且有两个值UIView和UILabel,有没有办法让一个元组具有不同数量的值? – ProgrammingEnthusiast

+0

如何在我的'for'循环中得到元组中三个值中的一个?我也发布了另一个问题。 – ProgrammingEnthusiast

+0

@ProgrammingEnthusiast是:'AnyObject'不是'Equatable',所以我应该使用'==='比较身份而不是'=='。对于那个很抱歉。另外,使用for循环遍历一个元组并不是真的支持。这是可能的,但很混乱。所以如果你想使用for循环方法,那么元组可能不是一个很好的解决方案,你应该坚持使用数组。对不起,不好的建议。 – Robert

1

要写如果检查数组中的元素的量简单地做:

if array.count == 3 

我不知道我这样做是正确的,但你可以这样做:

if buttonArray.count == 3{ 
    //do something 
} 

希望帮助

1

我不知道我用你的方法同意有FUNC建立所有的对象,但我绝对不会采用一系列必须是固定长度的参数。你可以尝试这样的事情:

var buttonArray: [UIButton] = [] 
var checkBoxArray: [UIView] = [] 
var labelArray: [UILabel] = [] 

struct ObjectDefinition { 
    let classType: UIView.Type 
    let frame: CGRect 
} 

func createAllTheStuff() { 
    let objectDefinitions: [ObjectDefinition] = [ 
     ObjectDefinition(classType: UIButton.self, frame: CGRect(x: 0, y: 0, width: 100, height: 200)), 
     ObjectDefinition(classType: UIButton.self, frame: CGRect(x: 10, y: 10, width: 10, height: 25)), 
     ObjectDefinition(classType: UIView.self, frame: CGRect(x: 0, y: 0, width: 50, height: 210)), 
     ObjectDefinition(classType: UILabel.self, frame: CGRect(x: 0, y: 0, width: 1200, height: 20)) 
    ] 

    for objectDefinition in objectDefinitions { 
     initializeStuff(objectType: objectDefinition.classType, frame: objectDefinition.frame) 
    } 
} 


func initializeStuff(objectType: UIView.self, frame: CGRect) { 
    switch objectType { 
    case UIButton.self: 
     let button = UIButton(frame: frame) 
     buttonArray.append(button) 
    case UILabel.self: 
     let label = UILabel(frame: frame) 
     labelArray.append(label) 
    case UIView.self: 
     let checkBox = UIView(frame: frame) 
     checkBoxArray.append(checkBox) 
    } 
} 

但是,我认为,除非你是做了很多的样板比你出什么,你可以很容易地摆脱这一点。它实际上更短,因为你不是什么都不需要封装。如果你是,你应该做一个工厂方法来预配置的UIButton,的UILabel,或UIView的

var buttonArray: [UIButton] = [] 
var checkBoxArray: [UIView] = [] 
var labelArray: [UILabel] = [] 


func createAllTheStuff() { 
    let button1 = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 200)) 
    buttonArray.append(button1) 
    let button2 = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 200)) 
    buttonArray.append(button2) 
    ... etc ... 
    let objectDefinitions: [ObjectDefinition] = [ 
} 
+0

你是什么意思的“样板?”这个函数是我较大的自定义UICollectionViewCell类的一部分。我将调用该函数三次(初始化我的所有UIButton,UIView,UILabel)。然后,我将只配置我的自定义类的确切布局和约束条件。 – ProgrammingEnthusiast

+0

@ProgrammingEnthusiast - 我的意思是如果你在你的UIButton,UIView或UILabel实例上设置了大量的参数。例如,在设置插图,字体,标签文本等的按钮上,然后您不希望为每个按钮调用所有这些方法,并且您希望使用工厂方法。 – dmorrow