【问题标题】:Auto Layout vs Frame Sizes自动布局与帧大小
【发布时间】:2016-02-24 07:53:27
【问题描述】:

所以我有点不好意思问这个问题,因为它看起来很初级,但是自从开始 iOS 开发(大约一年的自学/互联网教学)以来,在不使用情节提要时,我严重依赖帧大小并使用自动布局非常谨慎。在 Objective CI 中,我发现自己需要更频繁地使用自动布局,但使用 Swift,我可以为框架的 x 和 y 原点、其中心等设置动画......只需要帧大小和像素位置,我已经完成了一些相当复杂的视图工作。我的问题是,使用自动布局而不是帧大小和像素位置有什么好处?由于无知和习惯,我不想错过一些出色的性能优势。非常感谢!

【问题讨论】:

  • 如果一个人可以在没有自动布局的情况下实现预期的用户界面,他/她应该选择基于框架的布局。自动布局依赖于约束的计算来生成框架。更多约束更多计算。
  • @BangOperator 是完全正确的。这不是“这个与那个”的问题,你必须意识到什么时候你需要自动布局,什么时候你可以轻松摆脱它。自动布局很快就会变得昂贵。这是一个强大的工具,但如果你用错了它会导致问题
  • 这个问题的答案是here,作为iOS开发的新手,我个人认为它比这个页面上的答案更好地回答了这个问题。

标签: ios swift autolayout pixels frames


【解决方案1】:

iOS 基于框架与自动布局

Frame-based - 通过 (x, y, with, height) 定位。多屏情况下有很多计算和变种

Autoresizing Masks 是视图基于父视图的大小调整行为。增加了一些活力

view.autoresizingMask = [.flexibleRightMargin]

Auto Layout - 使用约束来设置视图之间的关系。 View 的 frame 是根据约束动态计算出来的


view.translatesAutoresizingMaskIntoConstraints = false // false for autolayout

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

AutoLayout 在UITableView 中使用,UITableView.automaticDimensionfunc tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat 中使用,这使您无需关心视图高度。

当视图已经添加到打印视图时也设置约束

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

或者你得到

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.'

