当前位置:  开发笔记 > 运维 > 正文

Swift中的全局变量和可选绑定

如何解决《Swift中的全局变量和可选绑定》经验,为你挑选了1个好方法。

关于可选绑定,全局变量以及包装和展开,我有一些非常简单的疑问.由于我是SWIFT的新手,因此了解其概念的山雀和部分非常重要.

1)在Swift中,如果我声明一个全局变量,我有两个选项可以使它成为可选或非可选,所以让我有2-4个或更多的可选变量.所以可取的是绑定所有这些变量

viewDidLoad() method// so that I could use them without any problem of unwrapping and fatal error in my program.

2)让我通过以下示例让自己更清楚 - 我的项目VC1和VC2中有2个VC.VC2有一个文本字段,用户在其中输入一些值并在VC1的tabelview中显示.

在Vc1

var namevc1 = NSMutableArray?//holds the input of textfield to be passed from VC2. 

正如您所看到的,我的VC1是第一个在我的项目运行时加载的视图控制器,我使用一个可选变量来填充我的tabke vuew

'arr'

所以当应用程序第一次运行时它是空的.因此,在代码中使用其值时可能会导致致命错误.那么它的解决方案是什么解决方案呢?

viewDidLoad() 

方法或全部声明一个空的NSMutable数组类型来代替可选类型.

提前致谢.



1> dfri..:

我将首先重复上面的评论.

可能你误解了Swift中全局变量的概念.

    如果您有一个全局变量,则不必在任何视图/方法/类等之间"传递"它,因为该变量是在全局范围内定义的(可在任何地方访问).

    通常,全局变量不是一个好主意,而是您想要避免的事情.

关于全局变量和快速问题,你真的应该将单身人士纳入讨论.参见例如以下现有的SO线程:

任何不使用的理由在Swift中使用单例"变量"?

(如何创建全局变量?)

(在Swift中声明全局变量)


TableViewController和ViewController之间通过segues进行通信(准备和展开segues)

(这个答案最终变得非常可能有点过于彻底,因为我不清楚你当前的tableview/viewcontroller程序状态是什么样的.很抱歉这个冗长的答案以及它可能给读者带来的任何不便).

现在,让我们留下全局变量,并讨论一个(以及其他)可行的选项,用于示例中两个控制器之间的通信.从您的问题,我将总结您的示例如下

VC1:故事板入口点,UITableViewControllerUITableViewCells组成,在这些单元格中,您可以通过实例显示一些文本UILabel.

VC2:aUIViewController,可从VC1的单元访问,包含UITextField实例.当用户在此文本字段中输入文本时,您希望文本显示在VC2中的关联单元格中(在VC1中用于访问VC2的单元格中关联).

我们将VC1和VC2分别与(cocoa touch)类TableViewController(TableViewController.swift)和ViewController(ViewController.swift)相关联.表视图控制器中的单元格将与(cocoa touch)类TableViewCell(TableViewCell.swift)相关联.这些课程的详细信息如下.

对于这个简单的示例,请注意我们不会将VC1嵌入导航控制器(否则适用于表视图 - >视图导航).

我们将从故事板开始,为a Table View Controller和a 添加对象(从对象库中拖放)View Controller.表视图容器还将自动包含Table Viewa TableViewCell.继续在故事板中:

UILabel对象添加到TableViewCell容器中Table View Controller(根据需要对齐)

View Controller,添加一个Text Field对象和一个Button对象(根据需要对齐它们).

将入口点设置为Table View Controller.

然后按住Ctrl键拖动"显示"segue TableViewCellView Controller.

选择Showsegue,然后从Attributes检查器中输入一个标识符,例如ShowDetail.

最后,使用TableViewCell选中的(如上所述;从属性检查器),输入单元格的标识符.在这里,我们将使用简单的使用标识符TableViewCell.

我们现在暂时离开故事板并实现三个类,与之相关联Table View Controller,View Controller以及与前者相关联TableViewCell.

我们从开始Table View Controller,并实现我们的UITableViewController子类.请注意,这里,我们只使用一个数组,而不是使用一个NSMutableArray来保存UITextLabel每个单元格中的文本String.

// TableViewController.swift
Import UIKit

class TableViewController: UITableViewController {

    // Properties
    var userTextLabels = [String]()
    var numberOfCells: Int?

    override func viewDidLoad() {
        super.viewDidLoad()

        numberOfCells = loadSampleTextLabels() // Load sample labels.
    }

    func loadSampleTextLabels() -> Int {
        userTextLabels += ["Label #1", "Label #2", "Label #3"]
        return userTextLabels.count
    }

    // func numberOfSectionsInTableView(tableView: UITableView) ...
    // func tableView(tableView: UITableView, numberOfRowsInSection section: Int) ...

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cellIdentifier = ("TableViewCell")
        let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! TableViewCell

        // Text for current cell
        let cellText = userTextLabels[indexPath.row]
        cell.userSuppliedTextLabel.text = cellText

