3

My game is going into background mode when performing a swipe from the bottom edge of the screen on iPhone X iOS 12.

As per Apple documentation overriding preferredScreenEdgesDeferringSystemGestures and calling setNeedsUpdateOfScreenEdgesDeferringSystemGestures should stop the app from going to background but this is's not working on iOS 12.

I am using Unity3D and the editor has the Defer system gestures on edges option , which is implemented as per apple documentation, but also does not work.

I am compiling the project in Xcode 10.

Does anyone else have this problem and do you have a fix?

PS: I am testing this in an empty single view iOS project, the only added code is the following:

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear: animated];

    [self setNeedsUpdateOfHomeIndicatorAutoHidden];
    [self setNeedsUpdateOfScreenEdgesDeferringSystemGestures];
}

- (UIRectEdge)preferredScreenEdgesDeferringSystemGestures
{
    return UIRectEdgeAll;
}

- (BOOL)prefersHomeIndicatorAutoHidden
{
    return YES;
}

Update: Turns out that if I use a swift implementation it works. Too bad I cannot do this for the Unity3D 2017 generated project.

class ViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()
    
    if #available(iOS 11.0, *){
        setNeedsUpdateOfScreenEdgesDeferringSystemGestures()
    }
}

override var preferredScreenEdgesDeferringSystemGestures: UIRectEdge{
    return [.all];
}
}

New Update: In Unity 2019 it works by unchecking "Status Bar Hidden" in Project Stttings\Resolution and presentation and making sure you check at least one edge in Poject Settings\Other Settings\Defer system gestures on edges

filo
  • 677
  • 7
  • 19

4 Answers4

7

Removing prefersHomeIndicatorAutoHidden makes it work in Objective C also.

This is the working example implementation, for anyone having the same problem:

- (void)viewDidLoad {
    [super viewDidLoad];

    if (@available(iOS 11.0, *)) { 
      [self setNeedsUpdateOfScreenEdgesDeferringSystemGestures];
    }
 }

- (UIRectEdge)preferredScreenEdgesDeferringSystemGestures
{
    return UIRectEdgeAll;
}

And for those who, like me, are using Unity3d just delete the following method from UnityViewControllerBase+iOS.mm in the generated Xcode project:

- (BOOL)prefersHomeIndicatorAutoHidden
{
    return YES;
}

If you're not using Unity, ensure that prefersHomeIndicatorAutoHidden is NO/false.

Dan Rosenstark
  • 68,471
  • 58
  • 283
  • 421
filo
  • 677
  • 7
  • 19
3

As per the apple documentation, preferredScreenEdgesDeferringSystemGestures doesn't stop the app from going to background, it just gives your gesture precedence over system gesture. However, if you try to do it successively a second time, the system gesture would work. You can easily verify this by comparing with other apps.

By default the line at the bottom which helps in swiping up is black in colour and the swipe up gesture would work instantly if you do not override this method. But in your app, the line will look gray'ed out initially. If you do a swipe up, it will become black again and if you swipe up a second time, the system gesture will work.

I am putting this as an answer because of limited characters for commenting.

GoGreen
  • 2,251
  • 1
  • 17
  • 29
  • Thanks for pointing this out, it helps clarify my question. The behaviour I am looking for is the one described by you where system gesture works the second time ( the app backgrounds on the second gesture ). The behaviour I am currently experiencing is that the app goes to background from the first gesture. – filo Oct 09 '18 at 12:25
1

For Swift the answer is to override the instance property like so within your UIViewController.

override var preferredScreenEdgesDeferringSystemGestures: UIRectEdge { 
    get { .all } 
}

for example.

Brian
  • 105
  • 12
0

Same as accepted answer but now more Swifty

class ViewController: UIViewController {

    // must be false so that first swipe up is ignored
    override var prefersHomeIndicatorAutoHidden: Bool {
        return false
    }

    override var preferredScreenEdgesDeferringSystemGestures: UIRectEdge {
        return [.bottom]
    }
    
    // MARK: - Either true or false works
    
    override var prefersStatusBarHidden: Bool { return true }
}
Dan Rosenstark
  • 68,471
  • 58
  • 283
  • 421