在笔尖或代码中deviseiPhone界面?

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

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

另一方面,在大型项目中,Interface Builder成为维护的麻烦。

任何build议将不胜感激。

我曾经强烈反对在我自己的项目中使用Interface Builder。 这是由于一些因素。 当iPhone SDK重新开始testing时(2008年3月左右),我开始首先使用Xcode工具,由于我不是来自Mac Cocoa背景,所以对于使用它有点不熟悉。 这并不是我最初拒绝使用iPhone进行iPhone开发的主要因素,尽pipe在最初的iPhone SDKtesting版中用于iPhone开发的界面生成器确实很糟糕,使用起来很麻烦。

不过,这个故事与今天的iPhone SDK有很大的不同。 虽然仍然有一些令人讨厌的IB错误,但是我对使用Interface Builder的态度已经做了近乎完整的180度。 多数情况下,在我的项目中使用Interface Builder是个好主意。 这是一个很好的工具,你应该利用它。

现在,请不要误解我的意思 – 我仍然坚信,你应该能够使用代码来实现你在Interface Builder中做的任何事情 ,我认为能够做到这一点是非常宝贵的。 不要使用Interface Builder作为拐杖 – 最终只会伤害自己(以及您的生产力或产品质量)。 虽然IB的拖放细节对于你需要做的90%是很好的,但是当你有一些自定义的实现只能在代码中完成的时候,你可能希望你遵循或者感激遵循这个build议。 我足够幸运地憎恨IB长达足够的时间,以至于我自学了如何在代码中完成所有事情,然后将这些知识应用到IB。

编辑:
为了解决NIB与代码之间缺乏可重用性(可视化的或真实的),您将不会实现在Interface Builder中大量重用的内容。 你不能真正在IB中做一个自定义的控件或视图,所以这是排除的,在大多数情况下,你将实现一个视图控制器的子类,是为了解决特定的目的而构build的。 您当然应该始终努力使您的代码和相关资源尽可能重用。 这可能包括devise注意事项,以确保不会不必要地重复非常相似的视图控制器子类。

使用构build器可以让你自由地使用代码,而不需要维护更好的代码。

由IB构build的布局确实需要一些维护,但它是一个标准工具,具有自己的文档和自己的在线支持(论坛,列表等)。 如果有人需要跳进你的代码,你几乎可以保证他们有经验的IB,但不一定是你的布局build设的特定风格。

这取决于你的喜好。

我宁愿写在代码中。

  1. 我重新使用了代码。
  2. 使用XIB / NIB通常会破坏一个定义规则(如果您正在进行任何定制)。
  3. XIB / NIB维护通常比较单调乏味,容易出错(ODR)。 我真的不喜欢维护每个button的button样式(例如)。
  4. 循环引用更可能。
  5. 代码/对象/ ib实例往往不太可重用/模块化。 虽然我是避免可以做任何事情的用户界面的types。
  6. 延迟/不明确的初始化顺序使得客户端处于非常可怕的状态,他们绝不能假定对象已经准备好使用或完全初始化(除非您更愿意维护这些检查,这是浪费时间的好办法)。
  7. 如果performance很重要,猜猜哪个更快?
  8. 资源pipe理vs连接器…严重的是,我已经写了子程序和testing来validation笔尖中存在的笔尖。

IB非常适合原型devise和浏览对象的function和外观(我不是一个平面devise师),但是如果您有任何维护或重用它的意图,那么只要原型存在,就把它写在代码中是最简单的。

我的build议是:编写高度可重用和稳定的代码库,并使用IB主要用于原型和一次性。


对策:

Sbrocket:我很好奇你为什么断言由于使用NIB而导致循环引用更可能发生。

Hi Sbrocket:我会从开始说我从Project Builder开始使用Interface Builder(Xcode的前身)。

缺乏可靠的结构化所有权,身份和初始化。 我不希望 ivars成为IB连接,因为它使得很多类在当前上下文之外难以使用,换句话说,它把代码和资源联系起来(更经常的是理想状态)。 由于您不能在IB中定义初始化顺序或定义初始化程序或附加初始化参数,因此必须使对象相互了解,从而创build循环依赖项和引用。

Sbrocket:或者当为了确保对象被初始化和连接而相对容易(或者实际上在很多情况下是自动的)时,为什么懒惰的初始化(假设其实就是你所指的)是如此的可怕。

回复:可怕的是我不是在谈懒惰的初始化。 我在谈论延迟和模糊的初始化顺序。

笔尖初始化是半有序的。 实际的顺序/过程可能会有所不同,而且在可重复使用的内省程序中不能可靠地使用它……再次,你最终会写太多的代码,这些代码很脆弱,不可能重用,永远无法保证可以预测,而且必须总是validation状态(循环依赖的另一个条目)。 如果不是一次性执行,为什么还要麻烦呢?

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

编写一致的程序要容易得多,初始化程序在上下文中确定了有效性,然后实现可以知道(如果初始化)对象通常准备使用。 特殊情况的复杂性被最小化。 许多这样的devise随着程序复杂性的增加而破裂,而图书馆编写者为了保持齿轮的移动而在“保护措施”层上添加层,穿线对于这样的海森堡来说是一个很好的入口。 不必要的歧义在可重复使用的生产级别代码中是不受欢迎的; 人类不应该交叉引用一个程序的所有特殊情况,关于定义的行为和特殊情况的复杂性只会传播或被忽略(假设它们被正确地跟踪和logging,这比从一开始就写得更好)。 我想我们都可以同意避免麻烦的接口和实现。

Sbrocket:我也有兴趣看到一些显示NIB加载速度较慢的硬数据 – 当然,一开始想这似乎是有意义的,但是如果不进行一些严格的testing,我们总是会对性能瓶颈做出如此糟糕的预测。

我从来没有(明确)说,这是慢的:)

好吧,对于我来说,NIB的非归档是一个非常缓慢的过程,尽pipe我们对慢速和非归档时间的想法可能会有很大的变化。

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

既然你有明确的答案,我会提醒你,你有衡量performance所需的所有工具。

请记住,性能分析和增强是学习的

接口生成器对于一定程度的复杂性是很好的。 对于或多或less复杂的事情,我宁愿用代码来做。

如果你有一个接口不能以多种方式使用,有几个但不是很多的元素,并不需要任何棘手的布局,比IB是伟大的。

从长远来看,我几乎从不使用IB。 这与我个人喜好的项目的性质一样多。 肯定有一些接口我会直接去IB,但是我不需要在一段时间内创build一个接口。