【讨论】:

    【解决方案2】:

    tl;博士 了解如何使用自动布局——它可以为实际应用节省大量时间!

    长答案:

    最后,您是否要使用 Apple 提供的自动布局或大小类等功能取决于您。这样做的主要好处是不是真正性能在最终产品的 UI 渲染方面。如果您计划开发适用于不同屏幕尺寸和方向的应用程序,那么现在是您需要考虑所有边缘情况的时候了。

    假设您想要完成支持 iPhone 4/4s 屏幕尺寸、iPhone 5/5s 屏幕尺寸、iPhone 6/6s (Plus) 屏幕尺寸和 iPad 屏幕尺寸以及纵向和横向模式所需的所有工作对于上面所有的屏幕尺寸你自己(here 的一个很好的概述):好吧,这没有什么问题,去做吧。然后,您当然需要非常仔细地进行测试,并且始终保持此列表是最新的——在您使用自己的解决方案的每个应用程序中。如果那是给你的,那就去做吧。

    但大多数人都希望在不为不同屏幕尺寸等问题而苦恼的情况下表达自己的想法。您当然可以从一个应用程序中提取自己的逻辑以在所有应用程序中使用它,而这正是自动布局和屏幕尺寸的意义所在。 简而言之,Apple 已经为您完成了所有工作,让您的框架设置在不同的屏幕上工作。您只需要使用他们的新词汇(约束)即可使其发挥作用。

    换句话说:它是一个在直接处理屏幕渲染逻辑之上的抽象层。如果你不喜欢它,就让它过去吧。但是,如果您打算开发一些适用于不同 iPhone/iPad 代的重要应用程序,并且还计划维护这些应用程序,那么,请学习如何使用 Auto Layout 和 Size Classes .这将为您和所有未来的维护者节省相当长的开发时间。

    一个好的起点是docs。或者 raywenderlich.com 上的 this one 之类的教程。

    Apple 自己对这个困难做了以下说明(在上面链接的文档中):

    在许多方面,以编程方式定义视图的框架提供了最大的灵活性和强大的功能。当发生更改时,您可以从字面上进行任何您想要的更改。然而,由于您还必须自己管理所有更改,因此设计一个简单的用户界面需要大量的设计、调试和维护工作。创建一个真正自适应的用户界面会使难度增加一个数量级。

    顺便说一句: 在编程语言方面,使用 Auto Layouts 或 Frames 完全没有区别:Swift 和 Objective-C 都很好地支持这两种方式。看来您只是还没有找到如何在 Obj-C 中更改帧。 ;)

    还有一件事: 您还不需要使用情节提要来使用自动布局。您可以从代码中使用自动布局。请参阅文档here。甚至还有很多 框架 试图让这更容易(Apple 的原始 API 在许多方面往往不是很漂亮),我可以推荐 SnapKit

    【讨论】:

    • 我最感兴趣的是 UI 渲染是否有任何差异,我可能没有说清楚。问题是关于性能优势。你确实让我明白了,所以谢谢你!但是,如果我没记错的话,语言处理框架的方式会有所不同。我还没有找到一种方法来在目标 c 中独立设置框架的 x 或 y 原始值,而不必再次显式创建整个框架。 Swift 的行为不同,或者至少更明显。此外,我经常以编程方式编写约束。我只是更频繁地使用替代方案。
    • 我很可能会从现在开始将使用自动布局作为我的日常工作,如果仅仅是因为看起来绝大多数开发人员都接受它而且我从来没有遇到过麻烦它。我只是从不介意帧大小。再次感谢您的洞察力!
    • 不客气。很高兴听到我能帮上忙。是的,在 Objective-C 中,你只能分配一个完整的 CGRect 对象(整个框架),直到 Swift 通过将 CGRect 实现为 Swift Struct 结构来引入更好的方法之前,这是要走的路。虽然 Swift 结构与 Objective-C 不兼容,所以它们仍然以旧方式集成(我认为是 C 结构),这就是为什么与 Swift 相比,在 Obj-C 中更改单个值仍然更麻烦。
    • 您可以构建一个没有自动布局的 UI 以适用于任何设备尺寸。如果您使用超级视图的宽度以编程方式设置视图的框架,则无需额外工作即可在 iPhone 7 或 4 上使 UI 看起来不错。当应用程序运行时视图发生变化时,自动布局开始使用,例如更改设备方向或来电时状态栏的高度加倍。事实是,Apple 的文档,尤其是在编程工作方面,非常简洁,因此要让自动布局完全按照您的意愿工作,需要大量的反复试验和互联网挖掘。
    • 我认为这家伙很有钱。性能优势可能不在于渲染,而是在生产力、维护、未来配置等方面得到保证。此外,在 ios 12 中,自动布局变得更好、更高效。
    【解决方案3】:

    依赖帧大小等于计算大小。当使用百分比或比例时,它可以在不同的手机型号上工作,但在一些分辨率下有时看起来仍然很奇怪。然后你会添加另一个条件语句,因为例如在 iPhone 4s 上,你会想要一些不同的布局。您的代码越来越复杂,并且可能导致任何更改都有风险的地方。这是可行的,但为什么要重新发明轮子呢?

    诸如基本约束之类的工具有时会取代非常庞大的布局逻辑块。当第二个标签扩展时压缩一个标签的逻辑意味着很少的如果。想想 10 个标签。随着尺寸类的增加,启用/禁用约束,压缩和拥抱,自动布局对我来说变得不可替代,我建议看看它,因为大多数公司都在使用它,如果不是在故事板中,那么在 xibs 或代码,但具有自动布局。

    【讨论】:

      【解决方案4】:

      开发自动布局是为了允许程序员在 iOS 上为任意大小的屏幕和视图编写程序。此前,对于前四代 iPhone,iOS 开发人员可以将他们的设计定位到一个屏幕尺寸,但最近的历史表明,苹果对制造不同形状和尺寸的硬件持开放态度。自动布局提供了一种创建 UI 的便捷方式,可以适应不同的屏幕和视图尺寸。一个人可以开发没有自动布局的 UI 来利用不同的视图尺寸吗?是的。但是要使用多个 UI 元素制作真正可调整大小的视图,通常程序员必须求助于相对于其他 UI 元素调整元素的大小,而其他 UI 元素本身必须已经调整大小和定位。例如:

      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];
      

      整个事情可能会有点笨拙。显然,有些视图比其他视图更简单,但如果您有复杂的视图,想要支持多任务和本地化以及其他会影响 UI 布局的东西,则使用自动布局通常更容易。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-04-08
        • 1970-01-01
        • 1970-01-01
        • 2014-04-29
        • 1970-01-01
        • 2015-09-10
        • 2016-06-04
        相关资源
        最近更新 更多