无法使用类型为“(字符串)”的参数列表调用 <method>
Posted
技术标签:
【中文标题】无法使用类型为“(字符串)”的参数列表调用 <method>【英文标题】:Cannot invoke <method> with and argument list of type '(String)' 【发布时间】:2015-04-12 00:46:09 【问题描述】:我正在尝试编写一个 OSX 应用程序。这个应用程序的一个功能是它显示机器 IP 地址。 程序打开时获取地址(AppDelegate.swift):
@NSApplicationMain class AppDelegate: NSObject, NSApplicationDelegate
var ipadd:String = ""
var path:String = ""
var status:String = ""
func applicationDidFinishLaunching(aNotification: NSNotification)
ipadd = getIFAddress() //<-- ip stored in here as String
println(ipadd) //successfully prints out the ip
ViewController.setIpDisp(ipadd) //error on this line
...
在 ViewController.swift 中:
class ViewController: NSViewController
@IBOutlet weak var ip: NSTextField!
...
func setIpDisp(ipin: String)
ip.stringValue = ipin
确切地说,错误是“无法使用类型为'(String)'的参数列表调用'setIpDisp'
谢谢
【问题讨论】:
函数不是静态的。您需要一个实例来调用它。我认为正确的想法是发送一条消息并在您的控制器中处理该消息。 【参考方案1】:AppDelegate
正在尝试调用 ViewController
方法,该方法正在更新视图控制器视图中的 @IBOutlet
。它需要一个有效的ViewController
实例来执行此操作。
但这是倒退的:应用程序委托不应该尝试调用视图控制器方法。视图控制器可以调用应用程序委托的方法/属性,但应用程序委托确实不应该调用视图控制器方法。
如果您需要更新视图控制器中的 IP 号字段,则视图控制器应该启动此操作(例如在 viewDidLoad
中):
class ViewController: NSViewController
@IBOutlet weak var ip: NSTextField!
override func viewDidLoad()
super.viewDidLoad()
updateIpDisp()
func updateIpDisp()
let appDelegate = NSApplication.sharedApplication().delegate as! AppDelegate
ip.stringValue = appDelegate.getIFAddress()
或者,如果您愿意,AppDelegate
在其init
方法(不是applicationDidFinishLaunching
)中设置一些ipadd
字符串属性,然后updateIpDisp()
方法可以从应用程序委托中检索属性的值,也。 (鉴于 IP 编号是动态的并且可以更改,这对我来说似乎不正确,但可以随心所欲。)无论如何,这可能看起来像:
class AppDelegate: NSObject, NSApplicationDelegate
var ipadd: String!
override init()
super.init()
ipadd = getIFAddress()
和
class ViewController: NSViewController
@IBOutlet weak var ip: NSTextField!
override func viewDidLoad()
super.viewDidLoad()
updateIpDisp()
func updateIpDisp()
let appDelegate = NSApplication.sharedApplication().delegate as! AppDelegate
ip.stringValue = appDelegate.ipadd
但是视图控制器应该从应用代理请求 IP 号并更新它自己的视图。但应用委托在视图控制器中没有业务调用方法。
【讨论】:
这个实际上效果更好。使用第一种方法时,我遇到了一些包装问题。我在某处读到程序变量应该从那里存储在 AppDelegate 上。所以我会把它设置在那里,并在那里访问它。我将改用这种方式。谢谢@Rob【参考方案2】:你的函数不是静态的,所以一定要初始化它的一个实例,像这样
@NSApplicationMain class AppDelegate: NSObject, NSApplicationDelegate
let viewController = ViewController()
var ipadd:String = ""
var path:String = ""
var status:String = ""
func applicationDidFinishLaunching(aNotification: NSNotification)
ipadd = getIFAddress() //<-- ip stored in here as String
println(ipadd) //successfully prints out the ip
viewController.setIpDisp(ipadd) //error on this line
...
【讨论】:
这消除了编译时错误,但可能不是正确的解决方案。他不应该为了调用某个函数而实例化一个虚拟的ViewController
实例。此外,这可能会导致运行时错误,因为在 ViewController
中为 ip
隐式展开 @IBOutlet
可能会失败。
你有什么建议@Rob?
@Rob,我是 xcode 开发的新手。在这种情况下,我获取了我的计算机的 IP,这个动作需要在启动时恰好一次。 applicationDidFinishLaunching
为我提供了这个。我在启动时获得 IP,并告诉视图控制器显示它。除非视图控制器有自己的“启动时运行”方法,否则我不知道我还能做什么。我愿意接受建议。
@Rob 您能否解释一下为什么在这种情况下,@IBOutlet
的隐式展开可能会在运行时失败?谢谢。
@Unheilig - 因为当您从情节提要中实例化场景时,插座已连接。但是ViewController()
的手动实例化并没有使用情节提要。它只是创建一个ViewController
实例,它与任何特定的故事板场景无关。因此,出口将是nil
。因此,任何尝试使用带有隐式展开的插座(即!
)都会失败。您会收到“致命错误:在展开可选值时意外发现 nil”运行时错误。以上是关于无法使用类型为“(字符串)”的参数列表调用 <method>的主要内容,如果未能解决你的问题,请参考以下文章
IOS9 - 无法使用类型为“(字符串)”的参数列表调用“计数”
无法使用类型为“(字符串,withIntermediateDirectories:B)的参数列表调用“createDirectoryAtPath”