iOS swift framework

iOS – Developing reusable Views in a Swift Framework

What does „Framework“ mean in iOS?

Usually a Framework is a code library, which defines a structure and offers functions to easily solve complex software and coding issues.
Regarding the iOS development the term „framework“ is a little more universal. An iOS Framework can consist of only a single class or be a complex semi application, which just has to be included and configured to produce a launchable app. Basically it is nothing more then a collection of views, controllers and other classes/files that can be shared along an infinite number of projects.

What do we want to achieve?

In this post, I will create an iOS Framework and include it in a test app project. Doing that, I will focus on the reusability of single components of the Framework.

In short, this post includes:

  • Creating a Framework for iOS-Projects with Swift
  • Including the Framework in an app project
  • Creating a resuable, configurable and extendable View that is connected to Class which defines most of its logic
    • + using that view in our test app project
  • Creating reusable classes
    • + Using those classes in our test app project

To achieve all that, I am going to create a simple Framework, containing a basic login View with a View Class, which will define the behavior of the View and offer some attributes for the possibility to configure the appearance of the View. Afterwards, I will include the Framework in a test app.

So let’s get started

Creating the Framework project is quite simple (Xcode Version 7.2.1): In Xcode, go to File -> New -> Project. Now the templates dialog should be visible.
On the left, choose -> Framework & Library, then click on Cocoa Touch Framework and confirm by clicking „Next“

create ios framework

In the following steps, you define the core data of your project as usual. Make sure you have „Swift“ selected as the project’s language.

Creating the View

So after creating the project, we can directly go to creating our first view. Our primary goal is to make this one reusable, i.e. you should be able to switch the View classes and/or Controller classes at any time.

To achieve that, we do not create that view in our Storyboard but in a seperate .xib file.

To do that, right click on your project folder and choose „New File…“

create iOS file

On the left, choose iOS -> User Interface, click „View“ and then „next“

create iOS view

I named the view „MyLoginView“. When you select it in the navigator, you can define the View the same way, you would do it in the Storyboard.

I just went ahead and created a simple login View, containing fields for username and password, a label to display error messages and a login button.

iOS standalone View

If you have never created a View before, you can learn how to do that in the iOS Documentation

Bringing the View to life

So now that we have the View, we have to take care of defining the behavior of the View. To do that, we will create a View Class, which will take care of loading the .xib file and define the behavior of its elements.

So again, click on your project folder in Xcode and select „New File…“. In the dialog, choose iOS -> Source -> Cocoa Touch Class

create iOS Class define iOS Class

To keep things structured, I gave the file the same name as its view „MyLoginView“
For „Subclass of“ choose „UIView“
and make sure the selected language is „Swift“

Now comes the tricky part. We have to make sure that the View gets properly loaded when this class is used on a Storyboard or as subview. Right now it is not possible to simply attach a file to a view so that it gets automatically assigned when dragged into the storyboard. So we need a little setup code.

I will put all the setup code in a seperate method called „setup()“. This will include the following actions (if you don’t want to know the exact behavior, you can scroll down a little and copy the setup() entirely) :

First of all, define two variables

let nibName:String = „MyLoginView“
var view: UIView!

Now, we have to load our login View and add it as subview to make it visible.

Loading the View can be done by the following one-liner:

self.view = UINib(nibName: self.nibName, bundle: NSBundle(forClass:
self.dynamicType)).instantiateWithOwner(self, options: nil)[0]
as! UIView

This line includes three actions:

  • Loading the current project bundle by creating an instance of NSBundle()
  • Loading the View file by creating an instance of UINib()
  • Creating a UIView instance of our View file with instantiateWithOwner()

The result will be assigned to our view variable, that we declared earlier.

So now that we have loaded the View file, we have to add it as subview and make sure it is properly displayed.
We do that by executing:

self.view.frame = bounds
self.view.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
self.addSubview(self.view)

 

So our setup method looks like this:

func setup() {
self.view = UINib(nibName: self.nibName, bundle:
NSBundle(forClass:self.dynamicType)).instantiateWithOwner(self,
options: nil)[0] as! UIView
self.view.frame = bounds
self.view.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
self.addSubview(self.view)
}

The final step is to call that function from the initializer. The UIView class has two initializers that are of our interest. One is for displaying the View inside the editor and the other one is the important one that allows us to show the view inside the real app.

I will use both:

public override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}

So that’s it, basic work is done. It is a good idea to put that part in a Base Class and let your actual views extend that class so you don’t have to copy that code to every View you create.

Now we want to get some actual logic inside that view.
To recall, we wanted to create a simple Login view and a Class that handles most of the basic work.
So to be able to do anything, we have to get references to the elements inside the view.
The first step to doing that, is setting our View Class as the .xib file’s owner

Select the MyLoginView.xib in the Navigator and then select „File’s Owner“ in the Editor area. Now select the Identity inspector tab in the utilities area and type „MyLoginView“ as Class in the Custom Class area.

