Mengaktifkan tata letak otomatis di iOS 6 sambil tetap kompatibel dengan iOS 5

153

Apa cara terbaik untuk memanfaatkan fitur tata letak otomatis baru iOS 6 sambil tetap memberikan kompatibilitas dengan perangkat yang lebih lama pada versi iOS sebelumnya?

sglantz
sumber
+1. Di mana Anda bisa mengetahui hal ini? Ada petunjuk?
Janak Nirmal
@ Jennis Belum. iOS 6 secara resmi akan dirilis besok (19/9/2012). Semoga itu termasuk beberapa dokumentasi tambahan tentang masalah ini.
sglantz
Saya belum menemukan apa pun. Pikiran yang ingin tahu ingin tahu!
Ben Kreeger
Saya pikir itu tidak mungkin. Mirip storyboard tidak mungkin di iOS4.
Leo Natan
Di luar menyediakan dua file nib, saya tidak melihat bagaimana itu mungkin terjadi. Tapi saya setuju dengan Anda.
Leo Natan

Jawaban:

120

Autolayout dapat diaktifkan atau dinonaktifkan pada setiap file .storyboard atau .xib. Cukup pilih file tertentu dan modifikasi properti "Use Autolayout" menggunakan inspektur File di Xcode:

properti autolayout di inspektur File

Menggunakan file antarmuka yang diaktifkan autolayout dengan target penyebaran yang ditetapkan ke versi iOS sebelum 6.0 menghasilkan kesalahan kompilasi, misalnya:

Kesalahan di MainStoryboard.storyboard: 3: Tata Letak Otomatis pada Versi iOS sebelum 6.0

Salah satu opsi Anda untuk menggunakan pembayaran otomatis dalam suatu proyek dan masih mempertahankan kompatibilitas dengan iOS4-5 adalah untuk membuat dua target : satu untuk target penyebaran iOS 6.0 dan satu untuk versi iOS sebelumnya, misalnya:

masukkan deskripsi gambar di sini

Anda juga dapat membuat dua versi untuk masing-masing storyboard dan file XIB dan menggunakan autolayout yang diaktifkan dengan target 6.0 dan yang lainnya dengan target lawas, misalnya:

masukkan deskripsi gambar di sini

Anda kemudian menambahkan MainStoryBoardAutoSize ke fase Build target iOS6 dan file lainnya ke target iOS4. Anda dapat mempelajari lebih lanjut tentang menggunakan beberapa target sini .

EDIT: Sebagai jawaban marchinram , jika Anda memuat file storyboard Anda dari kode dan tidak menggunakan pengaturan "Main Storyboard" di Xcode untuk mengatur storyboard awal, Anda dapat menggunakan satu target.

Bagi saya, biaya penambahan kompleksitas mempertahankan beberapa target dan file antarmuka tampaknya lebih besar daripada manfaat menggunakan autolayout. Kecuali untuk beberapa kasus khusus, Anda mungkin jauh lebih baik menggunakan ukuran otomatis lama (atau layoutSubViews dari kode) secara eksklusif jika kompatibilitas iOS4-5 diperlukan.

Imre Kelényi
sumber
29
Tata letak otomatis memerlukan iOS 6 atau lebih baru. Itu tidak bekerja dengan iOS 5! Harap verifikasi klaim Anda sebelum memposting. iOS 5 tidak memiliki API yang diperlukan (seperti NSLayoutConstraint kelas). Jika Anda tidak percaya, lihat apa yang dialami pengguna lain ketika mereka mencoba menggunakan Autolayout dengan iOS 5: stackoverflow.com/questions/11252057/… stackoverflow.com/questions/11198981/…
Imre Kelényi
1
Ya saya pikir Anda benar, saya pikir saya mendengarnya di beberapa video wwdc, tapi sekarang saya mengujinya di perangkat iOS 5.0 dan macet. Saya akan membaca video-video ini dan memeriksa di mana saya mendengarnya. Meskipun demikian, Anda benar, apakah itu macet di iOS 5.0
Asad Khan
@ ImreKelényi Bagaimana Anda mengirimkan ini ke app store? Saya tidak terlalu terbiasa dengan prosesnya, tetapi saya pikir Anda mengirimkan satu arsip zip dari file .app Anda. Apakah memiliki dua target membuat proses itu lebih sulit? Terima kasih.
Crystal
47

