Skip to content

Commit

Permalink
tidy up.
Browse files Browse the repository at this point in the history
  • Loading branch information
sgr-ksmt committed Mar 17, 2019
1 parent 14eea5e commit 26502e2
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 96 deletions.
2 changes: 1 addition & 1 deletion .swift-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4.1
4.2
1 change: 1 addition & 0 deletions Lobster.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ Pod::Spec.new do |s|
s.requires_arc = true
s.source_files = "Sources/**/*"
s.static_framework = true
s.swift_version = '4.2'
s.dependency "Firebase/RemoteConfig", "~> 5.0"
end
166 changes: 77 additions & 89 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,20 @@ extension ConfigKeys {
static let text = ConfigKey<String>("text")
}

// Get value.
// Get value from config.
// If value didn't fetch from remote yet. returns default value (if exists).
let text: String = Lobster.shared[.text]

// Get value from only config.
// it is possible to crash if value didn't fetch from remote yet.
let text: String = Lobster.shared[config: .text]

// Get value from only default.
// It is possible to crash if the default value is not set yet.
let text: String = Lobster.shared[default: .text]

// [safe:], [safeConfig:], [safeDefault:] subscripting syntax.
// It is safe because they return nil if they have no value.(return type is `Optional<T>`.)
let text: String? = Lobster.shared[safe: .text]
let text: String? = Lobster.shared[safeConfig: .text]
let text: String? = Lobster.shared[safeDefault: .text]
Expand Down Expand Up @@ -111,6 +119,8 @@ Lobster.shared.fetchExpirationDuration = 0.0
```

### isStaled
If you set `isStaled` to true, Lobster will fetch remote value ignoring `fetchExpirationDuration`.
`isStaled` will be set to `false` after fetched remote value.

```swift
Lobster.shared.fetchExpirationDuration = 60 * 12
Expand All @@ -123,17 +133,6 @@ Lobster.shared.isStaled = true
Lobster.shared.fetch()
```

### Demo
Required: CocoaPods 1.5 or higher.

```bash
$ cd path/to/Lobster
$ bundle install
$ cd ./Demo
$ bundle exec pod install
$ open Demo.xcworkspace
```

## Supported types

Lobster supports more types as default followings:
Expand All @@ -159,55 +158,27 @@ Lobster supports more types as default followings:
- enum(String/Int)
- Decodable Object
- Codable Object
- Dictionary

### TODO
- [ ] CGPoint
- [ ] CGSize
- [ ] CGRect
- [ ] Dictionary

#### URL
support text: e.g. `"https://example.com"`.
Supports text: e.g. `"https://example.com"`.

![](docs/img2.png)

#### UIColor
support only HEX sttring like `"#FF00FF"`.
Supports only HEX string like `"#FF00FF"`.

![](docs/img3.png)

#### CGPoint
support text: e.g. `"[100, 100]"`
→ Use `DecodableConfigKey`(or `CodableConfigKey`)

```swift
extension ConfigKeys {
static let labelOrigin = ConfigKey<CGPoint>("label_origin")
}
```

#### CGSize
support text: e.g. `"[100, 100]"`
→ Use `DecodableConfigKey`(or `CodableConfigKey`)

```swift
extension ConfigKeys {
static let boxSize = ConfigKey<CGSize>("box_size")
}
```

#### CGRect
support text: e.g. `"[10, 10, 100, 100]"`
→ Use `DecodableConfigKey`(or `CodableConfigKey`)

```swift
extension ConfigKeys {
static let boxRect = ConfigKey<CGRect>("box_rect")
}
```

<br />

![](docs/img4.png)

#### Enum
supports `Int` or `String` rawValue.
If you want to use other enum, see "Use custom value".
It can be used only by adapting `ConfigSerializable`.
If you want to use other enum, see ***Use custom value***.

#### Decodable compliant type
read only
Expand All @@ -222,73 +193,79 @@ You can easily define custom key in order to get remote value.
### Ex 1: enum

```swift
enum Status {
case invalid
case foo(String)
case bar(String)
// Adapt protocol `ConfigSerializable`
enum Status: ConfigSerializable {
// Define `_config`, `_configArray`(If needed).
// Custom ConfigBridge's definition see below.
static var _config: ConfigBridge<Status> { return ConfigStatusBridge() }
static var _configArray: ConfigBridge<[Status]> { fatalError("Not implemented") }

case unknown
case active
case inactive

init(value: String?) {
guard let value = value else {
self = .invalid
return
}
let separated = value.components(separatedBy: ":")
guard let query: (String, String) = separated.first.flatMap({ f in separated.last.flatMap({ l in (f, l) })}) else {
self = .invalid
self = .unknown
return
}
switch query {
case ("foo", let x):
self = .foo(x)
case ("bar", let x):
self = .bar(x)
default:
self = .invalid
switch value {
case "active": self = .active
case "inactive": self = .inactive
default: self = .unknown
}
}

var value: String {
switch self {
case .foo(let x):
return "foo:\(x)"
case .bar(let x):
return "bar:\(x)"
default:
return ""
case .active: return "active"
case .inactive: return "inactive"
default: return ""
}
}
}

// define subscript
extension Lobster {
subscript(_ key: ConfigKey<Status>) -> Status? {
get { return Status(value: configValue(forKey: key._key)) }
set { setDefaultValue(newValue?.value, forKey: key._key) }
// Define Bridge class
final class ConfigStatusBridge: ConfigBridge<Status> {
typealias T = Status

// Save value to default store
override func save(key: String, value: T?, defaultsStore: DefaultsStore) {
defaultsStore[key] = value?.value
}

// Get value from RemoteConfig
override func get(key: String, remoteConfig: RemoteConfig) -> T? {
return remoteConfig[key].stringValue.flatMap(Status.init(value:))
}

// Get value from default store
override func get(key: String, defaultsStore: DefaultsStore) -> T? {
return (defaultsStore[key] as? String).flatMap(Status.init(value:))
}
}

// define ConfigKey
// Define ConfigKey
extension ConfigKeys {
static let status = ConfigKey<Status>("status")
static let status = ConfigKey<Status>
}

// Use
// set default value
Lobster.shared[.status] = .foo("bar")
// Set default
Lobster.shared[default: .status] = .inactive

// get config value
if let status = Lobster.shared[.status] {
// ...
// Use value
Lobster.shared.fetch { _ in
let currentStatus = Lobster.shared[.status]
}
```

To define subscript makes it possible to access custom enum.

### Ex 2: Decodable compliant type
Just adapt class or struct to Decodable or Codable
Just adapt `Decodable` or `Codable` to class or struct and adapt `ConfigSerializable`

```swift
struct Person: Codable {
struct Person: Codable, ConfigSerializable {
let name: String
let age: Int
let country: String
Expand All @@ -299,10 +276,21 @@ extension ConfigKeys {
}
```

Define config value like below:
Define config value like below in console:

![](docs/img5.png)

## Demo
Required: CocoaPods 1.5 or higher.

```bash
$ cd path/to/Lobster
$ bundle install
$ cd ./Demo
$ bundle exec pod install
$ open Demo.xcworkspace
```

## Requirements
- iOS 11.0+
- Xcode 10+
Expand Down
6 changes: 0 additions & 6 deletions Sources/ConfigKeys.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,3 @@ public class ConfigKey<ValueType: ConfigSerializable>: ConfigKeys {
self._key = key
}
}

public extension ConfigKey where ValueType: ConfigSerializable, ValueType: OptionalType, ValueType.Wrapped: ConfigSerializable {
convenience init(key: String) {
self.init(key)
}
}

0 comments on commit 26502e2

Please sign in to comment.