草庐IT

Swift OSX - 委托(delegate)协议(protocol)函数返回 nil,在展开文本字段值时崩溃

coder 2023-09-10 原文

我正在使用 Swift 开发一个 OSX 应用程序,它使用一个 NSSplitView,它包含两个 View Controller :“TableViewController”和“EntryViewController”。我正在使用委托(delegate),以便在单击时将自定义 NSObject(“Entry”)从 TableViewController 传输到 SplitViewController,然后返回到 EntryViewController。

我的问题是这样的:当 EntryViewController 接收到 Entry 对象时,任何将其属性分配给文本字段值的尝试都会导致意外找到 nil 类型错误,不要介意 IBOutlets 已正确链接,并且它可以同时打印 Entry.property 文本字段字符串值(前提是它在不同的、不相关的函数中)。

我已经尝试了很多安排来解决这个问题,这就是为什么当前的配置可能有点过于复杂。直接从 Table VC 到 Entry VC 的委托(delegate)关系导致了同样的问题。

即使在调用委托(delegate)之前 View 已经加载,IBOutlets 是否有某种方式没有连接?我已经阅读了很多关于委托(delegate)的很多文章——主要是针对 iOS 的——但似乎无法找到问题的根源。我将是第一个承认我对 Swift 的掌握有点零碎的人,所以我愿意接受这样一种可能性,即我正在尝试做的只是糟糕的/hacky 编码,我应该尝试一些完全不同的东西。

感谢您的帮助!

表格 View Controller :

protocol SplitViewSelectionDelegate: class {
    func sendSelection(_ entrySelection: NSObject)
}

class TableViewController: NSViewController {

    @IBOutlet weak var searchField: NSSearchField!
    @IBOutlet var tableArrayController: NSArrayController!
    @IBOutlet weak var tableView: NSTableView!

    var sendDelegate: SplitViewSelectionDelegate?

    dynamic var dataArray = [Entry]()

// load array from .plist array of dictionaries

    func getItems(){
        let home = FileManager.default.homeDirectoryForCurrentUser
        let path = "Documents/resources.plist"
        let urlUse = home.appendingPathComponent(path)

        let referenceArray = NSArray(contentsOf: urlUse)
        dataArray = [Entry]()

        for item in referenceArray! {
            let headwordValue = (item as AnyObject).value(forKey: "headword") as! String
            let defValue = (item as AnyObject).value(forKey: "definition") as! String
            let notesValue = (item as AnyObject).value(forKey: "notes") as! String

            dataArray.append(Entry(headword: headwordValue, definition: defValue, notes: notesValue))
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        self.sendDelegate = SplitViewController()
        getItems()
        print("TVC loaded")
        // Do any additional setup after loading the view.
    }   

// send selection forward to entryviewcontroller

    @IBAction func tableViewSelection(_ sender: Any) {

        let index = tableArrayController.selectionIndex
        let array = tableArrayController.arrangedObjects as! Array<Any>
        let obj: Entry
        let arraySize = array.count
        if index <= arraySize {
            obj = array[index] as! Entry
            print(index)
            print(obj)
            sendDelegate?.sendSelection(obj)
        }
        else {
            print("index unassigned")
        }
        }

}

Split View Controller :

protocol EntryViewSelectionDelegate: class {
    func sendSecondSelection(_ entrySelection: NSObject)
}

class SplitViewController: NSSplitViewController, SplitViewSelectionDelegate {

    var delegate: EntryViewSelectionDelegate?
    @IBOutlet weak var mySplitView: NSSplitView!

    var leftPane: NSViewController?
    var contentView: NSViewController?

    var entrySelectionObject: NSObject!

    override func viewDidLoad() {

        super.viewDidLoad()

    // assign tableview and entryview as child view controllers
        let story = self.storyboard

        leftPane = story?.instantiateController(withIdentifier: "TableViewController") as! TableViewController?
        contentView = story?.instantiateController(withIdentifier: "EntryViewController") as! EntryViewController?

        self.addChildViewController(leftPane!)
        self.addChildViewController(contentView!)

        print("SVC loaded")
}

    func sendSelection(_ entrySelection: NSObject) {
        self.delegate = EntryViewController() //if this goes in viewDidLoad, then delegate is never called/assigned
        entrySelectionObject = entrySelection
        print("SVC:", entrySelectionObject!)
        let obj = entrySelectionObject!
        delegate?.sendSecondSelection(obj)
    }

}

最后,EntryViewController:

class EntryViewController: NSViewController, EntryViewSelectionDelegate {

