如何在视图控制器之外以编程方式创建视图
How to create view programmatically outside a view controller
目前我正在尝试创建一个将由管理器调用的 UIProgressView class:
func addProgressBar() {
let rect = CGRect(x: 10, y: 70, width: 250, height: 0)
let progressView = UIProgressView(frame: rect)
progressView.progress = 0.0
progressView.tintColor = UIColor.blue
self.view.addSubview(progressView)
}
出现的问题是:
self.view.addSubview(progressView)
因为函数不在 viewController 中,我得到错误:
Value of type 'NetworkHelper' has no member 'view'
知道如何在 viewcontroller 之外添加 progressView 吗?
好吧,你必须有一个视图来放置它。要么你抓住顶部 viewcontroller 并将它放在上面,要么你调用你的 NetworkHelper class 并传递一个它应该的视图把进度条放在.
我用这个方法抢顶viewcontroller
func topViewController() -> UIViewController? {
guard var topVC = UIApplication.shared.keyWindow?.rootViewController else { return nil }
while let presentedViewController = topVC.presentedViewController {
topVC = presentedViewController
}
return topVC
}
您可以获得最顶层的视图控制器,并将子视图添加到它的视图中属性。
iPhone -- How to find topmost view controller
您可以使用 "callbacks",或者使用委托设计模式
或Swift的闭包(Objective-C块)
您可以从函数中 return 一个 "closure",这个闭包会创建进度。用于 view/viewController
func addProgressBar() -> (UIView) -> () {
return { view in
let rect = CGRect(x: 10, y: 70, width: 250, height: 0)
let progressView = UIProgressView(frame: rect)
progressView.progress = 0.0
progressView.tintColor = UIColor.blue
view.addSubview(progressView)
}
}
然后使用这个 return 值,例如在视图控制器中:
(networkHelper.addProgressBar())(self.view)
如果你想在视图控制器上制作进度视图,并在那里管理它。
class NetworkHelper {
...
func doAnythingWithNetwork(withProgress: @escaping (NSProgress) -> (),
completion: @escaping (Data?, Error?) -> ()) {
...
// When you get any progress (like in Alamofire for example).
// Pass it to the callback
withProgress(progress)
...
}
}
然后在你的 viewController:
let networker = NetworkHelper()
...
@IBAction func buttonClicked(_ sender: Any?) {
networker.doAnythingWithNetwork(withProgress: { [weak self] progress in
// You can use your viewController here (note: use 'self?', not
// 'self', here self is "weak", only to avoid memory leaks).
// Note: Any update of the view must be in DispatchQueue.main
}, completion: { [weak self] data, error in
// Your usual completion handler.
})
}
但推荐的解决方案是使您的 NetworkHelper
只是一个模型,仅用于处理网络请求和数据。 SOLID 原则有一个 "Single Responsibility Principle",即设计每个对象只有一个责任。
视图(或 viewcontroller)应处理 addProgressBar
,NetworkHelper 应通过委托或 closure/block 将此进度传递给视图所在的 viewcontroller已更新。
好吧,您可能自己猜到了,您需要一个 view
,然后将 progressBar
放入其中。我认为 addProgressBar
方法的调用者应该知道它最适合的地方,所以我建议使用 progressBar
和 UIViewController
类型的参数,这将是目标它负责进行网络调用,因此是将进度条放入的目标:
func addProgressBar(targetViewController: UIViewController) {
// moreover, are you sure here that the height of the progressBar should be 0?
let rect = CGRect(x: 10, y: 70, width: 250, height: 0)
let progressView = UIProgressView(frame: rect)
progressView.progress = 0.0
progressView.tintColor = UIColor.blue
targetViewController.view.addSubview(progressView)
}
目前我正在尝试创建一个将由管理器调用的 UIProgressView class:
func addProgressBar() {
let rect = CGRect(x: 10, y: 70, width: 250, height: 0)
let progressView = UIProgressView(frame: rect)
progressView.progress = 0.0
progressView.tintColor = UIColor.blue
self.view.addSubview(progressView)
}
出现的问题是:
self.view.addSubview(progressView)
因为函数不在 viewController 中,我得到错误:
Value of type 'NetworkHelper' has no member 'view'
知道如何在 viewcontroller 之外添加 progressView 吗?
好吧,你必须有一个视图来放置它。要么你抓住顶部 viewcontroller 并将它放在上面,要么你调用你的 NetworkHelper class 并传递一个它应该的视图把进度条放在.
我用这个方法抢顶viewcontroller
func topViewController() -> UIViewController? {
guard var topVC = UIApplication.shared.keyWindow?.rootViewController else { return nil }
while let presentedViewController = topVC.presentedViewController {
topVC = presentedViewController
}
return topVC
}
您可以获得最顶层的视图控制器,并将子视图添加到它的视图中属性。
iPhone -- How to find topmost view controller
您可以使用 "callbacks",或者使用委托设计模式
或Swift的闭包(Objective-C块)
您可以从函数中 return 一个 "closure",这个闭包会创建进度。用于 view/viewController
func addProgressBar() -> (UIView) -> () {
return { view in
let rect = CGRect(x: 10, y: 70, width: 250, height: 0)
let progressView = UIProgressView(frame: rect)
progressView.progress = 0.0
progressView.tintColor = UIColor.blue
view.addSubview(progressView)
}
}
然后使用这个 return 值,例如在视图控制器中:
(networkHelper.addProgressBar())(self.view)
如果你想在视图控制器上制作进度视图,并在那里管理它。
class NetworkHelper {
...
func doAnythingWithNetwork(withProgress: @escaping (NSProgress) -> (),
completion: @escaping (Data?, Error?) -> ()) {
...
// When you get any progress (like in Alamofire for example).
// Pass it to the callback
withProgress(progress)
...
}
}
然后在你的 viewController:
let networker = NetworkHelper()
...
@IBAction func buttonClicked(_ sender: Any?) {
networker.doAnythingWithNetwork(withProgress: { [weak self] progress in
// You can use your viewController here (note: use 'self?', not
// 'self', here self is "weak", only to avoid memory leaks).
// Note: Any update of the view must be in DispatchQueue.main
}, completion: { [weak self] data, error in
// Your usual completion handler.
})
}
但推荐的解决方案是使您的 NetworkHelper
只是一个模型,仅用于处理网络请求和数据。 SOLID 原则有一个 "Single Responsibility Principle",即设计每个对象只有一个责任。
视图(或 viewcontroller)应处理 addProgressBar
,NetworkHelper 应通过委托或 closure/block 将此进度传递给视图所在的 viewcontroller已更新。
好吧,您可能自己猜到了,您需要一个 view
,然后将 progressBar
放入其中。我认为 addProgressBar
方法的调用者应该知道它最适合的地方,所以我建议使用 progressBar
和 UIViewController
类型的参数,这将是目标它负责进行网络调用,因此是将进度条放入的目标:
func addProgressBar(targetViewController: UIViewController) {
// moreover, are you sure here that the height of the progressBar should be 0?
let rect = CGRect(x: 10, y: 70, width: 250, height: 0)
let progressView = UIProgressView(frame: rect)
progressView.progress = 0.0
progressView.tintColor = UIColor.blue
targetViewController.view.addSubview(progressView)
}