【问题标题】:Swift: Referencing variables in one class from another function and/or classSwift:从另一个函数和/或类中引用一个类中的变量
【发布时间】:2018-04-23 15:48:30
【问题描述】:

在 Swift 中尝试一些事情。我正在尝试理顺一些对我来说似乎很混乱的事情——主要是关于我如何处理变量并在项目中引用它们。

我要做的是保持 ViewController 中定义的变量(基于结构)从应用程序中的各种其他函数访问和更新。

所以,这里是我所拥有的代码的简要概述。实际上,我编写了一个较小的应用程序来测试我的想法,然后再将它们应用到更复杂的东西上。

我从 XCode 开始,使用 Mac OSX 的基于 Swift 文档的应用程序。

在 ViewController.swift 我有:

import Cocoa
class ViewController: NSViewController {
    var myText = "Hello, some text"

    @IBOutlet weak var textView1: NSTextField!

    @IBAction func Button1(_ sender: Any) {
        myText = "This is button 1 clicked"
        myText = setText( thisText: &myText )
        textView1.stringValue = myText
    }

    @IBAction func Button2(_ sender: Any) {
        print("Button 2")
        myText = "This is button 2 clicked"
        textView1.stringValue = myText
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.   
        textView1.stringValue = myText
    }

    override func viewDidAppear() {
        let document = self.view.window?.windowController?.document as! Document
    }

    override var representedObject: Any? {
        didSet {
        // Update the view, if already loaded.
        }
    }
}

在 SetText.swift 中,我有这个:

import Foundation

func setText( thisText: inout String) -> String {
    thisText = "Function"
    return thisText
}

我喜欢将变量发送到 Set Text 函数然后返回它的想法,但仔细考虑它让我觉得实际上这可能会像众所周知的一碗意大利面条,其中包含函数调用函数并且谁知道还有什么。所以我在想这样的事情可能更有意义:

import Foundation

func setText( thisText: inout String) {
    let vc = ViewController()
    // Read the variable from View Controller
    var myTextHere = vc.myText
    myTextHere = myTextHere + " More text"

    // Set the variable in ViewController here
    vc.myText = myTextHere
}

根据我对这个主题的阅读,如果我调用 ViewController(),它将创建一个新的视图实例(是正确的,还是我误读了?)。这已经发生了,所以我需要引用调用 setText 函数的 ViewController,或者更确切地说,它拥有那个特定的代码实例。在考虑基于文档的应用程序时,我显然希望将 myText 的所有实例与每个文档的 ViewController 一起保留。

我的目标是创建一些更复杂的东西,使用基于 Struct 的变量将所有内容组合在一起。所以:

myCard.image // holds a bitmap image
myCard.size // holds the size of the image

等等。能够以 ViewController().myCard 的形式访问它以进行读写是我认为我需要做的。

我不想做的是使用全局变量。

谢谢。

【问题讨论】:

标签: swift macos class variables


【解决方案1】:

我很难看到您的问题标题和问题正文之间存在很大关联。事实上,我什至不完全确定有人问了这个问题。也就是说,我将尝试解决您似乎在问的问题(重写了我认为它们的意图):

当你初始化一个新的视图控制器时,它会创建一个新的视图吗?

是的。每个视图控制器都有一个视图属性,它不是共享组件或单例或其他类似的东西。每个视图控制器都有一个主视图。它几乎肯定由几十个其他子视图组成,但每个视图控制器都有一个 视图。

有没有办法从外部获取有关视图控制器状态的元数据,最好以结构的形式?

当然。首先,您需要定义 Card 结构。我建议在与视图控制器本身相同的文件中执行此操作。您可以在视图控制器之外定义它,或者如果您想要更严格的耦合和命名空间,您可以在视图控制器内部进行。请注意,后者意味着类型名称在视图控制器外部引用时将是 ViewController.Card 而不仅仅是 Card

然后你想在你的视图控制器上创建一个计算属性 (var card: Card) 或一个方法 (func card() -> Card),它会根据状态构建并返回其中一个。听起来您已经倾向于属性方法。

注意:我绝对建议不要使用普通的 get/set 属性,因为这样您就必须不断更新和修改它。最好的办法是拥有一个即时构建的计算属性。因此,当调用该属性时,它会进入您的所有组件以获取您想要的信息(如图像大小、字符串等),然后打包并移交 Card 元数据结构。像这样按需执行它可以消除不必要的复杂性并将元数据逻辑整合到一个地方。

您的代码示例中的一些危险内容:

  • 我想不出实施viewDidAppear() 但不调用super.viewDidAppear() 的充分理由。除非您有非常令人信服的理由将其排除在外(老实说,我想不出一个),否则不要这样做。
  • 我看不出您第一次实施 setText(thisText:) 方法的任何充分理由。您在 Button1(_ sender: Any) IBAction 中使用它的方式在功能上完全没有任何作用。该方法通常有几个原因:它有一个大写的方法名称,通过尝试分配给 stringValue 来设置 textView 文本,出于某种非常奇怪的原因,并且在三行中完成了可以在一个中完成的操作:

    textView1.text = "This is button 1 clicked"

  • setText(thisText:) 的第二个实现比前一个更没有意义。最大的两个问题是 1)您甚至不使用传入的 thisText 参数,以及 2)您的方法,称为“设置文本”,每次获取时都会创建一个全新的视图控制器叫?这严重违反了“按照锡上所说的去做”。方法应该有一个单一的职责,并且不应该做任何超出该职责的事情。一百万年后,我永远不会看到一个名为 setText 的方法并认为“我敢打赌这会初始化一个视图控制器”。从不。

我看到这个问题已经有点被否决了(不是我),我想花点时间指导您使用 Stack Overflow:就清晰、简洁、具体的主题提出清晰、简洁、具体的问题.正如我在回答顶部所说的那样,您的帖子中似乎没有任何问题。我不得不根据您写的内容进行推断。

请记住:编码不仅仅是在您思考应用程序时摆动手指。如果您正在努力做好工程,您可能会花费大约 10:1(或更多!)的比例来盯着屏幕,以实际输入任何代码。每次写一行代码,你都应该问自己,“我为什么要写这行代码?这有必要吗?我是在重新发明轮子吗?)

祝你好运!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-07
    相关资源
    最近更新 更多