呼叫指示器中的iOS正在下推视图/内容,修改根视图框架`

呼叫指示器中的iOS正在下推视图/内容,修改根视图框架`,ios,objective-c,Ios,Objective C,我有一个问题,我的根视图(UIViewController视图)被调用指示器按下:window.rootViewController.view.frame正在修改(Y设置为20)。当我独自响应did/willStatusBarFrameChange时,我不希望出现这种行为 我正在寻找一个属性或设置,该属性或设置阻止修改帧以响应调用中的状态栏。我使用其他API来响应顶部/底部框架和iPhone X安全区域中的更改 我尝试过像autoResizingMask,extendedlayoutinclud

我有一个问题,我的根视图(UIViewController视图)被调用指示器按下:
window.rootViewController.view.frame
正在修改(Y设置为20)。当我独自响应
did/willStatusBarFrameChange
时,我不希望出现这种行为

我正在寻找一个属性或设置,该属性或设置阻止修改帧以响应调用中的状态栏。我使用其他API来响应顶部/底部框架和iPhone X安全区域中的更改

我尝试过像
autoResizingMask
extendedlayoutincludesopaquebar
edgesForExtendedLayout
viewerrespectSystemMinimumLayoutMargins
之类的方法,但都没能奏效

如果相关的话,视图也会向下移动,表明这不是副作用,而是某个地方的预期行为

我读过很多关于类似行为的报道,但还没有弄清楚他们是否真的解决了这个问题和/或解决方案到底是什么(每个解决方案似乎都解决了一个稍微不同的问题)

相关问题:(答案不够详细),(不清楚如何适应)

--

我无法提供简单的复制,但设置视图的代码部分如下所示:

窗口设置:

uWindow* window = [[uContext sharedContext] window];
window.rootViewController = (UIViewController*)[[UIApplication sharedApplication] delegate];
[window makeKeyAndVisible];
我们的AppDelegate实现(相关部分)


我们的目标是无论调整了什么帧/控件/边距,
OurRootView
始终占据整个屏幕空间。我正在使用其他API来检测这些帧并相应地调整内容。我没有使用任何其他控制器、视图或布局。

我希望我能理解您的问题:如果您有一些像incall这样的指示器,或者在我的情况下,位置使用“地图”。你需要在应用程序启动时检测到有一些指示器,并重新设置整个窗口的框架。我的解决方案是:

didfishlaunchingwithoptions
中,检查状态栏的框架,因为incall是状态栏的一部分

CGFloat height = [UIApplication sharedApplication].statusBarFrame.size.height;
    if (height == 20) {
        self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    }
    else {
        CGRect frame = [[UIScreen mainScreen] bounds];
        frame.size.height = frame.size.height - height +20;
        frame.origin.y = height-20;
        self.window = [[UIWindow alloc] initWithFrame:frame];
    }

您可以在视图控制器中侦听通知
UIApplicationIDChangeStatusBarFrameNotification
,以便在状态栏发生更改时捕获。然后调整视图控制器的主视图矩形,使其始终覆盖整个屏幕

// Declare in your class
@property (strong, nonatomic) id<NSObject> observer;

- (void)viewDidLoad {
    [super viewDidLoad];

    _observer = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidChangeStatusBarFrameNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
        CGFloat newHeight = self.view.frame.size.height + self.view.frame.origin.y;
        self.view.frame = CGRectMake(0.0, 0.0, self.view.frame.size.width, newHeight);
    }];
}

-(void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:_observer];
}
//在类中声明
@属性(强,非原子)id观察器;
-(无效)viewDidLoad{
[超级视图下载];
_observer=[[NSNotificationCenter defaultCenter]addObserverForName:UIApplicationIDChangeStatusBarFrameNotification对象:nil队列:nil usingBlock:^(NSNotification*\u非空注释){
CGFloat newHeight=self.view.frame.size.height+self.view.frame.origin.y;
self.view.frame=CGRectMake(0.0,0.0,self.view.frame.size.width,newHeight);
}];
}
-(无效)解除锁定{
[[NSNotificationCenter defaultCenter]removeObserver:_observer];
}
我在各种型号上试用过,据我所知,效果很好。在iPhone X上,由于不会改变通话状态栏的高度,因此不会发布通知


还有一个相应的
UIApplicationWillChangeStatusBarFrameNotification
,在状态栏更改之前触发,以防您想以某种方式准备视图。

不清楚是否有禁用此行为的标志。然而,我确实找到了一种否定这种效果的方法

任何导致帧下移的操作都是通过修改根视图的
帧来实现的。可以超越此设定器并阻止移动。在我们的例子中,根视图是固定的,因此我这样做:

@implementation OurRootView

- (void)setFrame:(CGRect)frame;
{
    frame.origin.y = 0;
    [super setFrame:frame];
}
@endf
当显示in call display(来电显示)时,这将使视图保持在固定位置(我们通过更改statusBarFrame和/或SafeAreaInsetts自行处理新的大小)。我不知道为什么这也避免了帧的动画,但确实如此


如果由于某种原因您无法覆盖
setFrame
,您可以通过覆盖应用程序代理的
didChangeStatusBarFrame
并修改根视图的框架(将原点设置回0)获得近似类似的效果。动画仍然使用此路线播放。

您没有使用自动布局吗?您从代码中实例化了视图?是的,这些都是在ObjC中手工编写的。我们需要控制根视图。我也有同样的问题。如果我理解得很好,我将向您发送解决方案。“问题是我的视图本身在控制器中向下移动,因此我无法在其下方绘制。”这到底意味着什么?控制器不是视图,因此视图不能在其中移动。什么是“画在下面”?当in call bar出现时,您的应用程序会向下移动,这是正常的。有什么问题?“对
rootViewController.view=root
”的迂回调用,但您知道这是完全非法的吗?您不能将视图分配给视图控制器(当然,在其
loadView
实现中除外)。视图控制器获取其视图的方式有多种,直接赋值不是其中之一。你所做的每一件事都是如此的与众不同,完全脱离了现实,以至于我很惊讶它居然能奏效。这使得同情变得非常困难。我希望有一个API或标志可以禁用这种行为。如果操作系统行为发生变化,以这种方式使用statusBarFrame可能会导致大小调整错误。那么,使用故事板将解决此问题。这是唯一一种不被黑客攻击的方式。我同时发布了。我已经弄明白了这一点,并设法后退一步,避免修改帧矩形。是的,你的解决方案很好!不幸的是,我们似乎没有“api正确”的答案,这是最好的解决办法(
// Declare in your class
@property (strong, nonatomic) id<NSObject> observer;

- (void)viewDidLoad {
    [super viewDidLoad];

    _observer = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidChangeStatusBarFrameNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
        CGFloat newHeight = self.view.frame.size.height + self.view.frame.origin.y;
        self.view.frame = CGRectMake(0.0, 0.0, self.view.frame.size.width, newHeight);
    }];
}

-(void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:_observer];
}
@implementation OurRootView

- (void)setFrame:(CGRect)frame;
{
    frame.origin.y = 0;
    [super setFrame:frame];
}
@endf