Auto Layout vs Frame Sizes
Asked Answered
B

4

10

So I'm slightly embarrassed to ask this because it seems so rudimentary but ever since beginning iOS development (about a year of self/internet teaching), when not using storyboards, I have relied heavily on frame sizes and used auto layout very sparingly. In Objective C I find myself in situation where I need to use Auto Layout more often but with Swift I can animate a frame's x and y origins, its center, etc... I have never run into a situation where I could not accomplish what I want with frame sizes and pixel locations alone and I have done some fairly complex view work. My question is, what are the benefits of using Auto Layout rather than frame sizes and pixel locations? I would hate to miss out on some great performance benefits due to ignorance and habit. Thanks so much!

Branum answered 22/11, 2015 at 0:13 Comment(4)
If one can achieve expected UI without auto layout, he/she should go for Frame based layout. Auto layout relies on calculation of constraints to generate the frame. More constraints more calculations.Stine
@Stine is entirely right. It's not a "this vs that" issue, you've got to realize when you need auto layout vs when you can easily get away without it. Auto Layout gets expensive fast. It's a powerful tool but it causes problems if you use it wrongNeckline
The answer to this question is available here, and being new to iOS development, I personally think it answers the question better than the answers on this page.Deste
@BenButterworth Your link is to this very question. You probably meant some other link.Bull
C
19

tl;dr Learn how to use Auto Layout – it's a huge time saver for real-world apps!

Long answer:

Finally it is up to you if you want to use features like Auto Layout or Size Classes that Apple provides. The main benefit of those is not really performance in terms of UI rendering in the final product. It is the time you need to invest into thinking about all edge cases if you plan to develop an app that works on different screen sizes and orientations.

Let's say you want to do all the work you need to do to support iPhone 4/4s screen size, iPhone 5/5s screen size, iPhone 6/6s (Plus) screen size and iPad screen size plus Portrait and Landscape modes for all the above screen sizes yourself (here's a good overview): Well, there's nothing wrong with it, just go for it. You would then, of course, need to test things very carefully and also always keep this list up to date – in each app you are using your own solution. If that's for you, do it.

But most people want to get their ideas out without struggling with things like different screen sizes too much. You could of course extract your own logic from one app to use it in all of your apps, and that's exactly what Auto Layout and Screen Sizes are about. Simply put, Apple has done all of the work to make your frame-setting work in different screens for you. You just need to use their new vocabulary (Constraints) to make it work.

In other words: It's an abstraction layer on top of handling with the screen rendering logic directly. If you don't like it, let it go. But if you're planning to do some serious apps that should work on different iPhone/iPad generations and also plan to maintain those however, then, please, learn how to do things with Auto Layout and Size Classes. It will save you and all future maintainers quite some time in development.

A good starting point is the docs. Or a tutorial like this one on raywenderlich.com.

Apple says the following about this difficulty themselves (in the docs linked above):

In many ways, programmatically defining a view’s frame provides the most flexibility and power. When a change occurs, you can literally make any change you want. Yet because you must also manage all the changes yourself, laying out a simple user interface requires a considerable amount of effort to design, debug, and maintain. Creating a truly adaptive user interface increases the difficulty by an order of magnitude.

BTW: There's no difference at all in using Auto Layouts or Frames regarding the programming language: Both Swift and Objective-C support both ways perfectly well. It seems you just didn't find out how to change frames in Obj-C yet. ;)

One more thing: You also don't need to use Storyboards to use Auto Layout. You can use Auto Layout from code. See the docs here. There's even plenty of frameworks trying to make this easier (the original APIs from Apple tend to be not very pretty in many terms), I can recommend SnapKit.

