Creating your first IOS Framework

Source: Internet
Author: User
Tags thoughtbot

Transferred from: Https://robots.thoughtbot.com/creating-your-first-ios-framework

If you've ever tried to create your own IOS framework, you're know that it's not for the faint of heart–managing Dependenci Es and writing tests doesn ' t make it any easier. This tutorial would walk you through creating your first IOS framework from start to finish so the can go out and crea Te your own.

We ' re going to build a framework this exposes a function called that RGBUIColor(red:green:blue) returns a new UIColor created from those values. W E ' ll build it using Swift, with Carthage as our dependency manager. Our framework would be consumable using Carthage, CocoaPods, or git submodules.

Let ' s begin!

Setting up the Xcode Project
    • Select file→new→project.
    • Select ios→framework & Library from the left sidebar and select "Cocoa Touch Library" on the right.
    • Click "Next" and fill in the option prompts. Make sure to select the "Include Unit Tests" check box.

    • select where you ' d like to save your project.
    • uncheck "Create Git repository on My Mac", we'll manually set it up later.
    • click "Create" and the project would open in Xcode.
    • go to  file→save as Workspace  and Save it in the same directory as your Xcode project With the same name. We put the project in a workspace because we are adding our Carthage dependencies as submodules; They must is in a workspace for Xcode to build them.
    • close the Xcode project with  file→close project .
    • open the workspace with  file→open .
    • click on the scheme on the top left of Xcode and select "Manage schemes". We need to mark our scheme as "GKFX"  so that the project can is built with Carthage.
    • locate the "RGB" scheme and check the "Shared" check box and click "Close".

Let's jump over to the terminal.

Initializing Git

First, navigate to the directory of your saved your project in.

    • Run to git init initialize an empty repository.
    • Create a .gitignore which would keep out some pesky Xcode and dependency files we don ' t want to track in Git.

Here's a standard one for Swift projects with a few modifications. We added and .DS_Store removed Fastlane and extra comments.

## OS X Finder.DS_Store## Build generatedbuild/DerivedData## Various settings*.pbxuser!default.pbxuser*.mode1v3!default.mode1v3*.mode2v3!default.mode2v3*.perspectivev3!default.perspectivev3xcuserdata## Other*.xccheckout*.moved-aside*.xcuserstate*.xcscmblueprint## Obj-C/Swift specific*.hmap*.ipa# Swift Package Manager.build/# CarthageCarthage/Build
Adding Carthage and Dependencies
    • Create a file in your project directory named and the Cartfile runtime dependencies to it. We ll add Curry.
github "thoughtbot/Curry"
    • Create a Cartfile.private . It would house private dependencies as our test frameworks. We ' ll use Quick and nimble.
github "Quick/Quick"github "Quick/Nimble"
    • Create a bin/setup script. It's used to give we contributors (andUS) A simple-to set up the project and the dependencies.
mkdir bintouch bin/setupchmod +x bin/setup
    • Open up and bin/setup fill it with:
#!/usr/bin/env shif ! command -v carthage > /dev/null; then  printf ‘Carthage is not installed.\n‘ printf ‘See https://github.com/Carthage/Carthage for install instructions.\n‘ exit 1ficarthage update --platform iOS --use-submodules --no-use-binaries

In this script, we make sure the user have Carthage installed and run its update command to install the IOS dependencies.

We ' re using So, our --use-submodules dependencies is added as Submodules. This allows users and consume our framework outside of Carthage if they want. We use So, our dependencies is built on our --no-use-binaries system.

bin/setupwith created, let's run it so that Carthage would download our dependencies.

    • In the terminal, run bin/setup .

Now we need to set up our project to build and link the new dependencies.

Adding Dependencies to the Workspace

Since Our dependencies is submodules, we need to add them to our workspace.

    • Open up and add each dependency's to the root of the Carthage/Checkouts .xcodeproj workspace. They can dragged from Finder to the navigator of the Xcode project.

When you ' re-done it should look like:

Link Runtime Dependencies
    • With ' RGB ' selected in the Navigator and the ' RGB ' target selected on the middle sidebar, select the ' Build Phases ' tab an D Expand the ' Link Binary with Libraries ' section.
    • Click the "+" icon and select the from the Curry.framework Curry-iOS target.
    • Click "Add".

Link Development Dependencies
    • Select the "rgbtests" target from the middle sidebar.
    • Using the same process as before, add the Quick and nimble frameworks to the ' Link Binary with Libraries ' section for this Target.

When adding dependencies to each target, Xcode would automatically add them to the "Framework Search Paths" under the "Buil D Settings "tab. We can remove these from the ' RGB ' and ' rgbtests ' target because Xcode treats them as implicit dependencies due to them be ing in the same workspace.

    • Select the target, locate the "Framework Search Paths" setting, highlight it, and press "BACKSPACE" on your keyboard.

    • Next, look in the ' RGB ' project in the Navigator; You'll see there is three new frameworks at the root level. To keep the organized, highlight all three, right click and select "New Group from selection" to place them in a Nam Ed Group. I ' ll call mine "frameworks".

Now that Carthage are set up, let's add CocoaPods.

