使用 Swift 3
在我提供解决方案之前,我会指出 @Paulw11 的评论,他是 100% 正确的。正确的约定是将连接逻辑从视图控制器中提取出来。您应该在视图控制器中拥有的唯一代码是显示视图所需的代码。连接到服务器并管理结果与在视图中实际呈现结果数据无关。
如果你真的觉得有必要直接从另一个视图调用一个函数,你不应该这样做通过创建一个新的视图控制器实例。相反,您应该像这样获取现有实例:
let app = UIApplication.shared.delegate! as! AppDelegate
if let viewControllers = app.window?.rootViewController?.childViewControllers {
viewControllers.forEach { vc in
if let view = vc as? AnotherViewController {
view.downloadIt()
}
}
}
就个人而言,我建议以任何一种方式将此逻辑从视图控制器中拉出。如果您想尽量减少事情,或者如果这是您正在进行的唯一 Web 服务调用,您可以简单地执行以下操作:
添加一个带有协议和该协议扩展的新 Swift 文件:
protocol Downloadable : class { }
extension Downloadable {
func downloadStuff() -> String {
// Add your download logic here
return "downloading"
}
}
然后,在您希望能够使用此下载功能的任何视图中,只需将协议添加到您的视图控制器,如下所示:
class ViewController: UIViewController, Downloadable {}
然后你可以很容易地像这样获取你下载的数据:
@IBAction func handleDownloadTapped(_ sender: UIButton) {
let result = downloadStuff()
print(result)
}
同样,您不应该养成这样做的习惯,因为如果您使用几个不同的 api 调用,它会变得混乱。
最佳实践是创建一个包含 Web 服务内容的类,我个人喜欢 objc.io 方法。您可以在此处找到教程。
https://talk.objc.io/episodes/S01E01-networking
基本上你会创建这样的服务
public typealias JSONDict = [String: AnyObject]
struct Resource<A> {
let url: URL
let parse: (NSData) -> A?
}
let url = URL(string: "https://url")!
let myResource = Resource<[JSONDict]>(url: url) { data in
let json = try? JSONSerialization.jsonObject(with: data as Data, options: [])
return json as? [JSONDict]
}
final class Connect {
class func load<A>(resource: Resource<A>, completion: @escaping (A?) -> Void) {
URLSession.shared.dataTask(with: resource.url) { (data, _, _ ) in
if let data = data {
completion(resource.parse(data as NSData))
} else {
completion(nil)
}
}.resume()
}
}
你可以在任何你需要的地方调用它:
Connect.load(resource: myResource) { result in
// do stuff with result
}
我希望这对某人有帮助