设计一个提供自己的模态 UI 的 iOS 静态库的最简单方法是什么?

发布于 2024-11-18 18:21:00 字数 944 浏览 1 评论 0原文

我正在设计一个 iOS 静态库,供其他开发人员使用。该库需要提供自己的模式 UI。我正在寻找最简单的方法来设计应用程序和该库之间的接口来完成此任务。我只需要支持iOS 4.0及以上版本。

粗略架构

我的静态库有一个非常简单的 API,只有一个类。应用程序的 AppDelegate 实例化这一类并将其自身设置为委托,以便它可以接收通知。当应用程序希望库显示其 UI 时,它会调用一个方法,然后当库完成其工作时,它会通过委托协议的方法之一发送通知。

我可以看到两种方法来实现这一目标。

选项 1

当应用程序希望库显示其 UI 时,AppDelegate 传入 self.window,库设置其自己的根视图控制器,从而有效地获得 UI 的完全所有权。当 UI 完成时,它会通知 AppDelegate,然后 AppDelegate 在窗口上设置自己的根视图控制器,收回 UI 的所有权。

选项 2

该库公开了一个视图控制器,应用程序可以将其推送到它喜欢的任何视图堆栈上。当库通知 UI 已完成时,应用程序还负责删除视图控制器。

问题

对于选项 1,在运行应用程序期间更改根视图控制器可能会出现问题。使用选项 2,提供可以在任意上下文中工作的视图控制器(作为全窗口视图控制器、作为 UINavigationController 的子视图等)可能会出现问题。

这两个选项的另一个问题是 AppDelegate 可能收到的其他 UIApplicationDelegate 通知,例如 applicationWillResignActive: 和 applicationDidBecomeActive:。库可能需要处理类似的通知才能正确维护其 UI。当其 UI 处于活动状态时,AppDelegate 是否必须将其中每一个传递给库?

还有我没有想到的更好的选择3吗?

I'm designing an iOS static library that will be used by other developers. This library needs to provide its own modal UI. I'm looking for the simplest way to design the interface between the application and this library to accomplish this. I only need to support iOS 4.0 and above.

Rough architecture

My static library has a very simple API with one class. The application's AppDelegate instantiates this one class and sets itself as a delegate so it can receive notifications. When the application wants the library to show its UI it calls a single method, and then when the library is done with its work it sends a notification through one of the delegate protocol's methods.

I can see two ways to accomplish this.

Option 1

When the application wants the library to show its UI, The AppDelegate passes in self.window, and the library sets its own root view controller, effectively taking full ownership of the UI. When the UI is finished, it notifies the AppDelegate, which then sets its own root view controller on the window, taking back ownership of the UI.

Option 2

The library exposes a view controller, which the app can push onto whatever view stack it likes. The app is also responsible for removing the view controller when the library notifies it that the UI is finished.

Issues

With option 1, there may be problems changing root view controllers while in the middle of running an application. With option 2, there may be problems providing a view controller that can work in an arbitrary context (as a full-window view controller, as a sub-view of a UINavigationController, etc).

Another problem with both options is the other UIApplicationDelegate notifications that the AppDelegate may receive, such as applicationWillResignActive: and applicationDidBecomeActive:. The library may need to handle notifications like that to properly maintain its UI. Must the AppDelegate pass each of these to the library when its UI is active?

Is there a better option 3 that I haven't thought of?

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

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

发布评论

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