Chromatism answered 22/11, 2015 at 21:33 Comment(5)
I was mostly interested if there was any difference in the UI rendering and I may not have made that clear. The question was with regard to performance benefits. You did make that clear for me so thank you! There is, however, a difference in the way the languages treat frames if I'm not mistaken. I have yet to find a way to set a frame's x or y original independently in objective c without having to explicitly create the whole frame again. Swift acts differently or is at least more obvious about it. Also, I have written constraints programmatically often. I just use the alternative more often.Branum
I am more than likely going to make it my routine to use auto layout from here on out though, if only because it seems like the overwhelming majority of developers embrace it and I have never had a hassle with it. I've just never minded frame sizes. Thanks again for the insight!Branum
You're welcome. Glad to hear I could help. And yes, in Objective-C you can only assign a whole CGRect object (the whole frame) which was the way to go until Swift introduced a better way by implementing CGRect as a Swift Struct structure. Swift Structs are not compatible with Objective-C though, so they are still integrated the old way there (C structs, I think) which is why it's still more of a hassle to change a single value in Obj-C compared to Swift.Chromatism
You can construct a UI without auto layout to work on any device size. If you set a view’s frame programmatically using the width of the super view, there is no extra work to get a UI looking good on an iPhone 7 or 4. Auto layout comes into use when the view changes while the app is running, like changing device orientation or when a phone call comes in and the status bar doubles its height. Truth is, Apple’s documentation, especially when it comes to programmatic work, is terse and so getting auto layout to work exactly as you want it requires a lot of trial and error and internet digging.Stapes
I think this guy is on the money. The performance benefit might not be in rendering but its guaranteed in productivity, maintenance, future-proffing etc. Also, in ios 12 autolayout got a lot better and more efficient.Prejudice
C
3

Relying on frame sizes equals calculating the sizes. When using percentage or proportions, it could work on different phone models, but still might look sometimes strange on few resolutions. Then you would add another conditional statement because e.g. on iPhone 4s you would want a little bit different layout. Your code is more and more complicated and could lead to the place where any change is a risk. It is doable, but why reinventing the wheel?

Tools like basic constraints replace sometimes really huge logic blocks for layouts. Logic to compress one label when second one is extending means few ifs. Think about 10 labels. With addition of size classes, enabling/disabling constraints, compression & hugging, auto layout has become irreplaceable for me and I would suggest to take a look at it since most of companies are using it, if not in storyboards, then in xibs or in code, but with auto layout.

Caprine answered 22/11, 2015 at 1:4 Comment(0)
C
0

Auto Layout was developed to allow programmers to write programs on iOS for screens of and views of arbitrary sizes. Previously, for the first four generations of the iPhone, iOS developers could target their designs to one screen size, but as recent history has shown Apple is open to making hardware of different shapes and sizes. Auto layout provides a convenient way of creating UI that can adapt to different screen and view dimensions. Can one develop UI without auto layout that will take advantage of different view dimensions? Yes. But to make truly resizable views with multiple UI elements, generally programmers have to resort to sizing an element situating relative to other UI element, which have themselves had to have been sized and situated. For example:

NSString *nameString = [NSString stringWithFormat:@"%@", self.name];
        CGSize nameSize = [nameString sizeWithAttributes:attribs];

        [nameString drawAtPoint:CGPointMake(self.bounds.size.width*0.5-nameSize.width*0.5, IMAGE_INSET+4*CONTENT_BUFFER(self.bounds.size.height)+facePicHeight) withAttributes:attribs];

        questionFont = [UIFont systemFontOfSize:self.bounds.size.height*0.025];
        attribs = @{NSFontAttributeName: questionFont, NSParagraphStyleAttributeName:paragraphStyle};

        NSString *maleString = [NSString stringWithFormat:@"%@", self.male];
        CGSize maleSize = [maleString sizeWithAttributes:attribs];
        [maleString drawAtPoint:CGPointMake(self.bounds.size.width*0.5-maleSize.width*0.5,
                                            IMAGE_INSET+5*CONTENT_BUFFER(self.bounds.size.height)+facePicHeight+nameSize.height) withAttributes:attribs];

        NSString *femaleString = [NSString stringWithFormat:@"%@", self.female];
        CGSize femaleSize = [femaleString sizeWithAttributes:attribs];
        [femaleString drawAtPoint:CGPointMake(self.bounds.size.width*0.5-femaleSize.width*0.5,
                                              IMAGE_INSET+6*CONTENT_BUFFER(self.bounds.size.height)+facePicHeight+nameSize.height+maleSize.height) withAttributes:attribs];

        NSString *babyString = [NSString stringWithFormat:@"%@", self.baby];
        CGSize babySize = [babyString sizeWithAttributes:attribs];
        [babyString drawInRect:CGRectMake(IMAGE_INSET+CONTENT_BUFFER(self.bounds.size.height), IMAGE_INSET+7*CONTENT_BUFFER(self.bounds.size.height)+facePicHeight+nameSize.height+maleSize.height+femaleSize.height, self.bounds.size.width-2.0*(IMAGE_INSET+CONTENT_BUFFER(self.bounds.size.height)), babySize.height) withAttributes:attribs];

