Фоторамка. requestImageForAsset возвращает два результата. Невозможно установить изображение

178
14

Итак, я использую библиотеку SwipeView (https://github.com/nicklockwood/SwipeView), чтобы показывать изображения с помощью фреймворка Photos для iOS8.


Однако, когда я вызываю requestImageForAsset, я замечаю, что получаю два результата: размер миниатюр и больший размер, который я хочу. Однако большее изображение не загружается (оно называется async, которое я понимаю) вовремя, чтобы вернуться, поэтому оно возвращает небольшое изображение.


Этот код может иметь смысл.


    func swipeView(swipeView: SwipeView!, viewForItemAtIndex index: Int, reusingView view: UIView!) -> UIView! {
let asset: PHAsset = self.photosAsset[index] as PHAsset

var imageView: UIImageView!

let screenSize: CGSize = UIScreen.mainScreen().bounds.size
let targetSize = CGSizeMake(screenSize.width, screenSize.height)

var options = PHImageRequestOptions()
// options.deliveryMode = PHImageRequestOptionsDeliveryMode.Opportunistic
options.resizeMode = PHImageRequestOptionsResizeMode.Exact

PHImageManager.defaultManager().requestImageForAsset(asset, targetSize: targetSize, contentMode: .AspectFill, options: options, resultHandler: {(result, info)in
println("huhuhuh")
println(result.size)
println(info)
imageView = UIImageView(image: result)
})
println("setting view)
return imageView
}


Вот вывод журнала:


Enteredhuhuhuh
(33.5,60.0)
SETTING VIEW
huhuhuh
(320.0,568.0)

Как вы можете видеть, он возвращает представление изображения до получения большого изображения. Как заставить его вернуть это большее изображение, чтобы он не показывал thumbnai?


Спасибо.

спросил(а) 2014-12-27T21:38:00+03:00 5 лет, 9 месяцев назад
1
Решение
321

Прочитать заголовок PHImageManager class


Если - [PHImageRequestOptions isSynchronous] возвращает NO (или параметры nil), resultHandler можно назвать 1 или более раз. Обычно в этом case, resultHandler будет вызываться асинхронно по основному потоку с запрошенными результатами. Однако, если deliveryMode = PHImageRequestOptionsDeliveryModeOpportunistic, resultHandler может быть называемый синхронно на вызывающем потоке, если любые данные изображения Сразу Доступно. Если данные изображения, возвращенные в этом первом проходе имеет недостаточное качество, resultHandler будет вызван снова, асинхронно на основной поток в более позднее время с "правильным" Результаты. Если запрос отменен, resultHandler не может быть вызван вообще. Если - [PHImageRequestOptions isSynchronous] возвращает YES, resultHandler будет вызываться ровно один раз, синхронно и на вызывающий поток. Синхронные запросы не могут быть отменены. resultHandler для асинхронных запросов, всегда вызываемых в основном потоке



Итак, что вы хотите сделать, так это то, что вы вызываете resultHandler для вызова synchronously

PHImageRequestOptions *option = [PHImageRequestOptions new];
option.synchronous = YES;

[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:target contentMode:PHImageContentModeAspectFill options:option resultHandler:^(UIImage *result, NSDictionary *info) {
//this block will be called synchronously
}];


Итак, ваш блок будет вызван до окончания вашего метода


Удачи!

ответил(а) 2014-12-30T10:00:00+03:00 5 лет, 9 месяцев назад
90

По умолчанию requestImageForAsset работает как асинхронный. Таким образом, в вашем методе оператор возврата будет выполнен еще до того, как изображение будет восстановлено. Поэтому мое предложение вместо того, чтобы возвращать imageView, передать imageView в том, что вам нужно заполнить изображение:


func swipeView(swipeView: SwipeView!, viewForItemAtIndex index: Int, reusingView view: UIView!, yourImageView: UIImageView)
{
let asset: PHAsset = self.photosAsset[index] as PHAsset

var imageView: UIImageView! = yourImageView;

let screenSize: CGSize = UIScreen.mainScreen().bounds.size
let targetSize = CGSizeMake(screenSize.width, screenSize.height)

var options = PHImageRequestOptions()
options.resizeMode = PHImageRequestOptionsResizeMode.Exact

PHImageManager.defaultManager().requestImageForAsset(asset, targetSize: targetSize, contentMode: .AspectFill, options: options, resultHandler: {(result, info)in
imageView.image = result;
})
}


Примечание:

Другой вариант - вы можете запустить уведомление с помощью изображения результата из resultHandler. Но я предпочитаю вышеупомянутый метод.


Подробнее см. PHImageManager.

ответил(а) 2014-12-30T10:01:00+03:00 5 лет, 9 месяцев назад
80

resultHandler: В блоке есть словарь информации, который может содержать логическое значение для клавиши PHImageResultIsDegradedKey, что указывает, является ли результат изображения низкокачественной заменой запрашиваемого изображения.


Вот какая документация говорит:


PHImageResultIsDegradedKey: Булево значение, указывающее, result image - это низкокачественный заменитель запрошенного изображения. (NSNumber)

Если ДА, параметр результата вашего блока resultHandler содержит низкокачественное изображение, поскольку фотографии еще не более качественное изображение. В зависимости от ваших настроек в Объект PHImageRequestOptions, который вы предоставили с запросом, Фотографии могут снова вызвать ваш блок обработчика результатов, чтобы обеспечить более качественное изображение.


ответил(а) 2015-10-07T21:04:00+03:00 4 года, 11 месяцев назад
57

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


var imageView =  UIImageView()
...
...
PHImageManager.defaultManager().requestImageForAsset(asset, targetSize: targetSize, contentMode: .AspectFill, options: options, resultHandler: {(result, info)in
println("huhuhuh")
println(result.size)
println(info)
if result.size.width > 1000 && result.size.height > 1000 { // add any size you want
imageView.setImage(result)
}
})

ответил(а) 2014-12-30T09:41:00+03:00 5 лет, 9 месяцев назад
57

Проверьте документацию Apple на этот метод здесь. В этом они говорят:


Для асинхронного запроса фотографии могут вызывать блок обработчика результатов больше чем единожды. Сначала фотографии вызывают блок для обеспечения низкого качества изображение, подходящее для отображения временно, когда оно готовит высококачественное изображение. (Если данные низкого качества сразу доступный, первый вызов может произойти до возвращения метода.)



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

ответил(а) 2014-12-30T09:15:00+03:00 5 лет, 9 месяцев назад
41

Используйте ниже опции, swift 3.0



publi var imageRequestOptions: PHImageRequestOptions{
let options = PHImageRequestOptions()
options.version = .current
options.resizeMode = .exact
options.deliveryMode = .highQualityFormat
options.isNetworkAccessAllowed = true
options.isSynchronous = true
return options}

ответил(а) 2017-02-08T12:29:00+03:00 3 года, 7 месяцев назад
42

попробуйте, это будет работать также асинхронно.


[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:target contentMode:PHImageContentModeAspectFill options:option resultHandler:^(UIImage *result, NSDictionary *info) {
if ([info objectForKey:@"PHImageFileURLKey"]) {
//your code
}
}];

ответил(а) 2017-02-07T12:22:00+03:00 3 года, 7 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема