用笔尖或代码设计iPhone界面?

Jac*_*kin 15 iphone xcode objective-c interface-builder ios

我一直在思考这个问题一段时间了......

一方面,Interface Builder提供了一种非常简单的方法来设计界面,并将元素与代码中的对象连接起来.

另一方面,在较大的项目中,Interface Builder变得很难维护.

任何建议将不胜感激.

Bry*_*nry 17

我曾经非常反对在我自己的项目中使用Interface Builder.这是由于许多因素造成的.当iPhone SDK重新开始测试时(2008年3月左右),我开始使用Xcode工具,因为我不是来自Mac Cocoa背景,所以我对使用它有点不熟悉.这不是我最初拒绝用于iPhone开发的IB的主要因素,但在最初的iPhone SDK beta期间,用于iPhone开发的Interface Builder确实很糟糕,并且使用起来很痛苦.

然而,这个故事与今天的iPhone SDK有很大不同.虽然仍然有一些恼人的IB错误,但我对使用Interface Builder的态度已经接近完成了180˚.我发现,在你的项目中使用Interface Builder通常是个好主意.它现在是一个很棒的工具,你应该利用它.

现在,不要误解我的意思 - 我仍然坚定地认为你应该只使用代码来实现你在Interface Builder中所做的任何事情,我认为能够这样做是非常宝贵的.不要将Interface Builder用作拐杖 - 最终你只会伤害自己(以及你的生产力或产品质量).虽然IB的拖放效果非常适合您需要做的90%,但是当您有自定义实现的东西只能在代码中完成时,您可能希望您遵循或感谢遵循这个建议.我很幸运地厌倦了IB足够长的时间,我自学了如何单独用代码做所有事情,然后将这些知识应用到IB.

编辑:
为了解决NIB与代码缺乏可重用性(感知或真实)的问题......你不会实现在Interface Builder中大量重用的东西.您无法在IB中真正进行自定义控件或视图,因此排除了这种情况,并且在大多数情况下,您将实现为满足特定目的而构建的视图控制器子类.当然,您应该始终努力使您的代码和相关资源尽可能可重用.这可能包括设计注意事项,以确保您不会不必要地复制非常相似的视图控制器子类.

  • +1非常好.理解IB和MVC允许您在需要时做任何您需要的事情,但手工操作界面通常会成为障碍而不是优势.明智之举是根据您的开发人员的经验,您计划实施的非标准功能的数量以及项目本身来决定.即使有所有这些因素,我总是首先在IB中进行,然后如果你不能在IB中进行,那么只能手工完成. (3认同)

jso*_*son 8

使用构建器可以释放您需要维护的代码,并且您需要的维护越少越好.

IB构建的布局确实需要一些维护,但它是一个标准工具,有自己的文档和自己的在线支持(论坛,列表等).如果其他人需要跳转到您的代码,您几乎可以保证他们有IB的经验,但不一定是您的特定布局构建方式.


jus*_*tin 7

这取决于您的偏好.

我更喜欢用代码编写它.

  1. 我重用代码.
  2. 使用XIB/NIB通常会破坏一个定义规则(如果您正在进行任何自定义).
  3. XIB/NIB维护通常更加繁琐且容易出错(ODR).我真的不喜欢为每个按钮维护按钮样式(示例).
  4. 循环引用更有可能.
  5. 代码/对象/ ib实例通常较少可重用/模块化.虽然我是避免可以做任何事情的ui对象的类型.
  6. 延迟/模糊的初始化顺序使客户端处于非常可怕的状态,他们绝不能假定对象已准备好使用或完全初始化(除非您更愿意维护这些检查,这是浪费时间的好方法).
  7. 如果性能很重要,猜哪个更快?
  8. 资源管理与链接器......说真的,我已经编写了子程序和测试来验证nibs在bundle中的存在.

IB非常适合原型设计和浏览对象功能和外观(我不是平面设计师),尽管如果您有任何维护或重用的意图,认为只要原型存在就在代码中编写它是最容易的.

我的建议:编写高度可重用且稳定的代码库,并将IB主要用于原型设计和一次性.


对策:

Sbrocket:我很好奇为什么你断言循环引用更有可能因使用NIB而发生.

您好Sbrocket:我首先要说的是,自项目构建日(Xcode的前身)以来,我已经使用了Interface Builder.

缺乏可靠的结构化所有权,身份和初始化.我不希望 ivars成为IB连接,因为它使许多类难以在"当前上下文"之外使用,换句话说,它将代码与资源联系起来(通常比理想情况更多).由于您无法在IB中定义初始化顺序或定义初始化程序或其他初始化参数,因此必须使对象彼此了解,从而创建循环依赖项和引用.

Sbrocket:或者为什么延迟初始化(假设实际上你指的是什么)在相对容易(或实际上在许多情况下是自动的)确保对象被初始化和连接时是如此可怕.

Re:可怕我不是在谈论延迟初始化.我在谈论延迟和模糊的初始化顺序.

Nib初始化是半有序的.实际的订单/流程可能会有所不同,这在可重复使用的内省程序中无法可靠地使用...再次,您最终会编写太多易碎,无法重复使用的代码,永远无法确保其行为可预测,并且必须总是验证状态(循环依赖的另一个条目).如果它不是一次性实施,为什么要烦恼并发症呢?

这种编程方法是混乱的,实现必须(反过来)准备随时处理任何事情.保护自己免受崩溃是一回事,但是在这种情况下编写防御性的生产级代码......没办法.

编写一致的程序要容易得多,初始化程序确定了上下文中的有效性,然后实现可以知道(如果已初始化)该对象通常准备使用.特殊情况的复杂性最小化.许多这样的设计随着程序复杂性的增加而分崩离析,而图书馆编写者为了保持齿轮移动而在"保护措施"层上增加了层次 - 线程是这种heisenbugs的一个很好的入口.不可取的歧义在可重复使用的生产级代码中是不受欢迎的; 人类不应该交叉引用程序的所有特殊情况,并且有关定义的行为和特殊情况的复杂性只会被传播或被忽略(假设它们被正确地跟踪和记录,这比从一开始就正确编写它更加结合起来).我想我们都同意应该避免使用繁重的接口和实现.

Sbrocket:我也有兴趣看到一些硬数据显示NIB加载速度较慢 - 当然,它看起来似乎有意义,但我们总是如此糟糕地预测性能瓶颈而没有一些硬性测试.

我从未(明确地)说它慢了:)

好吧,严肃地说,NIB unarchiving(对我来说)是一个非常缓慢的过程,尽管我们对缓慢和非归档时代的想法可能会有很大的不同.

示例:我有一个基于文档的应用程序,当文档大小是笔尖大小的几倍时,笔尖加载比文档加载慢几倍.将实现移动到代码使得该过程更快.一旦它出现在代码上并且我控制了初始化顺序,我就删除了多个多线程复杂性(检查点,锁定,竞争条件条目等),这使得文档加载速度更快.

既然您有明确的答案,我会提醒您,您拥有衡量绩效所需的所有工具.

请记住,学习了性能分析和增强功能.