The whole thing can get a bit clunky. Obviously some views are simpler than others, but if you have complicated view that you want to support multitasking and localization and other things that are going to affect the layout of your UI it is generally much easier to use auto layout.

Coddle answered 22/11, 2015 at 1:2 Comment(0)
A
0

iOS Frame-based vs AutoLayout

translatesAutoresizingMaskIntoConstraints - bridge between Frame-based and AutoLayout.

  • By default true - for programmatically created view
  • By default false - for IB created view
  • true - under the hood creates a set of implicit constraints based on view's frame and autoresizing mask
  • false - allows you to apply your own constraints in AutoLayout and prevent conflict(implicit and explicit constraints)

Frame-based - positioning via (x, y, with, height). There are a lot of calculations and variants in multi-screen situation

let customView = CustomView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))

Enable in Interface Builder: Size Inspector -> Layout -> Inferred (Autoresizing Mask)

Autoresizing Masks is a view's resizing behaviour based on parent view. Adds some dynamism which based on:

  • springs - is a flexible dimension
  • struts - is a constant dimenssion
  • IB allows you to use struts for external properties, and springs for internal properties
  • A programmatic way allow you to use springs(.flexibleWidth, .flexibleHeight, .flexibleLeftMargin, .flexibleTopMargin, .flexibleRightMargin, .flexibleBottomMargin ). But if mask is skipped - it means use appropriate struts instead of it
view.autoresizingMask = [.flexibleRightMargin]

Simple example of Frame-based autoresizing:

let viewA = UIView(frame: CGRect(origin: CGPoint(x: 0, y: 100), size: CGSize(width: 150, height: 300)))
viewA.backgroundColor = .magenta
viewA.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(viewA)

let viewB = UIView(frame: CGRect(origin: CGPoint(x: 72, y: 22), size: CGSize(width: 20, height: 40)))
viewB.backgroundColor = .cyan
viewB.translatesAutoresizingMaskIntoConstraints = false

//set autoresizing mask
viewB.autoresizingMask = [.flexibleWidth] //<- comment it to show first screen

viewA.addSubview(viewB)

viewA.frame.size = CGSize(width: 300, height: viewA.frame.height)

First screen dosn't use autoresizingMask, and the ssecond one usse it as sshowed in the code

Auto Layout - uses constraints to set relationships between views. View's frame is calculated dynamically based on constraints. It adds extra step which theoretically has an impact on performance but on the other hand is more friendly

let customView = CustomView()
customView.translatesAutoresizingMaskIntoConstraints = false
customView.widthAnchor.constraint(equalToConstant: 50).isActive = true
...

AutoLayout engine

measurement(subView->superView) -> layout(superView->subView)


By default AutoLayout is disabled in InterfaceBuilder and enabled for programmatically created view.

  • Enable AutoLayout in code view.translatesAutoresizingMaskIntoConstraints = false
  • Enable AutoLayout in InterfaceBuilder - add constraint
view.translatesAutoresizingMaskIntoConstraints = false // false for autolayout

view.topAnchor.constraint(equalTo: parentView.topAnchor, constant: 16).isActive = true

AutoLayout is used in UITableView with UITableView.automaticDimension in func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat which allow you to don't care of view height.

Also set constraint when view was already added into print view

parentView.addSubview(view)
view.topAnchor.constraint(equalTo: self.topAnchor, constant: 16).isActive = true

or you get

Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to activate constraint with anchors <> because they have no common ancestor. Does the constraint or its anchors reference items in different view hierarchies? That's illegal.'
Antimicrobial answered 3/12, 2021 at 11:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.