Skip to content

Commit

Permalink
Added README docs
Browse files Browse the repository at this point in the history
  • Loading branch information
hnryjms committed Jan 22, 2019
1 parent d5cdaef commit 71dd7f4
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 0 deletions.
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2019 Hank Brekke

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
143 changes: 143 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
# UIKit.js

Build powerful native iOS or tvOS apps using JavaScript backend services.

**Note: This framework is currently a proof-of-concept—if you like the idea, let me know
at [@hnryjms][twitter-hnryjms] or my [personal website][hnryjms].**

This framework provides tools and methods for sharing data between JavaScript and native
code, but still allows (and even relies) on many powerful features of native apps built with
Xcode, such as Storyboards and UI Components.

Unlike [React Native][react-native], this project seeks solely to bridge existing properties of
Interface Builder components to the JavaScript environment, rather than reconstruct them
as look-alike JS components.

## Getting Started

### Installation

You can install UIKit.js using [Carthage][carthage] for iOS or tvOS.

```sh
$ echo 'github "hnryjms/UIKit.js" ~> 0.1' >> Cartfile
$ carthage update
```

Then, drag the `Carthage/Build/iOS/UIKitJS.framework` file into your project (make sure
to deselect the `Copy items if needed` option), and ensure the framework is added to your
app/target's `Embedded Binaries` and `Linked Frameworks and Libraries` section.

(note: you may want to check out the [Carthage][carthage] Quick Start guide on their project
README for a complete setup guide, including several `copy-framework` improvements).

### Setup

Once the framework is linked, you will create a single `JSBridge()` instance for moving data
between JavaScript and native code. Typically, a singleton can live anywhere in your application,
such as on your `AppDelegate` class.

```swift
import UIKitJS

@UIApplicationMain
class AppDelegate {
static let bridge = try! JSBridge(Bundle.main.url(forResource: "main", withExtension: "js"))
}
```

You can also used more advanced implementations, such as a `var bridge: JSBridge?` on
the instance of your `AppDelegate` (accessable by `(UIApplication.delegate as! AppDelegate).bridge`),
such as the example under `Advanced Usage; Custom Modules`

### Usage

The core functionality of UIKit.js is using backend services, such as network requests and data
storage in JavaScript. Assuming your UIs are built in an Interface Builder storyboard, you can
load information from JS with a single call.

```swift
import UIKit
import UIKitJS

class MyViewController: UIViewController {
func viewDidLoad() {
AppDelegate.bridge.invoke(JSOperation("MyJSModule.loadData()")!, withArguments: ["hello"]) { result, error in
// write your code here...
}
}
}
```

And you can write `MyJSModule` with vanilla ES6 formatting, as supported by JavascriptCore,
the framework underneith WebKit (i.e. Safari & Mobile Safari).

```js
class MyJSModule {
static async loadData() {
const data = await fetch("https://hnryjms.io/");
return data.text();
}
}

// Note: the root `this` property exposes JS objects to native code.
this.MyJSModule = MyJSModule;
```

### Advanced Usage; Webpack Bundler

You can use the Webpack bundler to build the JavaScript entrypoint for your native app code.

(guide coming soon)

### Advanced Usage; Custom Modules

You can create custom native modules that are accessable in JavaScript code. This means you
can create custom API Request implementations (such as `fetch()`), or host navigation routing
code within JavaScript files.

```swift
@objc protocol MyModuleExports: JSExport {
func exportedFunc()
}

class MyModule: NSObject, JSModule, MyModuleExports {
let name = "MyModule"

func exportedFunc() {
// write your code here...
}
}
```

Then you will pass your module into the `JSBridge()` as it is created, and the module is available
to all JavaScript code as the first line starts executing.

```swift
import UIKitJS

@UIApplicationMain
class AppDelegate {
static let bridge = {
let modules = [ MyModule() ]
return try! JSBridge(Bundle.main.url(forResource: "main", withExtension: "js"), modules: modules)
}()
}
```

### Advanced Usage; Exposing Native UI Components

You can expose UI entry points through the JavaScript bridge to allow some UI component rendering
and handling inside JS code.

(guide coming soon)

## Example Project

You can find an example project inside UIKit.js, built for iOS. You can run it from any clone of this
repository by simply opening the `UIKit.js.xcodeproj` file in Xcode.

[twitter-hnryjms]: https://twitter.com/hnryjms
[hnryjms]: https://hnryjms.io
[react-native]: https://github.com/facebook/react-native
[carthage]: https://github.com/Carthage/Carthage
6 changes: 6 additions & 0 deletions UIKit.js.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
367A6B2B21F675FC006542FD /* UIViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 367A6B2A21F675FC006542FD /* UIViewController.swift */; };
367A6B2F21F6E192006542FD /* JSOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 367A6B2E21F6E192006542FD /* JSOperation.swift */; };
367A6B3121F6E1BB006542FD /* JSError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 367A6B3021F6E1BB006542FD /* JSError.swift */; };
367A6B4121F79540006542FD /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = 367A6B4021F79540006542FD /* LICENSE */; };
36D31C6A21C56A040003F361 /* UINavigationBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36D31C6921C56A040003F361 /* UINavigationBar.swift */; };
36D31C6D21C56D800003F361 /* UINavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36D31C6C21C56D800003F361 /* UINavigationController.swift */; };
/* End PBXBuildFile section */
Expand Down Expand Up @@ -80,6 +81,8 @@
367A6B2A21F675FC006542FD /* UIViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIViewController.swift; sourceTree = "<group>"; };
367A6B2E21F6E192006542FD /* JSOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSOperation.swift; sourceTree = "<group>"; };
367A6B3021F6E1BB006542FD /* JSError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSError.swift; sourceTree = "<group>"; };
367A6B3F21F78BA4006542FD /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
367A6B4021F79540006542FD /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
36D31C6921C56A040003F361 /* UINavigationBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UINavigationBar.swift; sourceTree = "<group>"; };
36D31C6C21C56D800003F361 /* UINavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UINavigationController.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
Expand Down Expand Up @@ -114,6 +117,8 @@
3648A52121BD722900620B33 = {
isa = PBXGroup;
children = (
367A6B3F21F78BA4006542FD /* README.md */,
367A6B4021F79540006542FD /* LICENSE */,
3648A52D21BD722900620B33 /* UIKit.js */,
3648A53821BD722900620B33 /* UIKit.jsTests */,
3648A54A21BD726900620B33 /* UIKit.jsExamples */,
Expand Down Expand Up @@ -291,6 +296,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
367A6B4121F79540006542FD /* LICENSE in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down

0 comments on commit 71dd7f4

Please sign in to comment.