iPhone UIView - 当 UIView 的大小事先未知时,UIViewController 应如何处理 UIView 的大小?

发布于 2024-09-18 18:19:37 字数 401 浏览 9 评论 0原文

(iPhone新手问题)

我已经子类化了UIViewControllerUIView,并为视图创建了InitWithFrame。我的自定义控制器在其 loadView 函数中使用它来按帧初始化其视图。

我计划在不同的地方使用控制器并在我的代码中查看。有时在导航控制器、工具栏、两者或两者都没有等下。这意味着在控制器的 loadView 中创建视图的代码理想情况下应该知道以什么大小创建视图。

如何避免针对不同情况对这些大小进行硬编码?有没有办法构建周围的控制器(导航栏等),然后计算出可视框架的大小,然后以某种方式创建我的控制器并使用此框架大小初始化我的自定义视图?

如果我的设计不正确,任何提示都可能会有很大帮助......谢谢!

(IPhone newbie question)

I've subclassed a UIViewController and a UIView, and created a InitWithFrame for the view. My custom controller uses this to initialize its view, by frame, in its loadView function.

I plan to use the controller and view in my code at different places. At times under a navigation controller, toolbar, both, neither etc. This means that the code creating the view in loadView of the controller, should ideally know in what size to create the view.

How do I avoid hard coding these sizes for the different cases? Is there a way to build the surrounding controllers (navigation bar, etc.), then figure out the size of the viewable frame, and somehow only then create my controller and initialize my custom view using this frame size?

If my design is incorrect, any tip could be of great assistance... Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

千里故人稀 2024-09-25 18:19:37

对于初始视图大小,您可能会对 [UIScreen应用程序框架]。返回的矩形说明状态栏和界面方向。当您的控制器在导航控制器或其他更改可用屏幕空间的包装器中使用时,我认为视图会自动调整大小(通过 UIViewController 魔术),因此您无需执行任何操作(除了设置宽松的 autoresizingMask)。

For the initial vew size you might be interested in [UIScreen applicationFrame]. Returned rectangle accounts for the status bar and interface orientation. When your controller is used inside a navigation controller or other wrapper that changes the available screen space, I think the view gets resized automatically (through UIViewController magic), so there’s nothing you have to do (apart from setting a permissive autoresizingMask).

泛滥成性 2024-09-25 18:19:37

以下是我解决类似问题的方法:我想要:

  • 创建可重用的、独立的“小部件模块类”,实现从多个 UIKit 组件(以及其他嵌套小部件模块类!)构建的复杂视图。这些小部件类的更高级别的客户类不关心小部件内部的 UILabel 是什么、UIImageView 是什么,客户只关心“显示分数”或“显示球队徽标”。

  • 在小部件模块类中,使用接口构建器为小部件和连接插座布置 UI

  • 对于小部件的高级客户,我希望能够将小部件的框架放置在界面构建器中客户的视图内,而不必为 IB 等设计自定义插件。

这些小部件不是顶级控制器:因此它们作为子类是没有意义的UIViewController 的。 Apple 还建议不要在可见屏幕上同时显示多个 VC。另外,还有很多建议和意见,比如“MVC!MVC!你必须将视图和控件分开!MVC!”人们强烈反对子类化 UIView 或将应用程序逻辑放置在 UIView 类中。

但我还是决定这么做(UIView 的子类)。我已经来过几次了(但对 iPhone SDK/UIKit 来说还是相当新的),而且我对丑陋的设计非常敏感,这可能会导致问题,坦白说我没有看到问题在这里继承 UIView 。事实上,使可重用小部件成为 UIView 的子类而不是基于 UIViewController 有很多优点:

  • 您可以将小部件类的直接实例放置在客户视图的界面构建器布局中,以及小部件视图的 UIView 框架中当从 xib 加载客户类时,将会正确初始化。对我来说,这比在客户中放置“占位符视图”,然后以编程方式实例化小部件模块,并将小部件的框架设置为占位符的框架,然后将占位符视图交换为小部件的视图要干净得多。

  • 您可以创建一个干净简单的 xib 文件来在界面构建器中布置小部件的组件。 nib 文件包含另一个 UIView,其中布局了所有 GUI,然后在小部件的 awakeFromNib: 函数中,此 nib 视图作为子视图添加到小部件本身。如果有必要,任何帧大小调整都可以在此处处理,完全在小部件代码内进行。

  • 小部件通过在其自己的 awakeFromNib 方法中使用 NSBundle 的 loadNibNamed:owner:options 方法来自行初始化其用户界面,因此将小部件集成到客户类中是干净的:只需将 UIView 放入 IB 中的客户视图中,更改UIView 的类为 MyWidgetView,并在客户的 init 或 viewDidLoad 中使用您自己编写的小部件的 API 设置小部件显示中的任何默认值(setScore: setTeamImage: 等)

