oleynikd
oleynikd

Reputation: 932

Positioning UIWindow in UIScreen in iOS

I need to add additional UIWindow to my App. This UIWindow should always be positioned in the bottom right corner of the screen despite device's orientation, here's the sketch: enter image description here

I've tried to subclass UIWindow like this to be able to set the size and the margins of window:

@interface MyWindow : UIWindow

@property (nonatomic) CGSize size;
@property (nonatomic) CGFloat margin;

@end

@implementation MyWindow

- (id)initWithSize:(CGSize)size andMargin:(CGFloat)margin {
    self.size = size;
    self.margin = margin;
    return [self initWithFrame:[self calculateFrame]];
}

- (CGRect)calculateFrame {
    return CGRectMake([[UIScreen mainScreen] bounds].size.width-self.size.width-self.margin, [[UIScreen mainScreen] bounds].size.height-self.size.height-self.margin, self.size.width, self.size.height);
}

- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        [self assignObservers];
    }
    return self;
}

-(void)assignObservers {
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(statusBarDidChangeFrame:)
                                                 name:UIDeviceOrientationDidChangeNotification
                                               object:nil];
}

- (void)statusBarDidChangeFrame:(NSNotification *)notification {
    [self setFrame:[self calculateFrame]];
}

@end

Everything is great on startup! No matter what orientation is on initial start new UIWindow position is correct. But when I rotate device - my window goes crazy, it jumps to unexpected positions and I can't figure out why.

Please help!

Upvotes: 1

Views: 761

Answers (1)

oleynikd
oleynikd

Reputation: 932

Everything works fine if:

dispatch_async(dispatch_get_main_queue(), ^{
    [self setFrame:[self calculateFrame]];
}); 

So full working code looks like this:

@interface MyWindow : UIWindow

@property (nonatomic) CGSize size;
@property (nonatomic) CGFloat margin;

@end

@implementation MyWindow

- (id)initWithSize:(CGSize)size andMargin:(CGFloat)margin {
    self.size = size;
    self.margin = margin;
    return [self initWithFrame:[self calculateFrame]];
}

- (CGRect)calculateFrame {
    return CGRectMake([[UIScreen mainScreen] bounds].size.width-self.size.width-self.margin, [[UIScreen mainScreen] bounds].size.height-self.size.height-self.margin, self.size.width, self.size.height);
}

- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        [self assignObservers];
    }
    return self;
}

-(void)assignObservers {
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(statusBarDidChangeFrame:)
                                                 name:UIApplicationDidChangeStatusBarOrientationNotification
                                               object:nil];
}

- (void)statusBarDidChangeFrame:(NSNotification *)notification {
    dispatch_async(dispatch_get_main_queue(), ^{
        [self setFrame:[self calculateFrame]];
    });
}

@end

Many thanks to Cocoa-Chat and max.lunin :)

Upvotes: 1

Related Questions