        return cell
    }

    // ... communication?
}

其中两个注释掉的方法是分别用于表中UITableViewController的多个部分(例如return 1)和单元(例如return (numberOfCells ?? 0))的任何标准方法.我会把这些修好给你.

现在,我们TableViewCell将表视图中的对象与子类的实例相关联UITableViewCell.在这里,我们将为我们的细胞使用一个非常简单的类; 每个单元格只包含一个UILabel实例(通过故事板按Ctrl-拖动,@IBOutletUILabel表格视图单元格中创建).

// TableViewCell.swift
import UIKit

class TableViewCell: UITableViewCell {

    // Properties
    @IBOutlet weak var userSuppliedTextLabel: UILabel!
        // Ctrl-drag from UILabel (in TableViewCell) in storyboard

    override func awakeFromNib() {
        super.awakeFromNib()
    }

    override func setSelected(selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
    }

}

最后,对于从表视图细胞访问的视图控制器:使用单一@IBOutletUITextField用于用户输入的文本,并使用预先存在的处理事件在此文本字段UITextFieldDelegate.例如:

//  ViewController.swift
import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

    // Properties
    @IBOutlet weak var userSuppliedText: UITextField!
        // Ctrl-drag from storyboard...
    var cellText: String?

    override func viewDidLoad() {
        super.viewDidLoad()

        userSuppliedText.text = cellText ?? "..."

        // Handle the user input in the text field through delegate callbacks
        userSuppliedText.delegate = self
    }

    // UITextFieldDelegate
    func textFieldShouldReturn(textField: UITextField) -> Bool {
        // User finished typing (hit return): hide the keyboard.
        textField.resignFirstResponder()
        return true
    }

    func textFieldDidEndEditing(textField: UITextField) {
        cellText = textField.text
    }

}

我们还在这里声明了一个字符串属性(cellText),它将充当VC1和VC2之间通信的容器.

我们回到故事板和从---身份检查---三个故事板对象(关联Table View Controller,View Controller,TableViewCell),与其相关的类,我们刚才上面写的.

我们现在几乎达到了我们的目标; 它只是指定如何在两个控制器之间进行通信.

我们将从 VC1 VC2的通信开始.在上面的评论中,通过查看prepareForSegue(...)方法,您处于正确的轨道上(无论如何,对于此特定解决方案).在类中Table View Controller,我们添加以下方法:

// ... add to TableViewController.swift
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    // Get the new view controller using segue.destinationViewController.
    // Pass the selected object to the new view controller.

    if segue.identifier == "ShowDetail" {
        let viewController = segue.destinationViewController as! ViewController
        if let selectedCell = sender as? TableViewCell {
            let indexPath = tableView.indexPathForCell(selectedCell)!
            let currentTextInCell = userTextLabels[indexPath.row]
            viewController.cellText = currentTextInCell // <-- note this
        }
    }
}

因此,对于VC1-> VC2通信,我们可以(在此示例中)带来当前占用UILabel发送方单元的任何现有文本(由String数组指定userTextLabels).查看ViewController.swift中的viewDidLoad(...)方法,了解如何从VC1传递此值并将其设置为VC2 中的默认文本.UITextField

现在,对于通信VC2-> VC1,这是您询问的具体通信方向,再次向TableViewController.swift添加另一个方法(以编程方式):

// ... add to TableViewController.swift
@IBAction func unwindToTableView(sender: UIStoryboardSegue) {
    if let sourceViewController = sender.sourceViewController as? ViewController, 
        text = sourceViewController.cellText {
            // ^ note 2nd clause of if let statement above    
        if let selectedIndexPath = tableView.indexPathForSelectedRow {
            // Update cell text
            userTextLabels[selectedIndexPath.row] = text
            tableView.reloadRowsAtIndexPaths([selectedIndexPath], withRowAnimation: .None)
        }
    }
}

在这里,我们定义一个展开动作,当触发时,它会检索cellText作为segue源的视图控制器的属性,即在我们的例子中,是实例ViewController.但是我们如何触发这一行动呢?

回到故事板和View Controller.请注意View Controller对象顶部的三个小图标,更具体地说,最右边的这些名称Exit.按住Ctrl键并拖动操作从您ButtonExit图标,然后选择unwindToTableView动作Segue.当您单击视图控制器的按钮时,视图展开(退出)并在该unwindToTableView方法中着陆TableViewController.

生成的应用程序应如下所示:

enter image description here


这比我预期的要长,但是一旦开始编写......无论如何,上面的方法当然使用没有全局变量,但是使用对future(prepareForSegue)或historical(unwindToTableView)视图的引用来获取(通常来自当前或历史视图)或通过使用这些参考(未来/历史视图)设置(通常在未来视图的当前)值.

Apple在tableviewcontroller/viewcontroller上下文中有一个关于示例应用程序的非常全面的教程,我建议将其用完.当我开始编写Swift时,我发现它非常有价值.

开始开发iOS应用程序(Swift)

推荐阅读
臭小子
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有