Как я могу запустить цикл for с методами обработчика завершения? - PullRequest
0 голосов
/ 05 мая 2018

У меня есть несколько файлов изображений, которые мне нужно получить от дрона с помощью DJI SDK, но способ, которым я это сделал, не кажется самым идеальным. Мне было интересно, как я смогу сделать это, но вместо этого внутри цикла for. Вот код:

func getImages(with file: DJIMediaFile?) {
    guard let file = file else { return }
    file.fetchPreview { (error) in
        if error != nil {
            print(String(describing: error?.localizedDescription))
            return
        }

        guard let image = file.preview else { print("No preview"); return }
        self.images.append(image)
        self.imageView.image = image
        self.index += 1

        if self.index < self.mediaList.count {
            self.getImages(with: self.mediaList[self.index])
        } else {
            // [...]
        }

       }
   }
}

Любая помощь будет оценена кем-то, кто знаком с DJI SDK и Swift (возможно, мне следовало использовать какой-то другой метод API?). Спасибо!

1 Ответ

0 голосов
/ 05 мая 2018

Это в основном быстрый вопрос, а не проблема DJI SDK и больше относится к проверке кода. Но это просто

func getNewImages() {
    for file in self.mediaList where file != nil { 
        self.getImages(with: file!) { image, error in //not ideal to force unwarp but i don't know if the where clause supports if let binding, or if file is really nil, you'll have to check yourself in code
            guard let newImage = image else { return }
            self.cachedImages.append(newImage)
        }
    }

    self.setImage(at: 0)
}

func getImages(with file: DJIMediaFile, completion: (UIImage?, Error?)->()) {
    file.fetchPreview { (error) in // is this async? If its' async you may want to use dispatch groups in the for in loop to run the setImage at the correct time
        if let newError = error {
            print(String(describing: newError.localizedDescription))
            completion(nil, error)
            return
        }

        guard let image = file.preview else { 
            print("No preview")
            completion(nil, nil)
            return
        }

        completion(image, nil)
   }
}

func setImage(at row: Int) {
     guard row < self.cachedImages.count - 1 else { return }
     self.imageView.image = self.cachedImages[row]
}

Ваша рекурсия может привести к ошибкам, которые вам не нужны. Это то, что вы хотите сделать, но это должно быть просто изменить в зависимости от того, что я вижу здесь.

Редактировать: Возможно, вы также намереваетесь заменить файл, так как люди загружают свои изображения из самого беспилотника, и в этом случае код выглядит примерно так:

func getNewImages() {
    for file in self.mediaList where file != nil { 
        self.getImages(with: file!) { image, error in //not ideal to force unwarp but I don't know if the where clause supports if let binding, or if file is really nil, you'll have to check yourself in code
            guard let newImage = image else { return }
            self.imageView.image = newImage
        }
    }  
}

func getImages(with file: DJIMediaFile, completion: (UIImage?, Error?)->()) {
    file.fetchPreview { (error) in
        if let newError = error {
            print(String(describing: newError.localizedDescription))
            completion(nil, error)
            return
        }

        guard let image = file.preview else { 
            print("No preview")
            completion(nil, nil)
            return
        }

        completion(image, nil)
   }
}

edit2: Также обратите внимание, что это не обязательно лучший способ сделать это, но ранее это было то, как вы делаете это в цикле for. Я думаю, что лучшим способом было бы использовать map или forEach для самого массива mediaList, вот так. (тот же метод getImages, ничего не меняется). Это можно было бы дополнительно уточнить между протоколами, расширениями и тому, что нет, но не зная вашей программы, трудно сделать лучшие рекомендации.

func getNewImages() {
    self.mediaList.forEach { file in
        guard let newFile = file else { return }

        self.getImages(with: newFile) { image, error in
            guard let newImage = image else { return }
            self.imageView.image = newImage
        }
    }  
}
...