    @IBOutlet weak var definitionField: NSTextField!
    @IBOutlet weak var notesField: NSTextField!
    @IBOutlet weak var entryField: NSTextField!

    var entryObject: Entry!

    override func viewDidLoad() {
        super.viewDidLoad()
        print("EVC loaded")
    }

    func sendSecondSelection(_ entrySelection: NSObject) {
        self.entryObject = entrySelection as! Entry
        print("EVC:", entryObject)
        print(entryObject.headword)
// The Error gets thrown here:
        entryField.stringValue = entryObject.headword
    }

}

最佳答案

您不需要委托(delegate)/协议(protocol),因为有对 EntryViewController 的引用(contentView)——顺便说一下,使用 EntryViewController() 创建的实例 不是 viewDidLoad 中的实例化实例。

只需使用contentView 引用:

func sendSelection(_ entrySelection: NSObject) {
    contentView?.sendSecondSelection(entrySelection)
}

关于Swift OSX - 委托(delegate)协议(protocol)函数返回 nil,在展开文本字段值时崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44975390/

有关Swift OSX - 委托(delegate)协议(protocol)函数返回 nil,在展开文本字段值时崩溃的更多相关文章

  1. ruby - 为什么 4.1%2 使用 Ruby 返回 0.0999999999999996?但是 4.2%2==0.2 - 2

    为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返

  2. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  3. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  4. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

    我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

  5. ruby-on-rails - Rails 中的 NoMethodError::MailersController#preview undefined method `activation_token=' for nil:NilClass - 2

    似乎无法为此找到有效的答案。我正在阅读Rails教程的第10章第10.1.2节,但似乎无法使邮件程序预览正常工作。我发现处理错误的所有答案都与教程的不同部分相关,我假设我犯的错误正盯着我的脸。我已经完成并将教程中的代码复制/粘贴到相关文件中,但到目前为止,我还看不出我输入的内容与教程中的内容有什么区别。到目前为止,建议是在函数定义中添加或删除参数user,但这并没有解决问题。触发错误的url是http://localhost:3000/rails/mailers/user_mailer/account_activation.http://localhost:3000/rails/mai

  6. ruby - 检查字符串是否包含散列中的任何键并返回它包含的键的值 - 2

    我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案

  7. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  8. ruby-on-rails - `a ||= b` 和 `a = b if a.nil 之间的区别? - 2

    我正在检查一个Rails项目。在ERubyHTML模板页面上,我看到了这样几行:我不明白为什么不这样写:在这种情况下,||=和ifnil?有什么区别? 最佳答案 在这种特殊情况下没有区别,但可能是出于习惯。每当我看到nil?被使用时,它几乎总是使用不当。在Ruby中,很少有东西在逻辑上是假的,只有文字false和nil是。这意味着像if(!x.nil?)这样的代码几乎总是更好地表示为if(x)除非期望x可能是文字false。我会将其切换为||=false,因为它具有相同的结果,但这在很大程度上取决于偏好。唯一的缺点是赋值会在每次运行

  9. ruby - Ruby 中的隐式返回值是怎么回事? - 2

    所以我开始关注ruby​​,很多东西看起来不错,但我对隐式return语句很反感。我理解默认情况下让所有内容返回self或nil但不是语句的最后一个值。对我来说,它看起来非常脆弱(尤其是)如果你正在使用一个不打算返回某些东西的方法(尤其是一个改变状态/破坏性方法的函数!),其他人可能最终依赖于一个返回对方法的目的并不重要,并且有很大的改变机会。隐式返回有什么意义?有没有办法让事情变得更简单?总是有返回以防止隐含返回被认为是好的做法吗?我是不是太担心这个了?附言当人们想要从方法中返回特定的东西时,他们是否经常使用隐式返回,这不是让你组中的其他人更容易破坏彼此的代码吗?当然,记录一切并给出

  10. ruby 语法糖 : dealing with nils - 2

    可能已经问过了,但我找不到它。这里有2个常见的情况(对我来说,在编程Rails时......)用ruby​​编写是令人沮丧的:"astring".match(/abc(.+)abc/)[1]在这种情况下,我得到一个错误,因为字符串不匹配,因此在nil上调用[]运算符。我想找到的是比以下内容更好的替代方法:temp="astring".match(/abc(.+)abc/);temp.nil??nil:temp[1]简而言之,如果不匹配,则简单地返回nil而不会出错第二种情况是这样的:var=something.very.long.and.tedious.to.writevar=some

随机推荐