如何检查作为UDF参数的数组中的值的数量?

时间:2021-12-10 07:33:11

I am new to Swift (I learned it about a month ago) and I'm creating a custom UICollectionViewCell class, and I need three types of UIButtons and other objects as well, but I don't want to write each one out, so I am creating a function. However, since I have three buttons, the function must take exactly three arrays for each parameter. Can someone please help me with the code where I have included the comments? Thank you!

我是Swift的新手(大约一个月前我学到了它),我正在创建一个自定义的UICollectionViewCell类,我也需要三种类型的UIButtons和其他对象,但我不想写出每一个,所以我正在创建一个函数。但是,由于我有三个按钮,因此该函数必须为每个参数准确地使用三个数组。有人可以帮我提供我已包含评论的代码吗?谢谢!

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.")


        }
    }
}

3 个解决方案

#1


1  

There's a lot going on here. First off, the way you're checking if your parameters are arrays won't work:

这里有很多事情要做。首先,您检查参数是否为数组的方式不起作用:

if xOriginCgFloat != Array() {

Array() declares a new object of type Array and checks if xOriginCgFloat is equal to it. Instead, you want to check if xOriginCgFloat is of the Array type, which you can do like this:

Array()声明一个Array类型的新对象,并检查xOriginCgFloat是否等于它。相反,您要检查xOriginCgFloat是否属于Array类型,您可以这样做:

if xOriginCgFloat is Array {

But! you don't need to do this. Your function declaration specifies xOriginCgFloat: [CGFloat], which means that for the function to run, the value passed for xOriginCgFloat must be an Array of CGFloats. No need to check.

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

OK next up: when you say

接下来好吧:当你说的时候

if AnyObject.self == UIButton.self {

you probably think you're checking if the value passed for ObjectType is UIButton. But you're not. That's actually checking if the class AnyObject is the same as the class UIButton, which it isn't. So that will always return false. Instead, you can perform the check you're looking for like this:

您可能认为您正在检查ObjectType传递的值是否为UIButton。但你不是。这实际上是在检查类AnyObject是否与类UIButton相同,而不是。所以这总是会返回false。相反,您可以像这样执行您正在寻找的支票:

if objectType === UIButton.self {

this will succeed if you pass UIButton.self for objectType when you call the function, which I assume is your intention.

如果你在调用函数时为objectType传递UIButton.self,这将成功,我认为这是你的意图。

Lastly, your actual question: if you want to know how many elements your xOriginCgFloat array has, you can use xOriginCgFloat.count:

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

if xOriginCgFloat.count == 2 {

This will work, but it's not an ideal approach, as it doesn't support compile-time checking; if somewhere in your program you pass an array with the wrong number of values, the compiler can't catch it. You won't find out until the program is running, and maybe at a very bad time.

这可行,但它不是一种理想的方法,因为它不支持编译时检查;如果程序中某处传递的数组值错误,则编译器无法捕获它。在程序运行之前你不会发现,也许是在非常糟糕的时候。

Instead, if you know the number of values you're looking for, use a tuple. You can declare a function like this:

相反,如果您知道要查找的值的数量,请使用元组。你可以声明一个这样的函数:

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

And call it like this:

并称之为:

initializeStuff(xOriginCgFloat: (5.0, 6.7))

It expects a tuple with exactly two CGFloats inside, so it will show an error in the IDE if you try to call with anything else. When your function is called, you don't need to check as you're guaranteed exactly the values you wanted.

它期望一个元组内部恰好有两个CGFloats,所以如果你尝试用其他任何东西调用它会在IDE中显示错误。调用函数时,您无需检查,因为您可以确切地保证所需的值。

The downside of tuples is that you can't really iterate them with a for loop, (actually you can, but it's messy) so you have to do things manually. Since you only have two or three items in your tuple this might not be a bad approach. For example:

元组的缺点是你不能用for循环迭代它们(实际上你可以,但它很乱)所以你必须手动做事。由于你的元组中只有两个或三个项目,这可能不是一个糟糕的方法。例如:

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
}

You can read up on tuples in Apple's documentation.

您可以在Apple的文档中阅读元组。

#2


1  

To write an if that checks the amount of elements in an array simply do:

要写一个检查数组中元素数量的if,只需执行以下操作:

if array.count == 3

I don't know if I got it right, but you can do something like:

我不知道我是否做对了,但你可以这样做:

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

hope have helped

希望有所帮助

#3


1  

I'm not sure I agree with your approach to have a func to build all the objects, but I definitely wouldn't take an array of params that has to be a fixed length. You can try something like this:

我不确定我是否同意使用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)
    }
}

