简体   繁体   English

闭包的快速数组,“ Int”不是“()”的子类型

[英]Swift array of closures, 'Int' is not subtype of '()'

I have an array of closures, within a class (I'm declaring this inside a UIViewController that is a table view), and want to set actions for one of my cells based on a closure. 我在类中有一个闭包数组(我在一个UIViewController中声明它是一个表视图),并希望基于闭包为我的一个单元格设置操作。 This is my code: 这是我的代码:

        var actionItem : (Int)->Void = {
            (index: Int)->Void in
            if(self.pickedRoles[index] == "___") {
                self.pickedRoles[index] = self.roles[index];
            } else {
                self.pickedRoles[index] = "___";
            }
        }

        var roleActions : Array<(Int)->Void> = [{
                actionItem(0);
            }, {
                actionItem(1);
            }, {
                actionItem(2);
            }, {
                actionItem(3);
            }, {
                actionItem(4);
        }];

actionItem is my closure, pickedRoles is a class variable which is an array of Strings, similarly with roles . actionItem是我的闭合, pickedRoles是一个类变量这是一个字符串数组,类似地roles I want roleActions to represent what happens when a user selects a role, but at the line declaring roleActions , I get an error stating: 我希望roleActions表示用户选择角色时发生的情况,但是在声明roleActions的行中,出现了一个错误,指出:

'Int' is not a subtype of '()'

What do I do to solve this? 我该怎么解决?

Well, think about it: 好吧,考虑一下:

  • actionItem is a function that takes an Int and returns Void. actionItem是一个接受Int并返回Void的函数。

  • actionItem(0) is a call to that function, so it is a Void. actionItem(0)是对该函数的调用,因此它 Void。

  • So {actionItem(0)} is an anonymous function (a closure, as you call it) that takes Void and returns Void. 因此{actionItem(0)}是一个匿名函数(如您所说的闭包),它接受Void并返回Void。

Well, you are trying to put that into an array of (Int)->Void . 好吧,您正在尝试将其放入(Int)->Void数组中。 Clearly that's a typological mismatch: an Int input is not a Void input. 显然,这是类型上的不匹配:Int输入不是Void输入。 And that's exactly what the compiler is telling you. 这正是编译器告诉您的。

Frankly I don't see what any of this has to do with closures anyway! 坦白说,我不认为这与闭包有什么关系! Your goal, as you have agree in a comment, is: "I've got 5 buttons. I want the first button, when tapped, to toggle the first item in an array, the second button to toggle the second item in an array, and so on." 正如您在评论中所同意的那样,您的目标是:“我有5个按钮。我想点击时的第一个按钮切换数组中的第一项,第二个按钮切换数组中的第二项, 等等。”

So what I would do is: I would simply attach tags to each button - say, 100, 101, 102, 103, 104. I would give them each the same action method. 因此,我要做的是:我只需将标签附加到每个按钮上,例如100、101、102、103、104。我将为每个按钮赋予相同的操作方法。 When that method is called, we subtract 100 from the tag of the sender. 当调用该方法时,我们从发送方的标签中减去100。 Now we have the index! 现在我们有了索引! Now we toggle the value of that index of the array. 现在我们切换数组索引的值。

func doButton(sender:UIView) {
    let index = view.tag - 100
    if(self.pickedRoles[index] == "___") {
        self.pickedRoles[index] = self.roles[index];
    } else {
        self.pickedRoles[index] = "___";
    }
}

There are 2 possible ways to fix the compilation error, but I don't know which one is the correct one, depending in what you are trying to do. 有两种方法可以解决编译错误,但是我不知道哪种方法是正确的,具体取决于您要执行的操作。

The array of closures is filled in with parameterless closures: 闭包数组由无参数闭包填充:

{ Void -> Void in actionItem(0) }

So the array declaration is incorrect, the contained type should be Void -> Void - the fixed code is: 因此数组声明不正确,所包含的类型应为Void -> Void固定代码为:

var roleActions : Array<Void -> Void> = [{
        actionItem(0);
    }, {
        actionItem(1);
    }, {
        actionItem(2);
    }, {
        actionItem(3);
    }, {
        actionItem(4);
}]

Alternatively, if the type of the element contained in the array is correct, basing on your app logic, then you just have to skip the integer parameter that's passed to each closure, using _ in : 另外,如果数组中包含的元素类型正确(基于您的应用逻辑),则只需使用_ in跳过传递给每个闭包的整数参数即可:

var roleActions : Array<Int -> Void> = [{
        _ in actionItem(0);
    }, {
        _ in actionItem(1);
    }, {
        _ in actionItem(2);
    }, {
        _ in actionItem(3);
    }, {
        _ in actionItem(4);
}]

As @matt and @Antonio suggested, my initial approach was faulty, but to get the desired behavior in the end, I had to go a step further than either of their solutions. 正如@matt和@Antonio所建议的那样,我的最初方法是错误的,但是最终要获得所需的行为,我必须比他们的任何一种解决方案都更进一步。

To accomplish what @matt commented, which was my goal (to have 5 buttons where each button toggles an element in the array), I had to go with the following code: 为了完成@matt所评论的内容,这就是我的目标(要有5个按钮,每个按钮可以切换数组中的一个元素),我必须使用以下代码:

         var actionItem : ((Int)->(Void->Void)) = {
            (index: Int) in
            return {
                if(self.pickedRoles[index] == "___") {
                    self.pickedRoles[index] = self.roles[index];
                } else {
                    self.pickedRoles[index] = "___";
                }
            };
        }

        var roleActions : [Void->Void] = [actionItem(0), actionItem(1), actionItem(2), actionItem(3), actionItem(4)];

What this gives me is an array of closures, where each closure can be called with no parameters to simply toggle it's respective element in the pickedRoles array. 这给了我一个闭包数组,其中每个闭包都可以调用而无需任何参数即可简单地在pickedRoles数组中切换其各自的元素。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM