Подтвердить что ты не робот

IOS 7/Xcode 5: программный запуск программ запуска устройства

Есть ли способ использовать приложения LaunchImage в качестве фона в универсальном приложении iOS без размещения одинаковых ресурсов изображения в нескольких местах?

Мне не удалось получить доступ к файлам LaunchImage в Images.xcassets, поэтому я создал два новых набора изображений "Фоновый портрет" и "Фоновый пейзаж" (поскольку, похоже, нет способа разместить пейзажные и портретные изображения в тот же набор).

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

Приветствуются любые советы о том, как получить доступ к LaunchImage для текущего устройства.

GCOLaunchImageTransition должен был выполнить задание для iOS < 7.

4b9b3361

Ответ 1

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

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

и т.д.. Обратите внимание, в частности, они не называются Default.png или любые изменения этого. Даже если это то, что вы назвали файлами. Как только вы уронили их в одну из колодцев в каталоге активов, они выходят на другой конец со стандартным именем.

Так что [UIImage imageNamed:@"Default"] не будет работать, потому что в комплекте приложения нет такого файла. Тем не менее, [UIImage imageNamed:@"LaunchImage"] будет работать (при условии, что вы набрали либо iPhone Portrait 2x хорошо, либо iPhone iOS7 iPhone 1x хорошо).

Документация указывает, что метод imageNamed: на UIImage должен автоматически выбрать правильную версию, но я думаю, что это относится только к изображениям, отличным от образа запуска, по крайней мере, я не получил его работать вполне правильно (может быть, я просто не буду делать что-то правильно).

Таким образом, в зависимости от ваших конкретных обстоятельств вам может потребоваться небольшая пробная версия и ошибка, чтобы получить правильное имя файла. Создайте и запустите приложение в симуляторе, а затем вы всегда можете посмотреть в соответствующем подкаталоге ~/Library/Application Support/iPhone Simulator, чтобы проверить, что такое фактические имена файлов в пакете приложений.

Но опять же, главное, что нет необходимости включать дубликаты файлов изображений, и вам не нужно вносить какие-либо коррективы в фазу сборки Copy Bundle Resources.

Ответ 2

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

// Load launch image
NSString *launchImageName;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
    if ([UIScreen mainScreen].bounds.size.height == 480) launchImageName = @"[email protected]"; // iPhone 4/4s, 3.5 inch screen
    if ([UIScreen mainScreen].bounds.size.height == 568) launchImageName = @"[email protected]"; // iPhone 5/5s, 4.0 inch screen
    if ([UIScreen mainScreen].bounds.size.height == 667) launchImageName = @"[email protected]"; // iPhone 6, 4.7 inch screen
    if ([UIScreen mainScreen].bounds.size.height == 736) launchImageName = @"[email protected]"; // iPhone 6+, 5.5 inch screen
}
else if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
    if ([UIScreen mainScreen].scale == 1) launchImageName = @"LaunchImage-700-Portrait~ipad.png"; // iPad 2
    if ([UIScreen mainScreen].scale == 2) launchImageName = @"[email protected]~ipad.png"; // Retina iPads
}
self.launchImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:launchImageName]];

Ответ 3

В большинстве ответов требуется создать имя изображения в зависимости от типа устройства, масштаба, размера и т.д. Но, как отметил Мэтью Берк, каждое изображение в каталоге образа запуска будет переименовано в "LaunchImage *", и поэтому мы можем итерации через наши изображения запуска и найти (для текущего устройства) соответствующее изображение. В Objective-C он может выглядеть так:

NSArray *allPngImageNames = [[NSBundle mainBundle] pathsForResourcesOfType:@"png"
                                        inDirectory:nil];

for (NSString *imgName in allPngImageNames){
    // Find launch images
    if ([imgName containsString:@"LaunchImage"]){
        UIImage *img = [UIImage imageNamed:imgName];
        // Has image same scale and dimensions as our current device screen?
        if (img.scale == [UIScreen mainScreen].scale && CGSizeEqualToSize(img.size, [UIScreen mainScreen].bounds.size)) {
            NSLog(@"Found launch image for current device %@", img.description);
            break;
        }
    }
}

(Обратите внимание, что этот код использует метод "containsString", введенный с iOS 8. Для предыдущих версий iOS используйте "rangeOfString" )

Ответ 5

Быстрая версия отличного ответа от Daniel Witurna, который не требует проверки на список всех известных типов устройств или ориентации.

func appLaunchImage() -> UIImage?
{
    let allPngImageNames = NSBundle.mainBundle().pathsForResourcesOfType("png", inDirectory: nil)

    for imageName in allPngImageNames
    {
        guard imageName.containsString("LaunchImage") else { continue }

        guard let image = UIImage(named: imageName) else { continue }

        // if the image has the same scale AND dimensions as the current device screen...

        if (image.scale == UIScreen.mainScreen().scale) && (CGSizeEqualToSize(image.size, UIScreen.mainScreen().bounds.size))
        {
            return image
        }
    }

    return nil
}

Ответ 6

Info.plist в комплекте содержит информацию об образе запуска, включая имя образа запуска.

Objective-C:

- (UIImage *)getCurrentLaunchImage {
    CGSize screenSize = [UIScreen mainScreen].bounds.size;

    NSString *interfaceOrientation = nil;
    if (([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationPortraitUpsideDown) ||
        ([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationPortrait)) {
        interfaceOrientation = @"Portrait";
    } else {
        interfaceOrientation = @"Landscape";
    }

    NSString *launchImageName = nil;

    NSArray *launchImages = [[[NSBundle mainBundle] infoDictionary] valueForKey:@"UILaunchImages"];
    for (NSDictionary *launchImage in launchImages) {
        CGSize launchImageSize = CGSizeFromString(launchImage[@"UILaunchImageSize"]);
        NSString *launchImageOrientation = launchImage[@"UILaunchImageOrientation"];

        if (CGSizeEqualToSize(launchImageSize, screenSize) &&
            [launchImageOrientation isEqualToString:interfaceOrientation]) {
            launchImageName = launchImage[@"UILaunchImageName"];
            break;
        }
    }

    return [UIImage imageNamed:launchImageName];
}

Свифт 4:

func getCurrentLaunchImage() -> UIImage? {

    guard let launchImages = Bundle.main.infoDictionary?["UILaunchImages"] as? [[String: Any]] else { return nil }

    let screenSize = UIScreen.main.bounds.size

    var interfaceOrientation: String
    switch UIApplication.shared.statusBarOrientation {
    case .portrait,
         .portraitUpsideDown:
        interfaceOrientation = "Portrait"
    default:
        interfaceOrientation = "Landscape"
    }

    for launchImage in launchImages {

        guard let imageSize = launchImage["UILaunchImageSize"] as? String else { continue }
        let launchImageSize = CGSizeFromString(imageSize)

        guard let launchImageOrientation = launchImage["UILaunchImageOrientation"] as? String else { continue }

        if
            launchImageSize.equalTo(screenSize),
            launchImageOrientation == interfaceOrientation,
            let launchImageName = launchImage["UILaunchImageName"] as? String {
            return UIImage(named: launchImageName)
        }
    }

    return nil
}

Ответ 7

Краткая функция в Swift для получения имени образа запуска во время выполнения:

func launchImageName() -> String {
    switch (UI_USER_INTERFACE_IDIOM(), UIScreen.mainScreen().scale, UIScreen.mainScreen().bounds.size.height) {
        case (.Phone, _, 480): return "[email protected]"
        case (.Phone, _, 568): return "[email protected]"
        case (.Phone, _, 667): return "[email protected]"
        case (.Phone, _, 736): return "[email protected]"
        case (.Pad, 1, _): return "LaunchImage-700-Portrait~ipad.png"
        case (.Pad, 2, _): return "[email protected]~ipad.png"
        default: return "LaunchImage"
    }
}

Ответ 8

Я не знаю, означает ли это то, что вы имеете в виду с помощью кода. Но если вы выберете "project- > target- > build phase- > copy bundle resources", нажмите "+" и "добавьте другое", перейдите к вашим Images.xcassets- > LaunchImage.launchimage и выберите любой png, который вы хотите использовать. и нажмите "открыть". Теперь вы можете использовать изображение как [UIImage imageNamed:@"Default"];

Ответ 9

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

if( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone ){

    CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height;
    CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;
    if( screenHeight < screenWidth ){
        screenHeight = screenWidth;
    }

    if( screenHeight > 480 && screenHeight < 667 ){
        DLog(@"iPhone 5/5s");
    } else if ( screenHeight > 480 && screenHeight < 736 ){
        DLog(@"iPhone 6");
    } else if ( screenHeight > 480 ){
        DLog(@"iPhone 6 Plus");
    } else {
        DLog(@"iPhone 4/4s");
    }
}

Ответ 10

Ответ Мэтью Берка - правильный ответ. Ниже приведен код, который я использую, чтобы заставить это работать для iOS9/Xcode7, создав приложение для iOS7 и выше, для iPhone и iPad, разрешен пейзаж.

Во-первых, немного подробнее: В iOS8/Xcode6, если вы использовали файл экрана запуска раскадровки, при запуске приложения приложение создало бы 2 изображения (один портрет, один альбом) этого файла экрана запуска в правильном разрешении для вашего устройства, и вы смогли получить это изображение из пути к файлу. (Я считаю, что он хранился в папке Library/LaunchImage).

Однако в iOS9/XCode 7 это изображение больше не создается (хотя снимок сделан в папке моментальных снимков, но у него есть undescriptive name, которое постоянно меняется), поэтому, если вы хотите использовать свой LaunchImage где-то еще в ваш код, вам нужно будет использовать исходный источник изображения (предпочтительно, из-за приложения Thinning). Теперь, как объясняет Мэтью Берк, вы не можете добраться до этого образа, просто:

let launchImage = UIImage(named: "LaunchImage")

Даже если имя изображения в вашем каталоге активов - LaunchImage, Xcode/iOS9 не позволит вам.

К счастью, вам больше не нужно включать ваши снимки запуска в свой каталог активов. Я говорю, к счастью, потому что это означало бы увеличение размера загрузки приложения на 20 МБ, если вы создаете приложение для всех устройств.

Итак, как добраться до этих изображений запуска, чем? Ну, вот шаги:

  • Создайте свои изображения запуска и поместите их в свой каталог активов. Название изображений не имеет значения.
  • Убедитесь, что ваш файл экрана запуска (в соответствии с вашими основными настройками) пуст и удалите приложение с вашего устройства и симулятора. (просто удаление имени файла и повторного запуска его не будет, сначала вам нужно будет удалить приложение)
  • Запустите приложение в симуляторе и перейдите в папку ~/Library/Application Support/iPhone Simulator и найдите там свое приложение. (Это немного хлопот, поскольку имена папок являются indescriptive.) Покажите содержимое пакета для вашего файла .app, и там вы увидите несколько файлов изображений, начинающихся с "LaunchImage-...". В моем случае было 9 изображений поскольку я создаю приложение для iPhone и iPad для iOS7 и выше.
  • Затем в вашем коде вам нужно будет определить, на каком устройстве работает ваше приложение, и если оно в портретном или ландшафтном, а затем решить, какое изображение использовать. Чтобы сделать это немного легче, я использовал эту структуру: https://github.com/InderKumarRathore/DeviceGuru. Be ware, он еще не включил новейшие устройства (iPhone 6s и iPhone 6s plus), поэтому вам придется добавить строку в свой быстрый файл для этого. Затем поставьте ниже код кода в vc, где вы хотите свой запуск, и там вы идете:

    func launchImage() -> UIImage? {
        if let launchImageName = launcheImageName() {
            print(launchImageName)
            return UIImage(named: launchImageName)
        }
        else {
            print("no launch image")
            return nil
        }
    }
    
    func launcheImageName() -> String? {
        let HD35 = "[email protected]"
        let HD40 = "[email protected]"
        let HD47 = "[email protected]"
        var HD55 = "[email protected]"
        var padHD = "[email protected]~ipad.png"
        var pad = "LaunchImage-700-Portrait~ipad.png"
    
        if UIDevice.currentDevice().orientation == UIDeviceOrientation.LandscapeLeft || UIDevice.currentDevice().orientation == UIDeviceOrientation.LandscapeRight {
            HD55 = "[email protected]"
            padHD = "[email protected]~ipad.png"
            pad = "LaunchImage-700-Landscape~ipad.png"
        }
    
        let hardware = hardwareString()
        if (hardware == "iPhone1,1")            { return HD35 }
        if (hardware == "iPhone1,2")            { return HD35 }
        if (hardware == "iPhone2,1")            { return HD35 }
        if (hardware == "iPhone3,1")            { return HD35 }
        if (hardware == "iPhone3,2")            { return HD35 }
        if (hardware == "iPhone3,3")            { return HD35 }
        if (hardware == "iPhone4,1")            { return HD35 }
        if (hardware == "iPhone5,1")            { return HD40 }
        if (hardware == "iPhone5,2")            { return HD40 }
        if (hardware == "iPhone5,3")            { return HD40 }
        if (hardware == "iPhone5,4")            { return HD40 }
        if (hardware == "iPhone6,1")            { return HD40 }
        if (hardware == "iPhone6,2")            { return HD40 }
        if (hardware == "iPhone7,1")            { return HD55 }
        if (hardware == "iPhone7,2")            { return HD47 }
        if (hardware == "iPhone8,1")            { return HD55 }
        if (hardware == "iPhone8,2")            { return HD47 }
    
        if (hardware == "iPod1,1")              { return HD35 }
        if (hardware == "iPod2,1")              { return HD35 }
        if (hardware == "iPod3,1")              { return HD35 }
        if (hardware == "iPod4,1")              { return HD35 }
        if (hardware == "iPod5,1")              { return HD40 }
    
        if (hardware == "iPad1,1")              { return pad }
        if (hardware == "iPad1,2")              { return pad }
        if (hardware == "iPad2,1")              { return pad }
        if (hardware == "iPad2,2")              { return pad }
        if (hardware == "iPad2,3")              { return pad }
        if (hardware == "iPad2,4")              { return pad }
        if (hardware == "iPad2,5")              { return pad }
        if (hardware == "iPad2,6")              { return pad }
        if (hardware == "iPad2,7")              { return pad }
        if (hardware == "iPad3,1")              { return padHD }
        if (hardware == "iPad3,2")              { return padHD }
        if (hardware == "iPad3,3")              { return padHD }
        if (hardware == "iPad3,4")              { return padHD }
        if (hardware == "iPad3,5")              { return padHD }
        if (hardware == "iPad3,6")              { return padHD }
        if (hardware == "iPad4,1")              { return padHD }
        if (hardware == "iPad4,2")              { return padHD }
        if (hardware == "iPad4,3")              { return padHD }
        if (hardware == "iPad4,4")              { return padHD }
        if (hardware == "iPad4,5")              { return padHD }
        if (hardware == "iPad4,6")              { return padHD }
        if (hardware == "iPad4,7")              { return padHD }
        if (hardware == "iPad4,8")              { return padHD }
        if (hardware == "iPad5,3")              { return padHD }
        if (hardware == "iPad5,4")              { return padHD }
    
        if (hardware == "i386")                 { return HD55 }
        if (hardware == "x86_64")               { return HD55 }
        if (hardware.hasPrefix("iPhone"))       { return HD55 }
        if (hardware.hasPrefix("iPod"))         { return HD55 }
        if (hardware.hasPrefix("iPad"))         { return padHD }
    
        //log message that your device is not present in the list
        logMessage(hardware)
    
        return nil
    }
    

Ответ 11

 if (IS_IPHONE_4_OR_LESS) {
    self.imageView.image = [UIImage imageNamed:@"[email protected]"];
}
else if (IS_IPHONE_5){
     self.imageView.image = [UIImage imageNamed:@"[email protected]"];
}
else if (IS_IPHONE_6){
     self.imageView.image = [UIImage imageNamed:@"[email protected]"];
}
else if (IS_IPHONE_6P){
      self.imageView.image = [UIImage imageNamed:@"[email protected]"];
}

Ответ 12

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

-(NSString *)getLaunchImageName{

NSArray *allPngImageNames = [[NSBundle mainBundle] pathsForResourcesOfType:@"png" inDirectory:nil];
NSString *expression=[NSString stringWithFormat:@"SELF contains '%@'",@"LaunchImage"];

NSArray *res = [allPngImageNames filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:expression]];

NSString *launchImageName;
for (launchImageName in res){
    {
        UIImage *img = [UIImage imageNamed:launchImageName];
        // Has image same scale and dimensions as our current device screen?
        if (img.scale == [UIScreen mainScreen].scale && CGSizeEqualToSize(img.size, [UIScreen mainScreen].bounds.size)) {
            NSLog(@"Found launch image for current device %@", img.description);
            break;
        }

    }

}
return launchImageName; }

Ответ 13

Как только вы создали Images.xcassets, просто переименуйте LaunchImage в Default.

Это поможет сэкономить много проблем, если вы поддерживаете iOS5 и iOS6.

Фактическое имя "папки" /категории будет указано в активе при сборке. Все остальное верно, что сказал Мэтью Берк;)

Ответ 14

Создайте новую группу в своем проекте, не поддерживаемую каким-либо физическим каталогом. Импортируйте в эту группу свои изображения запуска, непосредственно из LaunchImage.launchimage. Вуаля.

Ответ 15

Еще одно более современное и элегантное решение, основанное на превосходном ответе Дэниела:

extension UIImage {
    static var launchImage: UIImage? {
        let pngs = Bundle.main.paths(forResourcesOfType: "png", inDirectory: nil)
        return pngs
            .filter({$0.contains("LaunchImage")})
            .compactMap({UIImage(named: $0)})
            .filter({$0.size == UIScreen.main.bounds.size})
            .first
    } 
}

Таким образом, вы можете просто написать:

let myLaunchImage = UIImage.launchImage

Ответ 16

Поскольку ресурс LaunchImage фактически является обычным зверем...

Мое предложение состоит в том, чтобы создать каталог вторичных активов с дубликатами изображений (или нужным подмножеством).

Я называю мой FauxLaunchImage. Они могут получить к нему доступ, как вы хотели

[UIImage imageNamed:@"FauxLaunchImage"];