Maximum height of iOS 8 Today Extension?

I made some tests and you can calculate the maximum height of your Today Extension with this formular:

for iPhone:

float maxHeight = [[ UIScreen mainScreen ] bounds ].size.height - 126;

for iPad:

float maxHeight = [[ UIScreen mainScreen ] bounds ].size.height - 171;

This should work for alle Screen sizes...


Ok, although you can assign to the preferredContentSize any CGSize it is reduced to max height and width.

Device Orientation (max width, max height):

iPhone 5S Portrait (272, 441.5)
iPhone 5S Landscape (520, 205.5)

iPhone 6 Portrait (327, 540.5)
iPhone 6 Landscape (586, 260.5)

iPhone 6 Plus Portrait (362, 610)
iPhone 6 Plus Landscape (585, 288)

iPad Mini Portrait (535, 853)
iPad Mini Landscape (535, 597)

iPad Portrait (711, 985)
iPad Landscape (967, 729)

How did I get these values?

@IBOutlet weak var sizerView: UIView!

inside viewDidLoad:

preferredContentSize = CGSizeMake(0, 2000)
dispatch_after(1, dispatch_get_main_queue(), { //it needs time to render itself
    label.text = NSStringFromCGSize(self.sizerView.bounds.size) //here you have MAX VALUES
}

To get the max height of the widgets active display mode, do this in your UIViewController:

let context = self.extensionContext
if let context = context{
    let height = context.widgetMaximumSize(for: context.widgetActiveDisplayMode).height
}

To get the max height of expanded and compact individually regardless of the current display mode, do this:

var context = self.extensionContext
if let context = context{
    let compactHeight = context.widgetMaximumSize(for: .compact).height
    let expandedHeight = context.widgetMaximumSize(for: .expanded).height
}

It seems, that iOS is adding an UIView-Encapsulated-Layout-Height constraint to your own constraints:

(
    "<NSLayoutConstraint:0x610000280640 V:[_UILayoutGuide:0x7f92d0513810]-(500)-[UILabel:0x7f92d040cb20'Hello World']>",
    "<NSLayoutConstraint:0x610000280690 V:[UILabel:0x7f92d040cb20'Hello World']-(500)-[_UILayoutGuide:0x7f92d0515100]>",
    "<_UILayoutSupportConstraint:0x6100002a2f40 V:[_UILayoutGuide:0x7f92d0513810(0)]>",
    "<_UILayoutSupportConstraint:0x6100002a2ee0 V:|-(0)-[_UILayoutGuide:0x7f92d0513810]   (Names: '|':UIView:0x7f92d040c810 )>",
    "<_UILayoutSupportConstraint:0x6100002a3000 V:[_UILayoutGuide:0x7f92d0515100(0)]>",
    "<_UILayoutSupportConstraint:0x6100002a2fa0 _UILayoutGuide:0x7f92d0515100.bottom == UIView:0x7f92d040c810.bottom>",
    "<NSLayoutConstraint:0x60800009e780 'UIView-Encapsulated-Layout-Height' V:[UIView:0x7f92d040c810(628)]>"
)

This constraint forces the widget to have the maximum height. You can get it's value like this:

- (void)widgetPerformUpdateWithCompletionHandler:(void (^)(NCUpdateResult))completionHandler {

    for (NSLayoutConstraint *constraint in self.view.constraints) {
        if ([constraint.identifier isEqualToString:@"UIView-Encapsulated-Layout-Height"]) {
            NSLog(@"Height: %@", @(constraint.constant));
        }
    }

    completionHandler(NCUpdateResultNewData);
}