应用扩展上的“‘共享’不可用:在适当的情况下使用基于视图控制器的解决方案”

Sch*_*999 3 ios swift ios-app-extension

我有一个进行网络调用的类。我希望能够在主应用程序和应用程序扩展中使用此类。但是,在本课程中我使用:UIApplication.shared.isNetworkActivityIndicatorVisible.

由于shared在应用程序扩展中不可用,有没有一种方法可以让我使用类似的东西#available,这样我就不必仅仅因为这一行代码而复制此类?(我可以删除活动指示器,但我不想这样做,因为我想让用户知道网络调用何时发生)

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

Mil*_*sáľ 5

使用依赖注入模式重构依赖于UIApplication.shared.

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

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

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

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

例如,让我们在这里上一堂大课:

class Big {

    ... a lot of code ...

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

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

        ... more code ...
    }
}
Run Code Online (Sandbox Code Playgroud)
  1. 首先,一个协议:

    protocol NetworkIndicator {
        func showActivity()
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 然后是两个实现:

    class AppNetworkIndicator: NetworkIndicator {
         func showActivity() {
             UIApplication.shared.isNetworkActivityIndicatorVisible = true
        }
    }
    
    class ExtensionNetworkIndicator: NetworkIndicator {
        func showActivity() {}
    }
    
    Run Code Online (Sandbox Code Playgroud)
  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 ...
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  4. 最后,在您使用该类的应用程序中Big,通过以下方式启动它:

    let big = Big(networkIndicator: AppNetworkIndicator())
    
    Run Code Online (Sandbox Code Playgroud)

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

    let big = Big(networkIndicator: ExtensionNetworkIndicator())
    
    Run Code Online (Sandbox Code Playgroud)