set-view-owner

 

This allows us to control-drag elements from the View into our View class, so we’re going to do that.
Simply hold the Ctrl key and drag any element to the class, using the assistant editor.

control drag view element define-element-variable

Go ahead and do that with every element you want to control inside the Class. I’m going to do it with the text fields and the error label.
Additionally I will add an action for the click event that will trigger the actual login.

control drag button define button action

 

Abstraction

The purpose of a Framework is to implement most of the required logics so that you don’t have to repeat the code in the actual project, but of course there are always parts that can not be implemented in a Framework. In our case the login is one of those examples. Each app might have a different server or a different method of authenticating so we have to leave the actual login to the app itself.
How you abstract your code is totally up to you. One possibility is the use of @IBInspectable, which allows you to define properties in your View class that can be directly set in the attributes inspector of the editor.

In our case, I am just going to define a public closure attribute, which is a function that will be called as soon as the user hits the login button. So by setting that attribute in the actual app, the developer is able to implement the login process.

So in my MyLoginView class, I will add a public property

public var loginHandler:((username: String, password: String)
-> Void)?

and add the call of that function to the login action

@IBAction func login(sender: UIButton) {

if(loginHandler == nil) {
print(„No loginHandler defined“)
return
}

loginHandler!(
username: usernameTextfield.text!,
password: passwordTextfield.text!)
}

Using the Framework in an app project

For now, we have a solid Framework for a login view and of course we want to use it in an actual app.
To do that, we first have to build the Framework to create an embeddable .framework file. If you expand the „Products“ group
in the Project navigator on the left, you will see that MyFramework.framework is red. That means that it has not yet been built.
To do that, first set the active scheme to „Generic iOS device“ by selecting it in the scheme selector at the top of Xcode.

 

iOS scheme selector

Now press Cmd + B (or Product -> Build in the menu bar)

After a little bit of building, the MyFramework.framework file should appear black, so we are ready to embed it in an actual project.

Right click on the MyFramework.framework file und select „Show in Finder“.
If you step back one folder, you will see that XCode has created two build folders: Debug-iphoneos and Debug-iphonesimulator

As you may have already suggested, the first folder contains the build result for iPhone devices and the other one is for the simulator.

For simplicity, we are just going to embed the debug build for the simulator.

First we have to create our iOS project. I will name mine „MyFrameworkTest“ and use the single view application template to create it.

There are many ways to get a Framework file embedded in an iOS project, but in our case we have to make sure that the binaries are linked and embedded in our test project.
To tell Xcode to do that all at once, click on the Root node in the Project navigator (MyFrameworkTest), select the one Target under „Targets“ and select the „General“ tab.
Now scroll down to „Embedded libraries“ and click on the plus icon.

add embedded binaries

In the dialog, click „Add other“ and navigate to your .framework file

iOS choose framework

In the options dialog, leave everything as it is and click on „Finish“

Using the Framework

Now we want to use the login View, we created in the framework project.
Go to the Main.storyboard and expand the View Controller Scene and the View Controller. This should have one View and we can use that directly as
our login View.

Select that View and select the Identity Inspector tab in the utilities area on the right. In the Custom Class area type „MyLoginView“ (Xcode should autocomplete it) and type „MyFramework“ as module

iOS embed framework View

Congratulations! You just embedded your first logic containing Framework View in your own app.
But there is one thing left to do: Define the actual behavior for the login button click.

For that, i created the public loginHandler attribute in the MyLoginView class. The only thing
we have to do is initialize it with a function in our app.

First, we are going to need a Controller for this view. When you just created the app, Xcode automatically creates a ViewController. If you don’t have it or don’t want to use it you can just create another one by creating a Cocoa Touch Class and letting it extend UIViewController.

In both cases you have to make sure the controller is assigned in your Main.storyboard

iOS assign controller

Now go to the View Controller and control-drag our login View into the controller.

control-drag-login-viewname-login-view

Now we have the instance of our login View in the controller. You will notice that MyLoginView is underlined and Xcode is telling us that it can’t find that class.
That is because we didn’t include it yet in the View Controller. To do that, just add the following line above the class:

import MyFramework

Now we can define the login function in our View Controller:

func login(username: String, password: String) {
let alert = UIAlertController(title: „Login“, message:“I guess i should log in now“, preferredStyle: .Alert)
alert.addAction(UIAlertAction(title: „OK“, style: .Default) { _ in })

self.presentViewController(alert, animated: true){}
}

and assign it as the login handler in the viewDidLoad function

override func viewDidLoad() {
super.viewDidLoad()

loginView.loginHandler = self.login
}

And that’s it! We can go right ahead and run the app.
When clicking the login button, it should show the alert dialog.

iOS app result

You can checkout the projects from our git repository

Framework project

Test project

0 Kommentare

Dein Kommentar

An Diskussion beteiligen?
Hinterlasse uns Deinen Kommentar!

Schreibe einen Kommentar