Ответ 1
Попробуйте использовать imageWithData:scale:
(iOS 6 и более поздние версии)
NSData *imageData = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:imageData scale:[[UIScreen mainScreen] scale]];
У меня есть приложение, которое извлекает изображения из NSURL
. Можно ли сообщить программе, что они являются сетчатыми ('@2x') версиями (изображения имеют разрешение сетчатки)? В настоящее время у меня есть следующее, но изображения отображаются на пикселях с более высоким разрешением:
NSURL *url = [NSURL URLWithString:self.imageURL];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];
self.pictureImageView.image = image;
Попробуйте использовать imageWithData:scale:
(iOS 6 и более поздние версии)
NSData *imageData = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:imageData scale:[[UIScreen mainScreen] scale]];
Вам нужно перемасштабировать UIImage, прежде чем добавлять его в представление изображения.
NSURL *url = [NSURL URLWithString:self.imageURL];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];
CGFloat screenScale = [UIScreen mainScreen].scale;
if (image.scale != screenScale)
image = [UIImage imageWithCGImage:image.CGImage scale:screenScale orientation:image.imageOrientation];
self.pictureImageView.image = image;
Лучше избегать жесткого кодирования значения шкалы, таким образом, вызов UIScreen. Дополнительную информацию о том, почему это необходимо, см. В документации на яблоки UIImage
s scale
property.
Также лучше избегать использования метода NSData
s -dataWithContentsOfURL:
(если ваш код не работает в фоновом потоке), поскольку он использует синхронный сетевой вызов, который нельзя контролировать или отменять. Вы можете больше узнать о проблемах синхронной сети и о способах избежать этого в этом техническом Q & A в Apple.
Вам нужно установить масштаб на UIImage.
UIImage* img = [[UIImage alloc] initWithData:data];
CGFloat screenScale = [UIScreen mainScreen].scale;
if (screenScale != img.scale) {
img = [UIImage imageWithCGImage:img.CGImage scale:screenScale orientation:img.imageOrientation];
}
В документации говорится о том, чтобы быть осторожным, чтобы построить все ваши UIImages в одном масштабе, иначе вы можете получить странные проблемы с отображением, когда вещи показывают половину размера, двойной размер, половинное разрешение и т.д. Чтобы избежать всего этого, загрузите все UIImages при разрешении сетчатки. Ресурсы будут загружены в правильной шкале автоматически. Для UIImages, созданных из URL-данных, вам нужно установить его.
Чтобы добавить к этому, то, что я сделал конкретно, было следующим, в той же ситуации, как шарм.
double scaleFactor = [UIScreen mainScreen].scale;
NSLog(@"Scale Factor is %f", scaleFactor);
if (scaleFactor==1.0) {
[cell.videoImageView setImageWithURL:[NSURL URLWithString:regularThumbnailURLString];
}else if (scaleFactor==2.0){
[cell.videoImageView setImageWithURL:[NSURL URLWithString:retinaThumbnailURLString];
}
@2x соглашение - это просто удобный способ для загрузки изображений из набора приложений. Если вы не хотите показывать изображение на экране сетчатки, вам нужно сделать его в 2 раза больше:
Размер изображения 100x100
Размер: 50x50.
Изменить: я думаю, что если вы загружаете изображения с сервера, лучшим решением будет добавление некоторого дополнительного параметра (например, масштаба) и возврата изображений соответствующего размера:
www.myserver.com/get_image.php?image_name=img.png&scale=2
Вы можете получить масштаб, используя шкалу [[UIScreen mainScreen]]
+ (void)deviceScaledImageForView:(UIImageView*)v
withParameterizedUrl:(NSString*)url
iPadSupport:(BOOL)iPadSupport
after:(UITask)after
{
// ...Declare Retina and Retina Plus versions of the the URL string...
NSString* url2x = @"";
NSString* url3x = @"";
// ...And if I'm on an iPad with my caller allowing iPad-specific images...
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad && iPadSupport) {
// ...Generate the iPad non-retina and retina versions of the URL...
/* Note 3x is not applicable to iPad */
url = [url stringByReplacingOccurrencesOfString:@".png" withString:@"~ipad.png"];
url2x = [url stringByReplacingOccurrencesOfString:@"~ipad.png" withString:@"@2x~ipad.png"];
}
// ...Or, for iPhone...
else {
// ...Generate the iPhone non-Retina, Retina and Retina Plus versions of the URL...
url2x = [url stringByReplacingOccurrencesOfString:@".png" withString:@"@2x.png"];
url3x = [url stringByReplacingOccurrencesOfString:@".png" withString:@"@3x.png"];
}
// ...If I'm running on iOS 7.1 or newer...
CGFloat scale = .0f;
UIScreen* screen = [UIScreen mainScreen];
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_7_1)
// ...Choose a scale based on the iOS 8 API.
//currently the scale for the 6 plus ranges from 2.6 to 2.8 to 3.0 depending on zoomed mode or running on the sim
// since our images are at 2x or at 3x we want whole numbers.
scale = ceilf(screen.nativeScale);
else
// ...Choose a device scale on the iOS 7 API.
scale = screen.scale;
// ...If I've chosen a Retina Plus scale...
if (scale > 2.0f){
// ...Select the 3x Retina Plus version of the image.
url = url3x;
}
// ...Otherwise for retina displays...
else if (scale == 2.0f)
// ...Select the Retina version of the image.
url = url2x;
// ...And finally, request the image data with SDWebImage (for cache support)...
[[SDWebImageDownloader sharedDownloader] downloadImageWithURL:[NSURL URLWithString:url]
options:SDWebImageDownloaderUseNSURLCache
progress:nil
completed:^(UIImage* i,
NSData* d,
NSError* e,
BOOL finished)
{
// ...And after the image is obtained...
// ...Apply it to the image view with the correct device scale...
v.image = [UIImage imageWithData:d scale:scale];
// ...And if I have an after-action...
if (after)
// ...Run it.
after();
}];
}
Чтобы программно определить iPhone, что конкретное изображение Retina, вы можете сделать что-то вроде этого:
UIImage *img = [self getImageFromDocumentDirectory];
img = [UIImage imageWithCGImage:img.CGImage scale:2 orientation:img.imageOrientation];
В моем случае изображение TabBarItem
было динамическим, то есть загружалось с сервера. Тогда iOS не может идентифицировать его как сетчатку. Вышеприведенный фрагмент кода работал у меня как шарм.