Detect if app is running in Slide Over or Split Vi

2019-01-13 05:36发布

In iOS 9, is it possible to detect when an app is running in iOS 9's Slide Over or Split View mode?

I've tried reading through Apple's documentation on iOS 9 multitasking, but haven't had any luck with this…

I ask because I might have a feature in my app that I'd like to disable when the app is opened in a Slide Over.

12条回答
再贱就再见
2楼-- · 2019-01-13 06:06

Like the solution by Dan Rosenstark, but changed to work on the new iPad Pro's that seem to report a different frame and screen.bounds height based on if it's ran directly on the device through Xcode, or if it is compiled and released through TestFlight or App Store. The height would return 980 when through AS or TF, rather than 1024 as it was supposed to like through Xcode causing it to be impossible to return true.

extension UIApplication {
    public var isSplitOrSlideOver: Bool {
        guard let w = self.delegate?.window, let window = w else { return false }
        return !(window.frame.width == window.screen.bounds.width)
    }
}
查看更多
\"骚年 ilove
3楼-- · 2019-01-13 06:07

You can watch both -willTransitionToTraitCollection:withTransitionCoordinator: for the size class and viewWillTransitionToSize:withTransitionCoordinator: for the CGSize of your view. Hardcoding in size values isn't recommended though.

查看更多
We Are One
4楼-- · 2019-01-13 06:08

Just another way to repackage all of this

extension UIApplication {
    public var isSplitOrSlideOver: Bool {
        guard let w = self.delegate?.window, let window = w else { return false }
        return !window.frame.equalTo(window.screen.bounds)
    }
}

then you can just

  • UIApplication.shared.isSplitOrSlideOver in Swift
  • UIApplication.sharedApplication.isSplitOrSlideOver in Objective-C

Note that, in Swift, the window object is a double optional... WTF!

查看更多
Fickle 薄情
5楼-- · 2019-01-13 06:15

Just check if your window occupies the whole screen:

BOOL isRunningInFullScreen = CGRectEqualToRect([UIApplication sharedApplication].delegate.window.frame, [UIApplication sharedApplication].delegate.window.screen.bounds);

If this is false, then you're running in a split view or a slide over.

Here is the code snipped which will automatically maintain this flag irrespective of rotation

-(void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection
{
 // simply create a property of 'BOOL' type
 isRunningInFullScreen = CGRectEqualToRect([UIApplication sharedApplication].delegate.window.frame, [UIApplication sharedApplication].delegate.window.screen.bounds);
}
查看更多
兄弟一词,经得起流年.
6楼-- · 2019-01-13 06:18

I wrote a SizeClasser library based on @Michael Voccola's library.
You can initialize it with the traitCollection of your view controller and detect split views as well as device specific orientation.
So you could write your code specifically 1/3 horizontal split view or 1/3 portrait split view which UITraitCollection does not give you a way to detect them.
https://github.com/cemolcay/SizeClasser

查看更多
淡お忘
7楼-- · 2019-01-13 06:22

I recently had to determine display style of an application based including, not only if it changed to split view or slide-over, but also what portion of the screen was being utilized for the application (full, 1/3, 1/2, 2/3). Adding this to a ViewController subclass was able to solve the issue.

/// Dismisses this ViewController with animation from a modal state.
func dismissFormSheet () {
    dismissViewControllerAnimated(true, completion: nil)
}

private func deviceOrientation () -> UIDeviceOrientation {
    return UIDevice.currentDevice().orientation
}

private func getScreenSize () -> (description:String, size:CGRect) {
    let size = UIScreen.mainScreen().bounds
    let str = "SCREEN SIZE:\nwidth: \(size.width)\nheight: \(size.height)"
    return (str, size)
}

private func getApplicationSize () -> (description:String, size:CGRect) {
    let size = UIApplication.sharedApplication().windows[0].bounds
    let str = "\n\nAPPLICATION SIZE:\nwidth: \(size.width)\nheight: \(size.height)"
    return (str, size)
}


func respondToSizeChange (layoutStyle:LayoutStyle) {
    // Respond accordingly to the change in size.
}

enum LayoutStyle: String {
    case iPadFullscreen         = "iPad Full Screen"
    case iPadHalfScreen         = "iPad 1/2 Screen"
    case iPadTwoThirdScreeen    = "iPad 2/3 Screen"
    case iPadOneThirdScreen     = "iPad 1/3 Screen"
    case iPhoneFullScreen       = "iPhone"
}

private func determineLayout () -> LayoutStyle {
    if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
        return .iPhoneFullScreen
    }
    let screenSize = getScreenSize().size
    let appSize = getApplicationSize().size
    let screenWidth = screenSize.width
    let appWidth = appSize.width
    if screenSize == appSize {
        return .iPadFullscreen
    }

    // Set a range in case there is some mathematical inconsistency or other outside influence that results in the application width being less than exactly 1/3, 1/2 or 2/3.
    let lowRange = screenWidth - 15
    let highRange = screenWidth + 15

    if lowRange / 2 <= appWidth && appWidth <= highRange / 2 {
        return .iPadHalfScreen
    } else if appWidth <= highRange / 3 {
        return .iPadOneThirdScreen
    } else {
        return .iPadTwoThirdScreeen
    }

}

override func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)
    respondToSizeChange(determineLayout())
}
查看更多
登录 后发表回答