Swift中的全局变量和可选绑定 [英] Global variable and optional binding in Swift

查看:84
本文介绍了Swift中的全局变量和可选绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对可选绑定,全局变量&包装和开卷.由于我是SWIFT的新手,因此了解山雀和山雀非常重要.他们的概念.

I have some quite simple doubt regarding optional binding,global variable & wrapping and unwrapping . Since I am new to SWIFT, its very important to understand the tits & bits of their concepts.

1)在Swift中,如果我声明一个全局变量,我有2个选项可以将其设置为可选或非可选,因此让我拥有2-4个或更多可选变量.因此,建议将

1) In Swift if I declare a global variable, I have 2 options either to make it optional or non optional, so let I am having 2-4 or more optional variables . So is it advisable to optional bind all those variables in

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

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

2) Let me make myself more clear by the following example- I have 2 VC in my project VC1 & VC2 . VC2 has a text field in which user enters some value and displays it in a tabelview in VC1.

在Vc1中

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

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

As you can see, my VC1 is the first view controller that loads when my project runs and I am using an optional variable to populate my tabke vuew that is

'arr'

因此,当应用程序首次运行时,它为empty.因此,在代码中使用其值时,可能会导致致命错误.那么,是否将其取消绑定在

So when the app runs for the first time its empty . So it might cause a fatal error while using its value in the code. So what is its solution whether to unbind it in the

viewDidLoad() 

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

method or in all total declare an empty NSMutable array type in place of optional type .

谢谢.

推荐答案

我将从上面重复我的评论开始.

I'll start by repeating the my comment from above.

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

Possibly you've misunderstanding the concept of global variables in Swift.

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

  1. If you have a global variable, you won't have to "pass" it between any views/methods/classes etc, because the variable is defined at global scope (accessible everywhere).

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

Generally global variables is not a good idea, and something that you want to avoid.

关于全局变量和快速问题,您确实应该在讨论中加入单例.参见例如以下现有的SO线程:

Regarding the matter of global variables and swift, you really should include singletons into the discussion. See e.g. the following existing SO thread(s):

(在Swift中声明全局变量)

TableseController和ViewController之间通过Segues(为& Unwind Segues做准备)之间的通信

(此答案最终可能非常彻底,因为我不详细了解您当前的tableview/viewcontroller程序状态如何.抱歉,冗长的答案以及可能给您带来的不便给读者看).

现在,让我们留下全局变量,并在您的示例中讨论两个控制器之间进行通信的一个可行的选择.从您的问题中,我将总结您的示例,如下所示:

Now, lets leave global variables and discuss one (among other) viable options for the communication between the two controllers in your example. From your question, I'll summarize your example as follows

  • VC1 :情节提要入口点,一个由UITableViewCell组成的UITableViewController,在这些单元格中,您可以通过以下方式显示一些文本,例如UILabel.
  • VC2 :一个UIViewController,可从VC1的单元中访问,其中包含一个UITextField实例.当用户在此文本字段中输入文本时,您希望将文本显示在VC2中的关联单元格中(在某种意义上,该关联是访问VC2的是VC1中的单元格.)/li>
  • VC1: storyboard entry point, a UITableViewController consisting of UITableViewCells, where, in these cells, you display some text, say, via instances of UILabel.
  • VC2: a UIViewController, accessible from the cells of VC1, containing an UITextField instance. When user enters text into this text field, your want the text to be displayed in the associated cell in VC2 (associated in the sense that it was the cell in VC1 that was used to access VC2).

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

We'll associate VC1 and VC2 with (cocoa touch) classes TableViewController (TableViewController.swift) and ViewController (ViewController.swift), respectively. The cells in the table view controller will be associated with (cocoa touch) class TableViewCell (TableViewCell.swift). Details for these classes follow below.

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

For this simple example, note that we will not embed VC1 into a navigation controller (which is otherwise appropriate for table view -> view navigation).

我们将从情节提要开始,为Table View ControllerView Controller添加对象(从对象库中拖放).表格视图容器还将自动在其Table View中包含一个TableViewCell.在情节提要中继续:

We'll start in the storyboard, adding objects (drag-and-drop from object library) for a Table View Controller and a View Controller. The table view container will also, automatically, contain, in its Table View, a TableViewCell. Continuing in the storyboard:

  • UILabel对象添加到Table View Controller中的TableViewCell容器中(根据需要对齐)
  • View Controller中,添加一个Text Field对象和一个Button对象(根据需要对齐它们).
  • 将入口点设置为Table View Controller.
  • 此后,按住Ctrl并将显示"序列从TableViewCell拖动到View Controller.
  • 选择Show segue,然后从属性"检查器中为其输入一个标识符,例如 ShowDetail .
  • 最后,选择TableViewCell(如上所述;从属性检查器中),输入单元格的标识符.在这里,我们将仅使用标识符 TableViewCell .
  • Add a UILabel object to the TableViewCell container in the Table View Controller (align it as you wish)
  • In the View Controller, add a Text Field object and a Button object (align them as you wish).
  • Set the entry point to the Table View Controller.
  • Thereafter Ctrl-drag a 'Show' segue from the TableViewCell to the View Controller.
  • Select the Show segue and, from the Attributes inspector, enter an identifier for it, say, ShowDetail.
  • Finally, with the TableViewCell selected, (as above; from the attribute inspector), enter an identifier for the cell. Here, we'll use simply use identifier TableViewCell.