评论(3

荒岛晴空 2024-11-25 18:21:00

您是否考虑过设计 API 来接受 UIViewController

- (void)presentFromViewController:(UIViewController *)presentingViewController
                         animated:(BOOL)animated
{
    [presentingViewController presentModalViewController:myViewController
                                                animated:animated];
}

这样,您的库就可以完全控制模态 UI 的呈现方式,并且还可以调用 -dismissViewControllerAnimated: 本身而不是依靠代表来这样做。

不必费心传递 -applicationWillResignActive: 等。只需在库类中注册底层通知 UIApplicationWillResignActiveNotification 等即可。

Have you considered designing your API to accept a UIViewController:

- (void)presentFromViewController:(UIViewController *)presentingViewController
                         animated:(BOOL)animated
{
    [presentingViewController presentModalViewController:myViewController
                                                animated:animated];
}

That way, your library has full control over how the modal UI is presented, and can also call -dismissViewControllerAnimated: itself rather than relying on the delegate to do so.

Don't bother to pass around -applicationWillResignActive: etc. Simply register for the underlying notifications UIApplicationWillResignActiveNotification etc. in your library class.

心凉 2024-11-25 18:21:00

我是这样做的:
在静态库中创建 UIViewController 以及以编程方式需要的所有内容视图(因为您无法轻松地在 iOS 上制作框架,因此无法轻松捆绑资源):

UIViewController *controller = [[[UIViewController alloc] initWithNibName: nil bundle: nil] autorelease];
UIView *containerView = [[[UIView alloc] initWithFrame: [UIScreen mainScreen].applicationFrame] autorelease];
containerView.backgroundColor = [UIColor darkGrayColor];

UIWebView *webView = [[[UIWebView alloc] initWithFrame: containerView.bounds] autorelease];
webView.delegate = self;

// ... some other code to setup custom things

[containerView addSubview: webView];

// ... some other code to setup custom things, spinner etc.

然后使用以下命令显示它

[[UIApplication sharedApplication].keyWindow.rootViewController presentModalViewController: myViewController animated: YES];

这是从工作静态库剪切并粘贴的它已嵌入到两个不同的 iOS 应用程序中,并且似乎在这两个应用程序中都运行良好。可能有一些边缘情况没有涵盖,但我还没有遇到:)

Here's how I do it:
In your static library create your UIViewController and all the content views that you need programmatically (since you can't easily make Frameworks on iOS you can't easily bundle resources):

UIViewController *controller = [[[UIViewController alloc] initWithNibName: nil bundle: nil] autorelease];
UIView *containerView = [[[UIView alloc] initWithFrame: [UIScreen mainScreen].applicationFrame] autorelease];
containerView.backgroundColor = [UIColor darkGrayColor];

UIWebView *webView = [[[UIWebView alloc] initWithFrame: containerView.bounds] autorelease];
webView.delegate = self;

// ... some other code to setup custom things

[containerView addSubview: webView];

// ... some other code to setup custom things, spinner etc.

then display it with

[[UIApplication sharedApplication].keyWindow.rootViewController presentModalViewController: myViewController animated: YES];

This is cut and pasted from a working static library that's been embedded into two different iOS applications and seems to work well in both. There may be edge cases that this doesn't cover, but I haven't hit them yet :)

各自安好 2024-11-25 18:21:00

使用块而不是委托。完成后,您的视图应该调用存储在属性中的提供的 dismissBlock,并且调用者可以从该块执行其需要执行的操作。有需要传回的数据吗?根据需要,将其作为块的参数或将其放入可从视图控制器访问的对象的属性中。

如果您有需要存储以响应事件的状态,请记录该状态并提供一种将该信息保存到某些数据中并从数据块恢复 UI 的方法。调用者可以按照自己的意愿进行处理。

UI 的精确显示方式应由客户端应用程序决定,但通过规定 UI 确实必须以模态方式显示,您就可以充分限制其环境,从而不必过多担心主机环境。

Use blocks instead of a delegate. Your view should call a provided dismissBlock stored in a property when it's done, and the caller can do what it needs to do from that block. Have data you need to pass back? Make it an argument of the block or put it in a property of an object accessible from your view controller, as appropriate.

If you have state that needs storing in response to an event, document that and provide a way to save off that info into some data and restore the UI from a block of data. The caller can handle that as they wish.

Precisely how the UI is displayed modally should be up to the client application, but by providing that the UI must indeed be displayed modally, you limit its environment enough that you shouldn't have to worry too much about the host environment.

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