for 循环 (Swift) 中的 onClick 事件不起作用

onClick event in a for loop (Swift) not working

使用 segue 在两个视图控制器之间共享数据在 for 循环中不起作用。我正在使用 Xcode9 和 Swift

swift4

ViewController.swift

import UIKit
import SwiftyJSON
import Alamofire

class ViewController: UIViewController {

var distnames = [String]()
var distcodes = [String]()
var data1: [AnyObject] = []
var values = [String]()
var values1 = [String]()
var current_arr :[String] = []
var ofcnames = " ";
var ofccodes = " ";
var code = " ";

var testtext = "";
var id = "";
var tiTle = "";
var releaseYear = "";

@IBOutlet weak var Verticalstackview: UIStackView!
@IBOutlet weak var scrollview: UIScrollView!
@IBOutlet weak var testlabel: UILabel!
@IBOutlet weak var mainView: UIView!

override func viewDidLoad() {
    super.viewDidLoad()
    print("code is \(code)")
    self.values = [String]()
    self.values1 = [String]()
    self.ofcnames = "";
    self.ofccodes = "";

    Alamofire.request("https://facebook.github.io/react-native/movies.json")

        .responseJSON { (response) in
            if ((response.result.value) != nil) {
                let jsondata = JSON(response.result.value!)
                // print(jsondata)
                if let da = jsondata["movies"].arrayObject
                {
                    self.data1 = da as [AnyObject]
                    print("resp is \(da) ")

                }

                    print("respcode count is    \(self.data1.count) ")
                    self.Verticalstackview.height(constant: 40)
                    self.mainView.height(constant: CGFloat(40 * self.data1.count))
                    self.scrollview.height(constant: CGFloat(40 * self.data1.count))

                    for distics in self.data1 {
                    if let resp = distics as? NSDictionary {

                        self.id = resp["id"] as! String
                        self.tiTle = resp["title"] as! String
                        self.releaseYear = resp["releaseYear"] as! String

                        let stackView =  UIStackView()
                        stackView.height(constant: 40)
                        stackView.distribution = .fill
                        stackView.alignment = .fill
                        stackView.axis = .horizontal
                        stackView.spacing = 5

                        let lblId = UILabel()
                        lblId .text = "\(self.id)"
                        lblId .font = UIFont(name: "verdana", size: 15.0)
                        lblId .textAlignment = .center
                        lblId .textColor = .gray
                        lblId .numberOfLines = 0
                        lblId .width(constant: 55)

                        let lbltiTle   = UILabel()
                        lbltiTle.text = "\(self.tiTle)"
                        lbltiTle.font = UIFont(name: "verdana", size: 15.0)
                        lbltiTle.textAlignment = .left
                        lbltiTle.textColor = .black
                        lbltiTle.numberOfLines = 0
                        lbltiTle.width(constant: 120)
                        let tap = UITapGestureRecognizer.init(target:self,action: #selector(self.tapFunction) )
                        lbltiTle.isUserInteractionEnabled = true
                        lbltiTle.addGestureRecognizer(tap)
                        self.testtext = lbltiTle.text!

                        let lblRYear = UILabel()
                        lblRYear.text = "\(self.releaseYear)"
                        lblRYear.font = UIFont(name: "verdana", size: 15.0)
                        lblRYear.textAlignment = .right
                        lblRYear.textColor = .black
                        lblRYear.numberOfLines = 0
                        lblRYear.width(constant: 100)

                        stackView.addArrangedSubview(lblId )
                        stackView.addArrangedSubview(lbltiTle)
                        stackView.addArrangedSubview(lblRYear)


                        self.Verticalstackview.addArrangedSubview(stackView)

                    }
                }
            }
            print(self.values1)
    }
}
override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}
@objc func tapFunction(sender:UITapGestureRecognizer) {
    print("tap working")
    self.performSegue(withIdentifier: "Segue", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    let secondcntroller = segue.destination as! SecondViewController
    secondcntroller.mystring = self.testtext
}
}
 extension UIView{
func height(constant : CGFloat){
    setConstraint(value: constant,attribute: .height)
}
func width(constant : CGFloat){
    setConstraint(value: constant,attribute: .width)
}
private func removeConstraint(attribute: NSLayoutAttribute){
    constraints.forEach {
        if [=11=].firstAttribute == attribute
        {
            removeConstraint([=11=])
        }
    }
}
private func setConstraint(value:CGFloat ,attribute: NSLayoutAttribute){
    removeConstraint(attribute: attribute)
    let Constraint =
        NSLayoutConstraint(item: self,
                           attribute: attribute,
                           relatedBy: NSLayoutRelation.equal,
                           toItem: nil,
                           attribute: NSLayoutAttribute.notAnAttribute,
                           multiplier: 1,
                           constant: value)
    self.addConstraint(Constraint)
}

}

第二ViewController.swift

import UIKit

class SecondViewController: UIViewController {
@IBOutlet weak var label: UILabel!

var mystring = String()
override func viewDidLoad() {
    super.viewDidLoad()
    label.text=mystring
}
}

当我单击电影名称文本时,我希望使用 segue 将其显示在第二个视图中。 https://i.stack.imgur.com/dvm8j.png 但它始终显示最后一部电影的名称。请帮我解决这个问题。
https://i.stack.imgur.com/UqyqM.png

ViewController 中的 self.testtext 属性 设置不正确。每次调用 tapFunction() 时都应设置它。 我建议您以任何方式使用 UITabiewViewController 和一个数据源数组,该数组应包含要显示的所有元素。

您应该更新您的 tapFunction

@objc func tapFunction(sender:UITapGestureRecognizer) {
    let touchedLabel = sender.view as! UILabel
    self.testtext = touchedLabel.text
    self.performSegue(withIdentifier: "Segue", sender: self)
}

希望对您有所帮助

编辑

现在你要传递多个值,你可以做的是:

首先将 for in 循环从

更改为
for distics in self.data1 {

for (index, distics) in self.data1.enumerated() {

现在,将标签设置为该行下方的标签

lbltiTle.addGestureRecognizer(tap)
// Add tag to your label
lbltiTle.tag = index
//**TIP: You should name the variables in camelCase format**

现在修改你的函数,它检测标签上的点击并获取带有索引的对象,该对象以标签的形式与标签一起传递。修改为.

@objc func tapFunction(sender:UITapGestureRecognizer) {
    let touchedLabel = sender.view as! UILabel
    let touchedIndex = touchedLabel.tag
    let selectedDict: NSDictionary = self.data1[touchedIndex]
    print("selectedDict:\(selectedDict)")
    self.performSegue(withIdentifier: "Segue", sender: self)
}

您可以从中打印所需的值。

注意:对于纯 swift 方法,您应该避免使用 NSDictionary,最好使用 [String: Any] 这是一个键值对。

希望对您有所帮助

问题

那是因为您将 testtext 作为参数传递给下一个 ViewController.mystringtesttext 每次在循环中都被更改,最后一次更改是在最后一个元素上。因此你需要保存一个索引来知道你按下的位置。

解决方案

更改您的 for 循环以获取您正在迭代的元素的索引,如上

for index in 0..<self.data1.count {
    let distics = self.data1[index]
        // Other lines of code
        lbltiTle.tag = index
}

如下更改您的处理程序

@objc func tapFunction(sender:UITapGestureRecognizer) {
    print("tap working")
    guard let index = sender.view?.tag,
        let title = (self.data1[index] as? NSDictionary)["title"] else { return }

    testtext = title
    self.performSegue(withIdentifier: "Segue", sender: self)
}

为您的标签再添加一项功能。

lbltiTle.target(forAction: onClickLabel, withSender:)

定义 -

func onClickLabel(sender: UILabel) {
     self.testtext = sender.text
}

在你的 tap 函数中调用它