Панель состояния iOS 7, такая как iOS 6

У меня есть приложение с поддержкой ландшафтного и портретного режима. И мне нужна та же строка поведения, что и на iOS 6. Каков самый простой способ сделать это?

Я пробовал решения в разделе "Переполнение стека" строка состояния iOS 7 в стиле iOS 6, но это не работает. Мое подчинение зависит от размера представления, и мое представление не растягивается правильно. Я не хочу обновлять свои XIB файлы; Я просто хочу добавить что-то, что помогает мне. Я не знаю, что это может быть (взломать или молиться).

Ответ 1

1) Это взлом, но он работает!

Используйте его, если вы не используете UIAlertView или KGStatusBar!!!

#import <objc/runtime.h>

@interface UIScreen (I_love_ios_7)
- (CGRect)bounds2;
- (CGRect)boundsForOrientation:(UIInterfaceOrientation)orientation;
@end

@implementation UIScreen (I_love_ios_7)
- (CGRect)bounds2
{
    return [self boundsForOrientation:[[UIApplication sharedApplication] statusBarOrientation]];
}

- (CGRect)boundsForOrientation:(UIInterfaceOrientation)orientation
{
    CGRect resultFrame = [self bounds2];
    if(UIInterfaceOrientationIsLandscape(orientation))
        resultFrame.size.width -= 20;
    else
        resultFrame.size.height -= 20;
    return resultFrame;
}
@end

void Swizzle(Class c, SEL orig, SEL new)
{
    Method origMethod = class_getInstanceMethod(c, orig);
    Method newMethod = class_getInstanceMethod(c, new);
    if(class_addMethod(c, orig, method_getImplementation(newMethod), method_getTypeEncoding(newMethod)))
        class_replaceMethod(c, new, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));
    else
        method_exchangeImplementations(origMethod, newMethod);
}


@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
        Swizzle([UIScreen class], @selector(bounds2), @selector(bounds));
        [application setStatusBarStyle:UIStatusBarStyleLightContent];
        self.window.clipsToBounds =YES;

        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(applicationDidChangeStatusBarOrientation:)
                                                     name:UIApplicationWillChangeStatusBarOrientationNotification
                                                   object:nil];
        NSDictionary* userInfo = @{UIApplicationStatusBarOrientationUserInfoKey : @([[UIApplication sharedApplication] statusBarOrientation])};
        [[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationWillChangeStatusBarOrientationNotification
                                                            object:nil
                                                          userInfo:userInfo];
    }

    return YES;
}

- (void)applicationDidChangeStatusBarOrientation:(NSNotification *)notification
{
    UIInterfaceOrientation orientation = [[notification.userInfo objectForKey: UIApplicationStatusBarOrientationUserInfoKey] intValue];
    CGSize size = [[UIScreen mainScreen] boundsForOrientation:orientation].size;
    int w = size.width;
    int h = size.height;
    float statusHeight = 20.0;
    switch(orientation){
        case UIInterfaceOrientationPortrait:
            self.window.frame =  CGRectMake(0,statusHeight,w,h);
            break;
        case UIInterfaceOrientationPortraitUpsideDown:
            self.window.frame =  CGRectMake(0,0,w,h);
            break;
        case UIInterfaceOrientationLandscapeLeft:
            self.window.frame =  CGRectMake(statusHeight,0,w,h);
            break;
        case UIInterfaceOrientationLandscapeRight:
            self.window.frame =  CGRectMake(0,0,w,h);
            break;
    }
}
@end

2) Создайте категорию и всегда используйте contentView вместо view

@interface UIViewController(iOS7_Fix)
@property (nonatomic, readonly) UIView* contentView;
- (void)updateViewIfIOS_7;
@end

@implementation UIViewController(iOS7_Fix)
static char defaultHashKey;
- (UIView *)contentView
{
    return objc_getAssociatedObject(self, &defaultHashKey)?: self.view;
}

- (void)setContentView:(UIView *)val
{
    objc_setAssociatedObject(self, &defaultHashKey, val, OBJC_ASSOCIATION_RETAIN_NONATOMIC) ;
}

- (void)updateViewIfIOS_7
{
    if([[[UIDevice currentDevice] systemVersion] floatValue] < 7 || objc_getAssociatedObject(self, &defaultHashKey))
        return;

    UIView* exchangeView = [[UIView alloc] initWithFrame:self.view.bounds];
    exchangeView.autoresizingMask = self.view.autoresizingMask;
    exchangeView.backgroundColor = [UIColor blackColor];

    UIView* view = self.view;
    if(self.view.superview){
        [view.superview addSubview:exchangeView];
        [view removeFromSuperview];
    }
    [exchangeView addSubview:view];
    self.view = exchangeView;

    CGRect frame = self.view.bounds;
    frame.origin.y += 20.0;
    frame.size.height -= 20.0;
    view.frame = frame;
    view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

    [self setContentView:view];
}

