<commit_before>URLNavigator
============

![Swift](https://img.shields.io/badge/Swift-2.1-orange.svg)
[![Build Status](https://travis-ci.org/devxoul/URLNavigator.svg)](https://travis-ci.org/devxoul/URLNavigator)
[![CocoaPods](http://img.shields.io/cocoapods/v/URLNavigator.svg)](https://cocoapods.org/pods/URLNavigator)
[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)

⛵️ URLNavigator provides an elegant way to navigate through view controllers by URLs. URL patterns can be mapped by using `URLNavigator.map(_:_:)` function.

URLNavigator can be used for mapping URL patterns with 2 kind of types: `URLNavigable` and `URLOpenHandler`. `URLNavigable` is a type which defines an custom initializer and `URLOpenHandler` is a closure which can be executed. Both an initializer and a closure receive an URL and placeholder values.


At a Glance
-----------

#### Mapping URL Patterns

URL patterns can contain placeholders. Placeholders will be replaced with matching values from URLs. Use `<` and `>` to make placeholders. Placeholders can have types: `string`(default), `int`, `float`, and `path`.

Here's an example of mapping URL patterns with view controllers and a closure. View controllers should conform a protocol `URLNavigable` to be mapped wisth URL patterns. See [Implementing URLNavigable](#implementing-urlnavigable) section for details.

```swift
Navigator.map("myapp://user/<int:id>", UserViewController.self)
Navigator.map("myapp://post/<title>", PostViewController.self)

Navigator.map("myapp://alert") { URL, values in
    print(URL.queryParameters["title"])
    print(URL.queryParameters["message"])
    return true
}
```

> **Note**: Global constant `Navigator` is a shortcut for `URLNavigator.defaultNavigator()`.

#### Pushing, Presenting and Opening URLs

URLNavigator can push and present view controllers and execute closures with URLs.

Provide the `from` parameter to `pushURL()` to specify the navigation controller which the new view controller will be pushed. Similarly, provide the `from` parameter to `presentURL()` to specify the view controller which the new view controller will be presented. If the `nil` is passed, which is a default value, current application's top most view controller will be used to push or present view controllers.

`presentURL()` takes an extra parameter: `wrap`. If `true` is specified, the new view controller will be wrapped with a `UINavigationController`. Default value is `false`.

```swift
Navigator.pushURL("myapp://user/123")
Navigator.presentURL("myapp://post/54321", wrap: true)

Navigator.openURL("myapp://alert?title=Hello&message=World")
```

For full documentation, see [URLNavigator Class Reference](http://cocoadocs.org/docsets/URLNavigator/0.6.0/Classes/URLNavigator.html).

#### Implementing URLNavigable

View controllers should conform a protocol `URLNavigable` to be mapped with URLs. A protocol `URLNavigable` defines an failable initializer with parameter: `URL` and `values`.

Parameter `URL` is an URL that is passed from `URLNavigator.pushURL()` and `URLNavigator.presentURL()`. Parameter `values` is a dictionary that contains URL placeholder keys and values.

```swift
final class UserViewController: UIViewController, URLNavigable {

    init(userID: Int) {
        super.init(nibName: nil, bundle: nil)
        // Initialize here...
    }

    convenience init?(URL: URLConvertible, values: [String : AnyObject]) {
        // Let's assume that the user id is required
        guard let userID = values["id"] as? Int else {
            return nil
        }
        self.init(userID: userID)
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}
```

> **Note**: `URLConvertible` is a protocol that `NSURL` and `String` conforms.


Installation
------------

- **For iOS 8+ projects** with [CocoaPods](https://cocoapods.org):

    ```ruby
    pod 'URLNavigator', '~> 0.6'
    ```

- **For iOS 8+ projects** with [Carthage](https://github.com/Carthage/Carthage):

    ```
    github "devxoul/URLNavigator" ~> 0.6
    ```

- **For iOS 7 projects** with [CocoaSeeds](https://github.com/devxoul/CocoaSeeds):

    ```ruby
    github 'devxoul/URLNavigator', '0.6.0', :files => 'Sources/*.swift'
    ```

- **Using [Swift Package Manager](https://swift.org/package-manager)**:

    ```swift
    import PackageDescription

    let package = Package(
        name: "MyAwesomeApp",
        dependencies: [
            .Package(url: "https://github.com/devxoul/URLNavigator", "0.6.0"),
        ]
    )
    ```
    

Tips and Tricks
---------------

#### Where to Map URLs

I'd prefer using separated URL map file.

```swift
struct URLNavigationMap {

    static func initialize() {
        Navigator.map("myapp://user/<int:id>", UserViewController.self)
        Navigator.map("myapp://post/<title>", PostViewController.self)

        Navigator.map("myapp://alert") { URL, values in
            print(URL.parameters["title"])
            print(URL.parameters["message"])
            self.someUtilityMethod()
            return true
        }
    }

    private static func someUtilityMethod() {<commit_msg>Add an Example section to README.md<commit_after>URLNavigator
============

![Swift](https://img.shields.io/badge/Swift-2.1-orange.svg)
[![Build Status](https://travis-ci.org/devxoul/URLNavigator.svg)](https://travis-ci.org/devxoul/URLNavigator)
[![CocoaPods](http://img.shields.io/cocoapods/v/URLNavigator.svg)](https://cocoapods.org/pods/URLNavigator)
[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)

⛵️ URLNavigator provides an elegant way to navigate through view controllers by URLs. URL patterns can be mapped by using `URLNavigator.map(_:_:)` function.

URLNavigator can be used for mapping URL patterns with 2 kind of types: `URLNavigable` and `URLOpenHandler`. `URLNavigable` is a type which defines an custom initializer and `URLOpenHandler` is a closure which can be executed. Both an initializer and a closure receive an URL and placeholder values.


At a Glance
-----------

#### Mapping URL Patterns

URL patterns can contain placeholders. Placeholders will be replaced with matching values from URLs. Use `<` and `>` to make placeholders. Placeholders can have types: `string`(default), `int`, `float`, and `path`.

Here's an example of mapping URL patterns with view controllers and a closure. View controllers should conform a protocol `URLNavigable` to be mapped wisth URL patterns. See [Implementing URLNavigable](#implementing-urlnavigable) section for details.

```swift
Navigator.map("myapp://user/<int:id>", UserViewController.self)
Navigator.map("myapp://post/<title>", PostViewController.self)

Navigator.map("myapp://alert") { URL, values in
    print(URL.queryParameters["title"])
    print(URL.queryParameters["message"])
    return true
}
```

> **Note**: Global constant `Navigator` is a shortcut for `URLNavigator.defaultNavigator()`.

#### Pushing, Presenting and Opening URLs

URLNavigator can push and present view controllers and execute closures with URLs.

Provide the `from` parameter to `pushURL()` to specify the navigation controller which the new view controller will be pushed. Similarly, provide the `from` parameter to `presentURL()` to specify the view controller which the new view controller will be presented. If the `nil` is passed, which is a default value, current application's top most view controller will be used to push or present view controllers.

`presentURL()` takes an extra parameter: `wrap`. If `true` is specified, the new view controller will be wrapped with a `UINavigationController`. Default value is `false`.

```swift
Navigator.pushURL("myapp://user/123")
Navigator.presentURL("myapp://post/54321", wrap: true)

Navigator.openURL("myapp://alert?title=Hello&message=World")
```

For full documentation, see [URLNavigator Class Reference](http://cocoadocs.org/docsets/URLNavigator/0.6.0/Classes/URLNavigator.html).

#### Implementing URLNavigable

View controllers should conform a protocol `URLNavigable` to be mapped with URLs. A protocol `URLNavigable` defines an failable initializer with parameter: `URL` and `values`.

Parameter `URL` is an URL that is passed from `URLNavigator.pushURL()` and `URLNavigator.presentURL()`. Parameter `values` is a dictionary that contains URL placeholder keys and values.

```swift
final class UserViewController: UIViewController, URLNavigable {

    init(userID: Int) {
        super.init(nibName: nil, bundle: nil)
        // Initialize here...
    }

    convenience init?(URL: URLConvertible, values: [String : AnyObject]) {
        // Let's assume that the user id is required
        guard let userID = values["id"] as? Int else {
            return nil
        }
        self.init(userID: userID)
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}
```

> **Note**: `URLConvertible` is a protocol that `NSURL` and `String` conforms.


Installation
------------

- **For iOS 8+ projects** with [CocoaPods](https://cocoapods.org):

    ```ruby
    pod 'URLNavigator', '~> 0.6'
    ```

- **For iOS 8+ projects** with [Carthage](https://github.com/Carthage/Carthage):

    ```
    github "devxoul/URLNavigator" ~> 0.6
    ```

- **For iOS 7 projects** with [CocoaSeeds](https://github.com/devxoul/CocoaSeeds):

    ```ruby
    github 'devxoul/URLNavigator', '0.6.0', :files => 'Sources/*.swift'
    ```

- **Using [Swift Package Manager](https://swift.org/package-manager)**:

    ```swift
    import PackageDescription

    let package = Package(
        name: "MyAwesomeApp",
        dependencies: [
            .Package(url: "https://github.com/devxoul/URLNavigator", "0.6.0"),
        ]
    )
    ```


Example
-------

You can find an example app [here](https://github.com/devxoul/URLNavigator/tree/master/Example).

1. Build and install the example app.
2. Open Safari app
3. Enter `navigator://user/devxoul` in the URL bar.
4. The example app will be launched.


Tips and Tricks
---------------

#### Where to Map URLs

I'd prefer using separated URL map file.

```swift
struct URLNavigationMap {

    static func initialize() {
        Navigator.map("myapp://user/<int:id>", UserViewController.self)
        Navigator.map("myapp://post/<title>", PostViewController.self)

        Navigator.map("myapp://alert") { URL, values in
            print(URL.parameters["title"])
            print(URL.parameters["message"])
            self.someUtilityMethod()
            return true
        }
    }

    private static func someUtilityMethod() {
{'fraction_non_alphanumeric': 0.13465291329802062, 'fraction_numerical': 0.005947402657745563, 'mean_word_length': 3.7980383415069103, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 23, 'https://': 23, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4380670', 'n_tokens_mistral': 3288, 'n_tokens_neox': 3132, 'n_words': 986}