我们现在暂时离开情节提要,并实现三个与Table View ControllerView Controller和前者的TableViewCell相关的类.

We now leave the storyboard for now and implement three classes, associated with the Table View Controller, the View Controller and the formers' TableViewCell.

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

We start with the Table View Controller, and implement our UITableViewController sub-class. Note that here, instead of using an NSMutableArray to hold the texts of the UITextLabel in each cell, we'll simply use a String array.

// 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)).我将把这些修复给您.

Where the two commented out methods are standard methods used in any UITableViewController, for number of sections (e.g. return 1) and cells (e.g. return (numberOfCells ?? 0)) in the table, respectively. I'll leave fixing these to you.

现在,我们将表视图中的TableViewCell对象与子类的实例关联到UITableViewCell.在这里,我们将为单元格使用一个非常简单的类.每个单元格仅包含一个UILabel实例(通过情节提要板Ctrl-拖动从表视图单元格中的UILabel作为@IBOutlet创建).

Now, we associate the TableViewCell object(s) in the table view with instances of a subclass to UITableViewCell. Here, we'll use a very simple class for our cells; each cell just containing a single UILabel instance (created via storyboard Ctrl-drag as an @IBOutlet from the UILabel in the table view cells).

// 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)
    }

}

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

Finally, for the view controller that is accessed from the table view cells: use a single @IBOutlet to the UITextField used for user text input, and handle events in this text field using the pre-existing UITextFieldDelegate. E.g.:

//  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之间通信的容器.

We've also declared a string property (cellText) here, that will as act as container for communication between VC1 and VC2.

我们返回情节提要,并-从身份检查器中--将三个情节提要对象(Table View ControllerView ControllerTableViewCell)与我们上面刚刚编写的关联类相关联.

We return to the storyboard and---from the Identity inspector---associate the three storyboard objects (Table View Controller, View Controller, TableViewCell) with their associated classes that we've just written above.

我们现在几乎要实现目标了;仅需指定两个控制器之间的通信方式.

We're now almost at our goal; it only remains to specify how to communicate between the two controllers.

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

We'll begin with communication from VC1 to VC2. In your comment above, you were on the right track (for this specific solution, anyway) by looking at the prepareForSegue(...) method. In the class for the Table View Controller, we add the following method:

// ... 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中将其设置为默认文本.

Hence, for VC1->VC2 communication, we can (in this example) bring whatever existing text that is currently occupying the UILabel in the sender cell (as is specified by the String array userTextLabels). Look at the viewDidLoad(...) method in the ViewController.swift to see how this value is passed from VC1 and set as default text in the UITextField in VC2.

现在,对于您要询问的特定通信方向VC2-> VC1,再次(以编程方式)向 TableViewController.swift 添加另一种方法:

Now, for communication VC2->VC1, which was the specific communication direction you were asking about, add another method (programmatically), again to 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的实例.但是,我们如何触发此动作?

Here, we define an unwind action that, when triggered, retrieves the cellText property of the view controller that was the source of the segue, i.e., in our case, the instance of ViewController. But how do we trigger this action?

返回情节提要和View Controller.请注意View Controller对象顶部的三个小图标,更具体地说,是它们中最右边的三个名为Exit的图标.按住Ctrl并将动作从Button拖动到Exit图标,然后选择unwindToTableView动作选择.当您单击视图控制器的按钮时,视图将展开(退出)并降落到TableViewController中的unwindToTableView方法.

Return to the storyboard and the View Controller. Note the three little icons in the top of the View Controller object, more specifically, the right-most of these, named Exit. Ctrl-drag an action from your Button to the Exit icon, and select the unwindToTableView Action Segue. When you click your button the view controller, the view unwind (exit) and land at the unwindToTableView method in the TableViewController.

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

The resulting app should look something like this:

这比我预期的要长,但是一旦您开始编写...无论如何,以上方法自然不使用全局变量,而是使用对future(prepareForSegue)或历史(prepareForSegue c59>)通过使用这些引用(到未来/历史视图)来获取(通常从当前或历史视图获取)或设置(通常从当前的未来视图获取)值.

This was way longer than I had expected, but once you get started writing... Anyway, the method above uses, naturally, no global variables, but make use of references to future (prepareForSegue) or historic (unwindToTableView) views to get (generally from current or historic view) or set (generally in current of future view) values by using these references (to future/historic view).

Apple在tableviewcontroller/viewcontroller上下文中的示例应用程序上有自己的非常详尽的教程,我建议复习一下.当我开始编写Swift时,我发现它非常有价值.

Apple has their own very thorough tutorial on an example app in the tableviewcontroller/viewcontroller context that I would recommend going over. I found it very valuable myself when I started coding Swift.

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

这篇关于Swift中的全局变量和可选绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