swift 中的依赖倒置

Dependency Inversion in swift

您好,我有一个问题要问这里的开发人员,我正在阅读一本来自 big nerd ranch 的 iOS 编程书籍。我对如何构建和技术来创建应用程序很感兴趣。我试图实现它,它是一个依赖倒置,代码是这样的

这是书中app delegate中的代码

let rootViewController = window!.rootViewController as! UINavigationController
    let photosViewController = rootViewController.topViewController as! PhotoViewController
    photosViewController.store = PhotoStore()

这是 photoViewController class

class PhotoInfoViewController: UIViewController {
@IBOutlet weak var imageView: UIImageView!

var photo: Photo! {
    didSet {
        navigationItem.title = photo.title
    }
}

var store: PhotoStore!

override func viewDidLoad() {
    super.viewDidLoad()

    store.fetchImage(for: photo) { (result) in
        switch result {
        case let .success(image):
            self.imageView.image = image
        case let .failure(error):
            print("Error fetching image for photo: \(error)")
        }
     }
  }
}

这是用于依赖倒置代码的照片商店class

enum ImageResult {
    case success(UIImage)
    case failure(Error)
}

enum PhotoError: Error {
    case imageCreationError
}

enum PhotoResult {
    case success([Photo])
    case failure(Error)
}

class PhotoStore {
    private let session: URLSession = {
        return URLSession(configuration: .default)
    }()

    let imageStore = ImageStore()

    func fetchInterestingPhoto(completion: @escaping (PhotoResult) -> Void) {
        let url = FlickerAPI.interestingPhotoURL
        let request = URLRequest(url: url)
        let task = session.dataTask(with: request) { (data, response, error) in
            let result = self.processPhotosRequest(data: data, error: error)

            OperationQueue.main.addOperation {
                completion(result)
            }
        }
        task.resume()
    }

    private func processPhotosRequest(data: Data?, error: Error?) -> PhotoResult {
        guard let jsonData = data else { return .failure(error!) }
        return FlickerAPI.photos(fromJSON: jsonData)
    }

    func fetchImage(for photo: Photo, completion: @escaping (ImageResult) -> Void) {
        let photoKey = photo.photoID
        if let image = imageStore.image(forKey: photoKey) {
            OperationQueue.main.addOperation {
                completion(.success(image))
            }
            return
        }

        let photoURL = photo.remoteURL
        let request = URLRequest(url: photoURL)

        let task = session.dataTask(with: request) { (data, response, error) in
            let result = self.processImageRequest(data: data, error: error)

            if case let .success(image) = result {
                self.imageStore.setImage(image, forKey: photoKey)
            }

            OperationQueue.main.addOperation {
                completion(result)
            }
        }
        task.resume()
    }

    private func processImageRequest(data: Data?, error: Error?) -> ImageResult {
        guard
            let imageData = data,
            let image = UIImage(data: imageData)
            else {
                // Couldn't create an image
                if data == nil {
                    return .failure(error!)
                } else {
                    return .failure(PhotoError.imageCreationError)
                }
        }
        return .success(image)
    }
}

我要问的是,如果我有一个选项卡栏控制器并且假设有 2 个视图控制器,其中一个正在获取新闻数据,而另一个控制器正在获取天气数据。我如何实现这种依赖倒置,因为应用程序委托中的根视图控制器将是选项卡栏控制器,这就是我混淆实现它的原因?因为这本书只使用一个视图控制器。

请记住这是一个 hack,在我看来,不应该这样做,因为依赖项应该在 init 中声明。但是因为您可能正在从 Storyboard 创建 TabBar。您只有这个选项可以从 window 获取 TabBar。 TabBarController 有一个构成 TabBar 的 viewController 数组。您只需要遍历并尝试将它们转换为 PhotoViewController。如果是,那么你设置商店:

let rootViewController = window!.rootViewController as! UITabBarController

for viewController in rootViewController.viewControllers {
    switch viewController {
    case let photoViewController as PhotoViewController:
        photoViewController.store = PhotoStore()
    default:
        break
    }
}