“'shared' 不可用:在适当的地方使用基于视图控制器的解决方案”在 App Extension 上

"'shared' is unavailable: Use view controller based solutions where appropriate instead" on App Extension

我有一个 class 可以进行网络呼叫。我希望能够在主应用程序和应用程序扩展中使用此 class。但是,在这个 class 中我使用:UIApplication.shared.isNetworkActivityIndicatorVisible.

由于 shared 在 App Extensions 中不可用,有没有一种方法可以让我使用类似于 #available 的东西,这样我就不必复制这个 class 仅仅因为那一行代码? (我可以删除 activity 指示器,但我宁愿不删除,因为我想让用户知道何时发生网络调用)

我已经尝试按照我在另一个问题上找到的答案的建议添加预编译宏,但编译仍然报错。

使用依赖注入模式根据UIApplication.shared重构代码。

  1. 使用协议来描述当前由UIApplication.shared提供的功能。

  2. 为基本应用程序实施该协议,其中 UIApplication.shared 可用并在那里使用它。在不使用 UIApplication.shared 的情况下实现另一个实现,它将用于应用程序扩展。

  3. 重构您当前的 class 以使用协议实现对象并在初始化时注入正确的实现(依赖注入模式)- class 的初始化程序将接受协议实施。

  4. 在创建重构 class 的实例时连接正确的实现 - 在应用程序扩展中传递没有 UIApplication.shared 的实现,在基础应用程序中传递带有 UIApplication.shared.

所以,例如,让我们在这里有这么大的class:

class Big {

    ... a lot of code ...

    func a() {
        ... again some code ...

        // here the code that needs shared
        UIApplication.shared.isNetworkActivityIndicatorVisible = true

        ... more code ...
    }
}
  1. 所以首先,一个协议:

    protocol NetworkIndicator {
        func showActivity()
    }
    
  2. 然后两种实现:

    class AppNetworkIndicator: NetworkIndicator {
         func showActivity() {
             UIApplication.shared.isNetworkActivityIndicatorVisible = true
        }
    }
    
    class ExtensionNetworkIndicator: NetworkIndicator {
        func showActivity() {}
    }
    
  3. 重构Big以支持依赖注入:

    class Big {
        private let networkIndicator: NetworkIndicator
    
        init(networkIndicator: NetworkIndicator) {
            self.networkIndicator = networkIndicator
        }
    
        ... rest of code ...
    
        func a() {
            ... again some code ...
    
            // use injected protocol implementation
            networkIndicator.showActivity()
    
            ... more code ...
        }
    }
    
  4. 最后,在您使用 Big class 的应用程序中,使用以下命令启动它:

    let big = Big(networkIndicator: AppNetworkIndicator())
    

    并在扩展中使用其他实现:

    let big = Big(networkIndicator: ExtensionNetworkIndicator())