此代码不是我自己的,我关注了YouTube视频linked here。
我遇到了以下代码的问题,并将其缩小到特定部分和问题。
首先,这里是代码:
import UIKit
class ViewController: UIViewController {
var activePlayer = 1 // cross
var gameState = [0,0,0,0,0,0,0,0,0]
@IBAction func action(_ sender: AnyObject)
{
if (gameState[sender.tag] == 0)
{
gameState[sender.tag] = activePlayer
if (activePlayer == 1)
{
sender.setImage(UIImage(named: "Cross.png"), for: UIControlState())
activePlayer = 2
}
else
{
sender.setImage(UIImage(named: "Nought.png"), for: UIControlState())
activePlayer = 1
}
}
}
主要问题是我不了解gameState [sender.tag]部分。当我运行程序时,第一次点击我所有的按钮什么也没做,然后点击下面的按钮放置一个cross.png。 放置第一个十字架后,单击不生成任何内容。十字架没有变化,也没有任何空白按钮变成十字架或者是否有。
在视频教程中,他指示添加" -1"在[sender.tag]的末尾,如下所示:gameState [sender.tag-1]但是,当我在程序运行时尝试单击按钮时,执行此操作会导致错误。因此我删除了那部分并且程序运行,但出现上述情况。
我对编码很新,只是在社区大学完成了C ++课程的介绍,现在学习Swift 3作为一种爱好,所以我可能会遗漏一些可以轻松解释这种情况的基本信息。
提前告诉社区,因为这种情况完全取决于我的无知,我已经尝试了解sender.tag,以及其他几天的事情,现在无济于事。我希望我能从这种情况中学习并欣赏任何信息!
答案 0 :(得分:0)
Martin R.在评论中回答了OP的问题(UIButton
标签未初始化)。我想详细说明标签,希望它会有所帮助。
iOS / OS X编程中的标记只是分配给视图的整数标识符。无论您是否使用它,完全取决于您。未设置的标签默认为零。
UIControl
及其所有子类(包括UIButton
)都使用目标操作设计模式。此模式通过向控件分配当用户与控件交互时在特定对象(目标)上调用的方法(操作)来工作。可以为控件支持的每种交互类型分配不同的操作方法(例如,可以将按钮上的触摸操作与触摸操作区分开来。)
调用操作方法时,它会接收发生交互的UIControl
实例作为其第一个参数。按照惯例,此参数称为sender
(这是有道理的,因为控件正在“发送”发生某些交互的通知)。
现在考虑一个tic-tac-toe网格中的九个UIButton
。由于所有按钮都具有相同的on-tap行为,因此让它们在视图控制器上调用相同的动作方法很方便。在OP的问题中,action方法实际上是一个名为action(_ sender:)
的函数(更好的是更具描述性的函数,例如squareTapped(_ sender: UIButton)
,但我离题了。)
如果按钮并非全部调用相同的操作方法,则必须应对upperLeftCornerTapped()
,upperMiddleTapped()
等功能的噩梦,所有这些功能都会相同事情。从设计和维护的角度来看,这非常难看。
但这引出了一个问题:由于所有按钮都调用了相同的操作方法,我们如何区分实际点击了哪个按钮?这是标签的来源。当设置按钮时,我们为每个按钮分配一个唯一的整数标识符。
由于默认情况下标签为零,因此必须使用非零标签值,以确保我们通过标签识别的视图是我们明确认为有效的视图。
既方便又实用,按钮索引从1开始并经过9.这为我们提供了一种直接将每个按钮与游戏状态变量相关联的方法。在这种情况下,tag - 1
用于获取可变gameState
数组中从零开始的索引。