-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Extended support for optionals & general improvements
- Loading branch information
1 parent
1f90ff1
commit c8c11fb
Showing
8 changed files
with
312 additions
and
82 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
# Swift Declarative Configuration | ||
|
||
[![Swift 5.3](https://img.shields.io/badge/swift-5.3-ED523F.svg?style=flat)](https://swift.org/download/) [![SwiftPM](https://img.shields.io/badge/SwiftPM-ED523F.svg?style=flat)](https://swift.org/package-manager/) [![@maximkrouk](https://img.shields.io/badge/contact-@maximkrouk-ED523F.svg?style=flat)](https://twitter.com/maximkrouk) | ||
[![Swift 5.3](https://img.shields.io/badge/swift-5.3-ED523F.svg?style=flat)](https://swift.org/download/) [![SwiftPM](https://img.shields.io/badge/SwiftPM-success.svg?style=flat)](https://swift.org/package-manager/) [![@maximkrouk](https://img.shields.io/badge/contact-@maximkrouk-#1DA1F2.svg?style=flat&logo=twitter)](https://twitter.com/maximkrouk) | ||
|
||
Swift Declarative Configuration (SDC, for short) is a tiny library, that enables you to configure your objects in a declarative, consistent and understandable way, with ergonomics in mind. It can be used to configure any objects on any platform, including server-side-swift. | ||
|
||
|
@@ -12,47 +12,69 @@ Swift Declarative Configuration (SDC, for short) is a tiny library, that enables | |
|
||
- **[FunctionalKeyPath](./Sources/FunctionalKeyPath)** & **[CasePaths](https://github.com/pointfreeco/swift-case-paths)** | ||
|
||
KeyPath functional wrappers, one is generalized and the other is for enums. [CasePath is a dependency](https://github.com/pointfreeco/swift-case-paths). | ||
KeyPath functional wrappers, one is generalized and the other is for enums. _[CasePath is a dependency](https://github.com/pointfreeco/swift-case-paths)_. | ||
|
||
- **[FunctionalConfigurator](./Sources/FunctionalConfigurator)** | ||
|
||
Funtional configurator for anything, enables you to specify modification of an object and to apply the modification later. | ||
|
||
Also contains self-implementing protocols (`ConfigInitializable`, `CustomConfigurable`) to enable you add custom configuration support for your types (`NSObject` already conforms to it for you). | ||
|
||
- **[FunctionalBuilder](./Sources/FunctionalBuilder)** | ||
|
||
Functional builder for anything, enables you to modify object instances in a declarative way. Also contains BuilderProvider protocol with a computed `builder` property and implements that protocol on NSObject type. | ||
Functional builder for anything, enables you to modify object instances in a declarative way. Also contains `BuilderProvider` protocol with a computed `builder` property and implements that protocol on `NSObject` type. | ||
|
||
- **[DeclarativeConfiguration](./Sources/DeclarativeConfiguration)** | ||
|
||
Wraps and exports all the products. | ||
|
||
## Basic Usage | ||
|
||
### UIKit & FunctionalConfigurator | ||
### UIKit & No SDC | ||
|
||
Maybe it worth to make another abstraction over configurator for UI setup, but for example I'll be using pure version. | ||
```swift | ||
class ImageViewController: UIViewController { | ||
let imageView = UIImageView() | ||
|
||
override func loadView() { | ||
self.view = imageView | ||
} | ||
|
||
override func viewDidLoad() { | ||
super.viewDidLoad() | ||
imageView.contentMode = .scaleAspectFit | ||
imageView.backgroundColor = .black | ||
imageView.layer.masksToBounds = true | ||
imageView.layer.cornerRadius = 10 | ||
} | ||
} | ||
``` | ||
|
||
### UIKit & FunctionalConfigurator | ||
|
||
```swift | ||
import FunctionalConfigurator | ||
|
||
class ImageViewController: UIViewController { | ||
enum StyleSheet { | ||
static let imageView = Configurator<UIImageView> | ||
.contentMode(.scaleAspectFit) | ||
.backgroundColor(.black) | ||
.layer.masksToBounds(true) | ||
.layer.cornerRadius(10) | ||
} | ||
|
||
let imageView = UIImageView(config: StyleSheet.imageView) | ||
let imageView = UIImageView { $0 | ||
.contentMode(.scaleAspectFit) | ||
.backgroundColor(.black) | ||
.layer.masksToBounds(true) | ||
.layer.cornerRadius(10) | ||
} | ||
|
||
override func loadView() { | ||
self.view = imageView | ||
} | ||
|
||
} | ||
``` | ||
|
||
**Note:** This way is **recommended**, but remember, that custom types **MUST** implement initializer with no parameters even if the superclass already has it or you will get a crash otherwise. | ||
|
||
### UIKit & FunctionalBuilder | ||
|
||
```swift | ||
import FunctionalBuilder | ||
|
||
|
@@ -70,40 +92,51 @@ class ImageViewController: UIViewController { | |
} | ||
``` | ||
|
||
### Modification | ||
Note: This way is recommended too, and it is more **safe**, because it modifies existing objects. | ||
|
||
### Other usecases | ||
|
||
#### Builder | ||
|
||
Customize any object by passing initial value to a builder | ||
|
||
```swift | ||
import FunctionalModification | ||
let object = Builder(Object()) | ||
.property.subproperty(value) | ||
.build() // Returns modified object | ||
``` | ||
|
||
struct MyModel { | ||
var value1 = 0 | ||
init() {} | ||
} | ||
For classes you can avoid returning a value by calling `apply` method, instead of `build` | ||
|
||
let model_0 = MyModel() | ||
let model_1 = modification(of: model_0) { $0.value = 1 } | ||
```swift | ||
let _class = _Class() | ||
Builder(_class) | ||
.property.subproperty(value) | ||
.apply() // Returns Void | ||
``` | ||
|
||
import UIKit | ||
Conform your own types to `BuilderProvider` protocol to access builder property. | ||
|
||
extension UIView { | ||
@discardableResult | ||
func cornerRadius(_ value: CGFloat) -> Self { | ||
modification(of: self) { view in | ||
view.layer.cornerRadius = value | ||
view.layer.masksToBounds = true | ||
} | ||
} | ||
} | ||
```swift | ||
import CoreLocation | ||
import DeclarativeConfiguration | ||
|
||
extension CLLocationCoordinate2D: BuilderProvider {} | ||
// Now you can access `location.builder.latitude(0).build()` | ||
``` | ||
|
||
#### Configurator | ||
|
||
> README PLACEHOLDER (Not yet written 😅) | ||
## Installation | ||
|
||
### Basic | ||
|
||
You can add DeclarativeConfiguration to an Xcode project by adding it as a package dependency. | ||
|
||
1. From the **File** menu, select **Swift Packages › Add Package Dependency…** | ||
2. Enter "https://github.com/makeupstudio/swift-declarative-configuration" into the package repository URL text field | ||
2. Enter [`"https://github.com/makeupstudio/swift-declarative-configuration"`](https://github.com/makeupstudio/swift-declarative-configuration) into the package repository URL text field | ||
3. Choose products you need to link them to your project. | ||
|
||
### Recommended | ||
|
@@ -113,7 +146,7 @@ If you use SwiftPM for your project, you can add DeclarativeConfiguration to you | |
```swift | ||
.package( | ||
url: "[email protected]:makeupstudio/swift-declarative-configuration.git", | ||
from: "0.0.2" | ||
from: "0.0.4" | ||
) | ||
``` | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.