В каждом UIViewController:

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self updateViewIfIOS_7];
    UILabel* lab = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 130, 30)];
    lab.backgroundColor = [UIColor yellowColor];
    [self.contentView addSubview:lab];
    //...
}

PortraitLandscape

Ответ 2

Вы можете попробовать написать это в своем ViewWillappear или DidAppear. Здесь мы сдвигаем рамку представления на 20 пикселей вниз.

CGRect frame = self.view.frame;
frame.origin.y = 20;

if (self.view.frame.size.height == 1024 || 
    self.view.frame.size.height == 768)
{
    frame.size.height -= 20;
}

self.view.frame = frame;

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

-(UIStatusBarStyle)preferredStatusBarStyle
{
     return UIStatusBarStyleLightContent; // For light status bar

     return UIStatusBarStyleDefault // For Dark status bar
}

Ответ 3

Если вы находитесь на Xcode 5 и вы устанавливаете в iOS 7, то извините, этого не произойдет (насколько мне известно).

Если вы хотите увидеть строку состояния на iOS 7, например iOS 6, чем открыть свой проект в Xcode 4.xx и установить в iOS 7. Одна из проблем с этим подходом я обнаружил, что иногда Xcode 4.xx не распознает устройство iOS 7.

Но если ваш Xcode 4.x.x может показать ваше устройство iOS 7, он будет работать.

.api, сгенерированный из Xcode 4.xx, будет работать как в iOS 6, так и в iOS 7, но вы не получите лишнее пространство (строки состояния) на iOS 7 и новый вид клавиатуры, выбора, переключателя и т.д. Но да, вы получите новый UIAlertView (я не знаю, почему это новое, а остальные элементы управления старые).

Надеюсь, мы скоро получим лучшее решение в Xcode 5 для этого.

UPDATE:

Я нашел способ запустить приложение из Xcode 5 как Xcode 4. Это всего лишь вопрос базового SDK. Если вы хотите создать Xcode 4 (iOS 6 SDK) из Xcode 5, выполните следующие действия.

  • Закройте Xcode 4 и 5.

  • В Xcode 4 Перейдите к

    /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs

  • Здесь вы найдете iPhoneOS6.1.sdk. Скопируйте эту папку. А теперь идите в Xcode 5 по тому же пути. В Xcode 5 вы найдете iPhoneOS7.0.sdk. Вставьте iPhoneOS6.1.sdk с ним.

  • Теперь закройте Finder и запустите Xcode 5. Перейдите в project target setting -> Build Setting и найдите Base SDK. Выберите iOS 6.1 в качестве базового SDK. Это также будет работать в 6.0. Вам просто нужно найти iPhoneOS6.0.sdk.

  • Теперь вы увидите имя устройства дважды в раскрывающемся списке run. Один для SDK 7.0 и один для SDK 6.1. Итак, теперь вы можете запускать оба способа с помощью iOS 6 SDK и iOS 7 SDK.

Надеюсь, это поможет кому-то.

Ответ 4

Недавно мне пришлось решить подобную проблему, и я подошел к ней несколько иначе...

Подход состоял в том, чтобы использовать дополнительный контроллер представлений, который выступал в качестве контроллера представления контейнера для того, что изначально было моим rootViewController. Во-первых, я создал такой контейнер:

_containerView = [[UIView alloc] initWithFrame:[self containerFrame]];
_containerView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
_containerView.clipsToBounds = YES;

[self.view addSubview:_containerView];
[self.view setBackgroundColor:[UIColor blackColor]];

[UIApplication.sharedApplication setStatusBarStyle:UIStatusBarStyleLightContent animated:NO];

где containerFrame был определен следующим образом:

- (CGRect)containerFrame
{
    if ([MyUtilityClass isSevenOrHigher])
    {
        CGFloat statusBarHeight = [MyUtility statusBarHeight]; //20.0f
        return CGRectMake(0, statusBarHeight, self.view.bounds.size.width, self.view.bounds.size.height - statusBarHeight);
    }

    return self.view.bounds;
}

Наконец, я добавил, что первоначально был моим rootViewController в качестве childViewController нового:

//Add the ChildViewController
self.childController.view.frame = self.containerView.bounds;
self.childController.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
[self addChildViewController:self.childController];
[self.containerView addSubview:self.childController.view];
[self.childController didMoveToParentViewController:self];

Примечания: - Модальные контроллеры будут по-прежнему представлены в стиле iOS7, поэтому мне все равно придется это объяснять.

Надеюсь, это поможет кому-то!

Ответ 5

Это руководство помогает мне.

http://www.doubleencore.com/2013/09/developers-guide-to-the-ios-7-status-bar/

Самый надежный способ обработки разницы в размере 20 точек - это автоматический макет.

 Если вы не используете Auto Layout, Interface Builder предоставляет вам инструменты для обработки разницы в размере экрана между iOS 7 и более старыми версиями. Когда автоматическая компоновка отключена, вы заметите область на вкладке калибровки области полезности (правая панель) Interface Builder, которая позволяет вам установить iOS 6/7 Deltas.