Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the simplest way to design an iOS static library that provides its own modal UI?

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?

like image 611
Bob Whiteman Avatar asked Jul 06 '11 00:07

Bob Whiteman


People also ask

What is static library in iOS?

Static library - a unit of code linked at compile time, which does not change. However, iOS static libraries are not allowed to contain images/assets (only code).

How do I create a static library in XCode?

Open XCode and start a new project. Under iOS, select Library and “Cocoa Touch Static Library” say it as "staticlibrary". This will create a nice new project for us that builds a . a file.

How do I create a static library in Swift?

Create Static Library ProjectOpen Xcode and select Cocoa Touch Static Library . Give it a name and select Swift as the development language. In our case, we will call it Networking and assume that it will contain the code to communicate with a back end. Press Cmd+N and select Swift file .

Is XCFramework static or dynamic?

An XCFramework can be either static or dynamic and can include headers.


3 Answers

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.

like image 58
hatfinch Avatar answered Oct 17 '22 22:10

hatfinch


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 :)

like image 38
Dad Avatar answered Oct 17 '22 22:10

Dad


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.

like image 1
Jeremy W. Sherman Avatar answered Oct 17 '22 22:10

Jeremy W. Sherman