Adding CocoaPods Support

To add CocoaPods support, we need to create a at the root of our project and fill with our .podspec project info.

    • Create a file named RGB.podspec .
    • Copy and paste the sample below into the file.
    • Fill in the options with your project s details. There is a lot more options available to you, but these is what's needed for this project.
Pod:: spec.newDo |spec| Spec.name ="RGB" spec.version ="1.0.0" spec.summary ="The Sample framework from the blog post, not to real world use." Spec.homepage ="Https://github.com/jakecraige/RGB" Spec.license = {type:  ' MIT ', file:  ' LICENSE '} Spec.authors = { "Your Name" = =  ' [email protected] '} spec.social_ Media_url =  "Http://twitter.com/thoughtbot" Spec.platform = :ios,  "9.1" Spec.requires_arc = true spec.source = {git:  "Https://github.com/jakecraige/RGB.git", tag: #{spec.version} ", submodules: true} spec.source_files = Span class= "string" > "rgb/**/*". {H,swift} "spec.dependency " ~> 1.4.0 " End                 

One line to pay attention to is spec.dependency "Curry", ‘~> 1.4.0‘ . Because we ' re supporting CocoaPods, we expect the consumers of our frameworks to being using it instead of Carthage, so we hav E to specify dependencies here and in the Cartfile .

Once This was set up we can run the pod lib lint command to test that everything is configured properly. If all goes well, we'll see something as this:

With the project and dependencies set up, we ' re almost ready to write some code. Before we do and let's create our first commit.

"Project and dependencies set up"
Writing the first Test

Open So, we can take a look at the RGBTests/RGBTests.swift default template. It uses @testable XCTest and, but we'll be changing both of these.

we ' ll remove @testable because we want to test the public API that consumers of the framework would use. As our framework grows, we could need to test parts that is not @testable exposed publicly; generally we want to avoid We're testing what's exposed to the consumer. This feature are most useful in testing applications rather than frameworks.

From the Apple Docs on testability:

With testability, you is now able to write tests of Swift 2.0 frameworks and apps without have to do all of your inte rnal routines public. Use @testable Import {modulename} in your test source code to make all public and internal routines usable by Xctest Targe TS, but isn't by the other framework and app targets.

We ll use the Quick and nimble for testing. Quick provides a nicer testing interface with a behavior-driven style that's very similar to RSpec and specta; Nimble gives us many powerful assertions and the ability to write asynchronous code with less boilerplate.

Once Those changes is made, the test file should look like:

import Quickimport Nimbleimport RGBclass RGBTests: QuickSpec { override func spec() { describe("RGB") { it("works") { expect(true).to(beTrue()) } } }}

Run the tests with? U or product→test and they should be green.

And ... we ' re done!

Just kidding. Let ' s write some real tests.

We expect that calling would RGBUIColor(red: 195, green: 47, blue: 52) return a beautiful "Thoughtbot red" UIColor .

In code, this looks like:

 describe ( "Rgbuicolor") {It ( "is a correct Representation of the values ") {let thoughtbotred = uicolor (r Ed: cgfloat (195/255), Green:  CGFloat (47/255), Blue: cgfloat ( 52/255), Alpha: 1) let color = rgbuicolor (red: 195, Green: 47, Blue: 52) expect (color). to (equal (thoughtbotred))}}     

If We run the tests, now they would fail as we expect. Swift's type checking would prevent us from running the tests because we never defined the RGBUIColor function.

Let's do that.

Writing the implementation

Right click on the "RGB" group in the Navigator and select "New File".

Create a Swift file called and RGBUIColor.swift save it. Fill it with this implementation:

 import curry Func rgbuicolor (red Red:int, Green:int, Blue:int),  Uicolor {return curry (Createcolor) (red) (green) (blue)}private func createcolor (Red:int, Green: Int, Blue:int), uicolor {return uicolor (red: cgfloat (Red/255), Green: cgfloat (green/ 255), Blue: cgfloat (Blue/155), Alpha: 1)}              

The use of this are used as an curry example of using a runtime dependency. This was a non-standard use and doesn ' t provide any value here.

Now let ' s run the tests!

At first glance, this error may seem a bit odd. We clearly defined RGBUIColor the function, right?

We did, but it's not marked as public .

What the This means is if someone tries to the use of our framework, they won ' t being able to see this function. If you want to see the difference in action, add back and @testable your tests'll pass.

Experiencing this error was why we removed the @testable "the import " at the beginning. It helps us to catch these kinds of errors earlier, before we release our framework to others.

To fix this, let's mark the function as like so public :

public func RGBUIColor(red red: Int, green: Int, blue: Int) -> UIColor { return curry(createColor)(red)(green)(blue)}

Let ' s run the tests!

We ' re green!

Let's commit this bad boy.

"Completed my first iOS framework!"
That ' s all folks!

That ' s it. There were a lot of steps but we've successfully created a marginally usefulframework that could is published to GitHub. As a matter of fact, we published Thesource for the This framework on GitHub.

We can ' t wait to see what kinds of awesome open-source projects you ' ll create.

Creating your first IOS Framework

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.