3

The application in question must allow the user to select one the available screen modes of the selected display. For example, an external display may natively support 1920x1080 but it's EDID will also show supported resolutions of 1920x1200, 1280x720 and 1024x768.

By default, connected an external display to an iOS device appears to always favor the highest supported resolution o the external display. I have allowed a user to select from the list of UIScreenMode.availableModes to change resolution. Once the mode is selected and applied to the externalScreen.currentMode it does appear the the new resolution is being considered.

In testing, I have assigned a view to the external display which is all red. After changing the resolution from, for example, 1920x1080 to 1024x768, the red box is displayed on the monitor at a 4:3 aspect ratio. Doing the same but to 1280x720 keeps the red box 16:9 which fills the screen much the same as 1080.

However, the red box contains two labels with AutoLayout constraints. When the resolution changes, the x/y coordinates of the labels stay the same relative to the red box. They should be centered in the red box, but they do not seem to re-layout when the resolution is changed. Additionally, the physical size of the labels enlarges when the resolution is dropped, which shows that they are being affected in some way by the resolution change.

So, how can the subviews of the red box (a UIView assigned to the externalDisplay) be updated after changed the UIScreenMode.currentMode?

Below is a simplified version of what is going on:

var externalScreen:UIScreen!
var externalWindow: UIWindow!
var extView: MyExternalDisplay?

func initializeExternalScreen(externalScreen:UIScreen) {
    self.externalScreen = externalScreen

    // Create a new window sized to the external screen's bounds
    self.externalWindow = UIWindow(frame: self.externalScreen.bounds)

    // Assign screen object to screen property of the new window
    self.externalWindow.screen = externalScreen

    // Load the clock view
    let clockView = self.storyboard?.instantiateViewControllerWithIdentifier("ExternalDisplay") as! ExternalDisplay
    clockView.view.frame = self.externalWindow.frame

    // Add the view to the window
    self.externalWindow.addSubview(clockView.view)

    // Create a reference to the clockView
    self.extView = clockView

    // Make the window visible
    self.externalWindow.makeKeyAndVisible()
}

func applyNewMode () {
    let newMode = externalScreen.availableModes[1] // 1024x768
    externalScreen.currentMode = newMode
}

This is called when a screenModeDidChange notification is received.

func handeScreenModeDidChangeNotification (notification:NSNotification) {
        extView?.view.frame = externalWindow.frame
        extView?.view.layoutSubviews()
}

UPDATE

Adding the following response to screenModeDidChange notification seems to - sometimes - solve the issue. The results are inconsistent and I am not sure if this is an iOS 9 beta issue or not.

func handeScreenModeDidChangeNotification (notification:NSNotification) {
    let screen = UIScreen.screens()[1]
    initializeExternalScreen(screen)
}

UPDATE #2

While it seems possible to change the resolution of the external screen with the methods listed here, it does not change the actual output resolution. For example, if an iOS device is connected to a monitor showing a preferred EDID of 1920x1080 the device will default to this resolution. Changing the resolution using the previously-mentioned methods will change the resolution of the presented image, but the output resolution stays 1920x1080. In essence, all that is happening is the reduction in resolution of the displayed content while the actual output resolution remains unchanged.

Michael Voccola
  • 1,827
  • 6
  • 20
  • 46
  • Having just googled up this issue and finding this question, I'd like to point out the documentation explicitly calls out that you need to set the screen mode *before* you attach the screen to a window. Could that have effected your tests in some way? (Thanks for giving me a pointer to the references in question, btw; I was running in circles before discovering the keyword UIScreenMode !) – RonLugge Sep 21 '17 at 17:44

0 Answers0