在扩展中移动函数时出错 "Value of type 'UIViewController' has no member..."

error "Value of type 'UIViewController' has no member..." when moving a func inside extension

我需要移动一个方法来在扩展中添加和删除日志视图,以便将它提供给每个控制器。为此,我在原始方法中添加了一个 inout UIVew 参数,我在其中为视图使用了一个全局变量。不,我有这个错误

Value of type 'UIViewController' has no member 'containerForLoading'

self.containerForLoading 中删除自己会给出错误:

Escaping closure captures 'inout' parameter 'containerForLoading'

在动画闭包内(见评论) 是整个过程都错了还是我在最后一步迷路了?

extension UIViewController {
        
    func showLoadingView(containerForLoading: inout UIView, uponView: UIView) {
        
           containerForLoading = UIView(frame: uponView.bounds)
           uponView.addSubview(containerForLoading)
           
           containerForLoading.backgroundColor = .white
           containerForLoading.alpha = 0
           UIView.animate(withDuration: 0.24) { self.containerForLoading.alpha = 0.8 } //here the error
           let activivityIndicator = UIActivityIndicatorView()
           containerForLoading.addSubview(activivityIndicator)
           
           activivityIndicator.translatesAutoresizingMaskIntoConstraints = false
           
           
           NSLayoutConstraint.activate([
               
               activivityIndicator.centerYAnchor.constraint(equalTo: uponView.centerYAnchor),
               activivityIndicator.centerXAnchor.constraint(equalTo: uponView.centerXAnchor)
               
           ])
           
           activivityIndicator.startAnimating()
       }
       
    func removeLoading(containerForLoading: inout UiView, uponView: UIView) {
           
           containerForLoading.removeFromSuperview()
           
       }
    
}

这是原来里面的代码viewController

使用这个变量

var containerForLoading = UIView()

需要时这样调用

self.showLoadingView(uponView: self.view)
extension ViewController {
    
    func showLoadingView(uponView: UIView) {
        containerForLoading = UIView(frame: uponView.bounds)
        uponView.addSubview(containerForLoading)

        containerForLoading.backgroundColor = .white
        containerForLoading.alpha = 0
        UIView.animate(withDuration: 0.24) { self.containerForLoading.alpha = 0.8 }
        let activivityIndicator = UIActivityIndicatorView()
        containerForLoading.addSubview(activivityIndicator)

        activivityIndicator.translatesAutoresizingMaskIntoConstraints = false


        NSLayoutConstraint.activate([

            activivityIndicator.centerYAnchor.constraint(equalTo: uponView.centerYAnchor),
            activivityIndicator.centerXAnchor.constraint(equalTo: uponView.centerXAnchor)

        ])

        activivityIndicator.startAnimating()
    }

    func removeLoading(uponView: UIView) {

        containerForLoading.removeFromSuperview()

    }
    
    
}

您可以将 loadingContainerTag 设为局部变量,并将参数名称更改为其他名称。然后在创建容器视图后分配给参数:

extension UIViewController {
    func showLoadingView(containerForLoadingProperty: inout UIView, uponView: UIView) {
        // local variable!
        let containerForLoading = UIView(frame: uponView.bounds)
        
        // also set property
        containerForLoadingProperty = containerForLoading
        
        uponView.addSubview(containerForLoading)
        containerForLoading.backgroundColor = .white
        containerForLoading.alpha = 0
        
        // no "self."!
        UIView.animate(withDuration: 0.24) { containerForLoading.alpha = 0.8 }
        // ... everything else is the same

removeLoading 可以只有一个非 inout 参数:

func removeLoading(containerForLoadingProperty: UIView) {
    containerForLoadingProperty.removeFromSuperview()
}

但是...


显示加载指示器的方法需要一个 inout 参数是非常奇怪的。它不应分配给 caller 提供的特殊 属性。它应该只显示加载指示器!

containerForLoading 属性 的目的是让您在 removeLoading 中知道要删除哪个视图。如果您不将 containerForLoading 视图存储在 属性 中的某处,您将不知道要删除哪个视图,对吗?那么,我们可以使用视图的 tag 属性 来标识视图,因此您可以将 containerForLoading 设为局部变量,然后在 removeLoading 中使用其标记来找到它。

extension UIViewController {
    
    static let loadingContainerTag = <a number you like>

    func showLoadingView(uponView: UIView) {
        // local variable!
        let containerForLoading = UIView(frame: uponView.bounds)
        uponView.addSubview(containerForLoading)
        containerForLoading.backgroundColor = .white
        containerForLoading.alpha = 0
        
        // set tag
        containerForLoading.tag = UIViewController.loadingContainerTag
        
        // no "self."!
        UIView.animate(withDuration: 0.24) { containerForLoading.alpha = 0.8 }
        let activivityIndicator = UIActivityIndicatorView()
        containerForLoading.addSubview(activivityIndicator)
        activivityIndicator.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            activivityIndicator.centerYAnchor.constraint(equalTo: uponView.centerYAnchor),
            activivityIndicator.centerXAnchor.constraint(equalTo: uponView.centerXAnchor)
        ])
        activivityIndicator.startAnimating()
    }
    func removeLoading(uponView: UIView) {
        // find view with the tag
        uponView.viewWithTag(UIViewController.loadingContainerTag)?.removeFromSuperview()
    }
}