Apakah Anda benar-benar membutuhkan dua target? Saya membuatnya bekerja seperti ini, saya memiliki 2 storyboard seperti yang dikatakan Imre Kelényi, satu dengan auto layouts diaktifkan dan yang lainnya tanpa, kemudian dalam delegasi aplikasi saya hanya memeriksa versi mana yang mereka gunakan dan pilih storyboard yang tepat:

#import "AppDelegate.h"

#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:(v) options:NSNumericSearch] != NSOrderedAscending)

@interface AppDelegate ()
    @property (strong, nonatomic) UIViewController *initialViewController;
@end

@implementation AppDelegate

@synthesize window = _window;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    UIStoryboard *mainStoryboard = nil;
    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"6.0")) {
        mainStoryboard = [UIStoryboard storyboardWithName:@"iPhone_iOS6" bundle:nil];
    } else {
        mainStoryboard = [UIStoryboard storyboardWithName:@"iPhone_iOS5" bundle:nil];
    }

    self.initialViewController = [mainStoryboard instantiateInitialViewController];
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.window.rootViewController = self.initialViewController;
    [self.window makeKeyAndVisible];

    return YES;
}

@end

Memiliki 2 target juga berfungsi tetapi sepertinya terlalu berat bagi saya

marchinram
sumber
1
Kamu benar. Ini berfungsi selama Anda memuat storyboard dari kode dan tidak menggunakan pengaturan "Main Storyboard" target di Xcode. Saya menambahkan referensi ke jawaban Anda dari posting saya.
Imre Kelényi
SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TOberlebihan. Cukup uji kelas iOS 6-saja terhadap nol. Lihat developer.apple.com/library/mac/#documentation/developertools/…
matt
ya poin bagus, tidak terlalu memikirkan restorasi ketika saya menjawab awalnya
marchinram
Ahem, jangan gunakan willFinishLaunchingWithOptions - Saya mendapat "Pengakhiran aplikasi karena pengecualian tanpa tertangkap 'NSInvalidUnarchiveOperationException', alasan: 'Tidak dapat membuat instance kelas bernama NSLayoutConstraint'" menjalankan simulator di bawah iOS 5.1. Masalahnya tidak terjadi dengan didFinishLaunchingWithOptions.
Elise van Looij
4

Jika perbedaan tata letak tidak besar, jauh lebih mudah untuk menggunakan Springs dan Struts untuk memposisikan elemen.

Apodaca kaya
sumber
3

Terinspirasi oleh satu gagasan target @ marchinram, ini adalah solusi yang akhirnya saya buat. Dua storyboard, satu untuk struts-and-spring dan satu untuk autolayout. Dalam ringkasan target, saya menetapkan storyboard autolayout sebagai default. Kemudian, di appDelegate, saya memeriksa apakah saya perlu memuat storyboard struts-and-spring pre-6.0 setelah semua:

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    Class cls = NSClassFromString (@"NSLayoutConstraint");
    if (cls == nil) {
        NSString *mainStoryboardName = nil;
        if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
            mainStoryboardName = @"MainStoryboard_iPad_StrutsAndSprings";
        } else {
            mainStoryboardName = @"MainStoryboard_iPhone_StrutsAndSprings";
        }
        UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:mainStoryboardName bundle:nil];

        UIViewController *initialViewController = [mainStoryboard instantiateInitialViewController];
        self.window.rootViewController = initialViewController;
        [self.window makeKeyAndVisible];
    }

Juga, saya menetapkan target penempatan storyboard struts-and-spring ke iOS 5.1, dan storyboard autolayout ke Project SDK (iOS 6.0).

Saya benar-benar ingin melakukan peralihan sebelum default di storyboard dimuat, di willFinishLaunchingWithOptions: tetapi itu menghasilkan 'NSInvalidUnarchiveOperationException', alasan: 'Tidak dapat membuat instance kelas bernama NSLayoutConstraint' tidak peduli apa yang saya coba.

Elise van Looij
sumber
0

Saya telah menemukan pengaturan ukuran tampilan utama Xibs ke Freeform, dan kemudian menggunakan Autosizing works a treat. Tidak mengotak dalam kode untuk masalah tampilan.

Anonim
sumber