在我看来,以这种方式子类化 UIView 来制作可重用的“小部件”之间没有什么区别。使用 UIViewController。在这两种情况下,小部件的 .h 文件都充满了成员、出口、操作声明和特殊 API 声明。在这两种情况下,小部件的 .m 文件都充满了操作实现和特殊 API 实现。并且视图与控件是分离的——视图位于 xib 文件中!

因此,总而言之,这就是我为打包复杂的可重用视图小部件所做的工作:

  • 使小部件类成为 UIView 的子类
  • 在 IB 中直接在应用程序的其他视图中的任意位置实例化小部件。
  • 在 IB 中设计您的小部件的 UI。
  • 在小部件类的 awakeFromNib: 方法中,从 xib 加载小部件的 UI 并执行以下操作
    [self addSubview:theXibView]

  • 像编写 UIViewController 一样编写小部件:outlet、actions、特殊 API

我有兴趣了解其他用于创建可重用小部件的结构系统,以及相对于这种方法的优点。

编辑:忘记提及,如果小部件需要向客户类报告事件,只需使用委托协议,其中客户将小部件的委托设置为 self。

Here is how I'm solving a similar problem: I wanted to:

  • create reusable, self-contained "widget module classes" implementing a complex view built from multiple UIKit components (and other nested widget module classes!). The higher-level customer classes of these widget classes don't care about what's a UILabel, what's a UIImageView internally within the widget, the customers only care about "displaying the score" or "showing the team logo."

  • within a widget module class, lay out the UI for the widget and hookup outlets using interface builder

  • for higher level customers of a widget, I wanted to be able to place the frame of the widget within the view of the customer in interface builder without having to design custom plugins to IB, etc.

These widgets are not top level controllers: so it makes no sense for them to be subclasses of UIViewController. Then also there's the Apple advice not to have more than one VC on a visible screen at a time. Also, there's so much advice and opinion floating around like "MVC! MVC! You must separate your View and your control! MVC!" that people are so strongly discouraged from subclassing UIView or ever placing app logic within a UIView class.

But I decided to do it anyway (subclass UIView). I've been around the block a few times (but fairly new still to the iPhone SDK/UIKit), and I'm very sensitive to design that is ugly, and that can cause problems, and I frankly don't see the problem with subclassing UIView here. In fact there are many advantages to making your reusable widget be a subclass of UIView rather than be UIViewController-based:

  • You can place a direct instance of the widget class in a customer view's interface builder layout, and the widget view's UIView frame will be properly initialized when the customer class is loaded from the xib. This is much cleaner to me than putting a "placeholder view" in the customer, then instantiating the widget module programmatically, and setting the widget's frame to that of the placeholder, and then swapping the placeholder view for the widget's view.

  • You can create a clean and simple xib file to lay out the widget's components in interface builder. The nib file contains another UIView where all of the GUI is laid out, and then in the awakeFromNib: function of the widget, this nib view is added to the widget itself as a subview. Any frame size adjustments can be handled here, entirely within the widget code, if any is necessary.

  • The widget self-initialzes its user interface by using NSBundle's loadNibNamed:owner:options method in its own awakeFromNib method, so integration of the widget into customer classes is clean: just drop a UIView into the customer's view in IB, change the UIView's class to MyWidgetView, and in the customer's init or viewDidLoad set up any defaults in the widget's display using the widget's API that you write yourself (setScore: setTeamImage: etc.)

It seems to me there is very, very little difference between subclassing a UIView in this way to make a reusable "widget", and using a UIViewController. In both cases the .h file of the widget are full of members, outlets, action declarations, and special API declarations. In both cases the .m file of the widget is full of action implementations, and special API implementation. And the view IS separated from the control -- the view is in the xib file!

So, in summary, this is what I do for packaging up complex reusable view widgets:

  • Make the widget class a subclass of UIView
  • Instantiate the widget wherever you want, in other views in your app in IB directly.
  • Design your widget's UI in IB.
  • in the widget class's awakeFromNib: method, load the widget's UI from xib and do
    [self addSubview:theXibView]

  • Code the widget just like you would a UIViewController: outlets, actions, special APIs

I'd be interested in hearing about other structural systems for creating reusable widgets, and what the advantages are over this approach.

edit: forgot to mention, if the widget needs to report events to the customer class, just use a delegate protocol where the customer sets the widget's delegate to self.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文