However, I think that unless you are doing a lot more boilerplate than what you've shown, you could just as easily get away with this. Its actually shorter, since you aren't really don't anything else that needs to be encapsulated. If you are, you should make a factory method to preconfigure the UIButton, UILabel, or UIView

但是,我认为,除非你做的事情比你所展示的要多得多,否则你可以轻松逃脱这一点。它实际上更短,因为你真的没有其他任何需要封装的东西。如果是,您应该使用工厂方法来预配置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] = [
}

#1


1  

There's a lot going on here. First off, the way you're checking if your parameters are arrays won't work:

这里有很多事情要做。首先,您检查参数是否为数组的方式不起作用:

if xOriginCgFloat != Array() {

Array() declares a new object of type Array and checks if xOriginCgFloat is equal to it. Instead, you want to check if xOriginCgFloat is of the Array type, which you can do like this:

Array()声明一个Array类型的新对象,并检查xOriginCgFloat是否等于它。相反,您要检查xOriginCgFloat是否属于Array类型,您可以这样做:

if xOriginCgFloat is Array {

But! you don't need to do this. Your function declaration specifies xOriginCgFloat: [CGFloat], which means that for the function to run, the value passed for xOriginCgFloat must be an Array of CGFloats. No need to check.

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

OK next up: when you say

接下来好吧:当你说的时候

if AnyObject.self == UIButton.self {

you probably think you're checking if the value passed for ObjectType is UIButton. But you're not. That's actually checking if the class AnyObject is the same as the class UIButton, which it isn't. So that will always return false. Instead, you can perform the check you're looking for like this:

您可能认为您正在检查ObjectType传递的值是否为UIButton。但你不是。这实际上是在检查类AnyObject是否与类UIButton相同,而不是。所以这总是会返回false。相反,您可以像这样执行您正在寻找的支票:

if objectType === UIButton.self {

this will succeed if you pass UIButton.self for objectType when you call the function, which I assume is your intention.

如果你在调用函数时为objectType传递UIButton.self,这将成功,我认为这是你的意图。

Lastly, your actual question: if you want to know how many elements your xOriginCgFloat array has, you can use xOriginCgFloat.count:

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

if xOriginCgFloat.count == 2 {

This will work, but it's not an ideal approach, as it doesn't support compile-time checking; if somewhere in your program you pass an array with the wrong number of values, the compiler can't catch it. You won't find out until the program is running, and maybe at a very bad time.

这可行,但它不是一种理想的方法,因为它不支持编译时检查;如果程序中某处传递的数组值错误,则编译器无法捕获它。在程序运行之前你不会发现,也许是在非常糟糕的时候。

Instead, if you know the number of values you're looking for, use a tuple. You can declare a function like this:

相反,如果您知道要查找的值的数量,请使用元组。你可以声明一个这样的函数:

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

And call it like this:

并称之为:

initializeStuff(xOriginCgFloat: (5.0, 6.7))

It expects a tuple with exactly two CGFloats inside, so it will show an error in the IDE if you try to call with anything else. When your function is called, you don't need to check as you're guaranteed exactly the values you wanted.

它期望一个元组内部恰好有两个CGFloats,所以如果你尝试用其他任何东西调用它会在IDE中显示错误。调用函数时,您无需检查,因为您可以确切地保证所需的值。

The downside of tuples is that you can't really iterate them with a for loop, (actually you can, but it's messy) so you have to do things manually. Since you only have two or three items in your tuple this might not be a bad approach. For example:

元组的缺点是你不能用for循环迭代它们(实际上你可以,但它很乱)所以你必须手动做事。由于你的元组中只有两个或三个项目,这可能不是一个糟糕的方法。例如:

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
}

You can read up on tuples in Apple's documentation.

您可以在Apple的文档中阅读元组。

#2


1  

To write an if that checks the amount of elements in an array simply do:

要写一个检查数组中元素数量的if,只需执行以下操作:

if array.count == 3

I don't know if I got it right, but you can do something like:

我不知道我是否做对了,但你可以这样做:

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

hope have helped

希望有所帮助

#3


1  

I'm not sure I agree with your approach to have a func to build all the objects, but I definitely wouldn't take an array of params that has to be a fixed length. You can try something like this:

我不确定我是否同意使用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)
    }
}

However, I think that unless you are doing a lot more boilerplate than what you've shown, you could just as easily get away with this. Its actually shorter, since you aren't really don't anything else that needs to be encapsulated. If you are, you should make a factory method to preconfigure the UIButton, UILabel, or UIView

但是,我认为,除非你做的事情比你所展示的要多得多,否则你可以轻松逃脱这一点。它实际上更短,因为你真的没有其他任何需要封装的东西。如果是,您应该使用工厂方法来预配置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] = [
}