Skip to content

Commit

Permalink
Merge pull request #2 from ndizazzo/feature/swift-4-codable
Browse files Browse the repository at this point in the history
[FEATURE] Swift 4 Codable Support
  • Loading branch information
ndizazzo authored Jun 20, 2018
2 parents 09935db + bac6801 commit e581d72
Show file tree
Hide file tree
Showing 27 changed files with 1,250 additions and 542 deletions.
4 changes: 2 additions & 2 deletions Biome.podspec
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
Pod::Spec.new do |s|
s.name = 'Biome'
s.version = '1.0.0'
s.version = '2.0.0'
s.summary = 'Simple environment management for iOS / macOS / tvOS / watchOS!'
s.description = <<-DESC
Biome is a simple way to manage sets of variables between environments you might need to work with when developing your application.
One problem developers face, is the need to create multiple builds in order to test how their application functions in different environments. Biome aims to reduce the amount of re-building that needs to occur, by providing a mechanism to switch configurations during run-time.
One problem developers face, is the need to create multiple builds in order to test how their application functions in different environments. Biome aims to reduce the amount of re-building that needs to occur by providing a mechanism to switch values and configurations during run-time.
DESC

s.homepage = 'https://github.com/ndizazzo/Biome'
Expand Down
306 changes: 173 additions & 133 deletions Biome.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

44 changes: 40 additions & 4 deletions Biome.xcodeproj/xcshareddata/xcschemes/Biome.xcscheme
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0820"
LastUpgradeVersion = "1000"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand All @@ -20,24 +20,53 @@
ReferencedContainer = "container:Biome.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "NO"
buildForProfiling = "NO"
buildForArchiving = "NO"
buildForAnalyzing = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "C59A9BEE20D2B9E600C150E9"
BuildableName = "BiomeTests.xctest"
BlueprintName = "BiomeTests"
ReferencedContainer = "container:Biome.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
codeCoverageEnabled = "YES">
codeCoverageEnabled = "YES"
onlyGenerateCoverageForSpecifiedTargets = "YES"
shouldUseLaunchSchemeArgsEnv = "NO">
<CodeCoverageTargets>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "C5EE7B131E6DE98200EC5A49"
BuildableName = "Biome.framework"
BlueprintName = "Biome"
ReferencedContainer = "container:Biome.xcodeproj">
</BuildableReference>
</CodeCoverageTargets>
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "C5EE7B1C1E6DE98200EC5A49"
BlueprintIdentifier = "C59A9BEE20D2B9E600C150E9"
BuildableName = "BiomeTests.xctest"
BlueprintName = "BiomeTests"
ReferencedContainer = "container:Biome.xcodeproj">
</BuildableReference>
<SkippedTests>
<Test
Identifier = "HashableTests/testHashableTypeHasher()">
</Test>
</SkippedTests>
</TestableReference>
</Testables>
<MacroExpansion>
Expand All @@ -49,6 +78,13 @@
ReferencedContainer = "container:Biome.xcodeproj">
</BuildableReference>
</MacroExpansion>
<EnvironmentVariables>
<EnvironmentVariable
key = "SWIFT_DETERMINISTIC_HASHING"
value = "1"
isEnabled = "YES">
</EnvironmentVariable>
</EnvironmentVariables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
Expand Down
116 changes: 22 additions & 94 deletions Biome/Classes/Biome.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,115 +2,43 @@
// Biome.swift
// Biome
//
// Created by Nick DiZazzo on 2017-02-28.
// Copyright © 2017 Nick DiZazzo. All rights reserved.
// Created by Nick DiZazzo on 2018-05-11.
// Copyright © 2018 Nick DiZazzo. All rights reserved.
//

import Foundation

// MARK: -
// MARK: BiomeProvider

public protocol BiomeProvider {
var biomeName: String { get }
func mappedPropertyDictionary() -> [String: Any]
}

// MARK: -
// MARK: BiomeManager
// MARK: Biome

public enum BiomeError: Error {
case previouslyRegistered
case notRegistered
/// A simple protocol that tells the `BiomeGroup` and `BiomeManager` how to work with objects.
public protocol Biome: Codable {
var identifier: String { get }
var keyCount: Int { get }
}

public protocol BiomeManagerDelegate {
func switched(to biome: Biome?)
enum BiomeError: LocalizedError {
case missingResource
}

public class BiomeManager {
public static let shared = BiomeManager()

internal var biomes: Set<Biome> = Set<Biome>()

public var count: Int { get { return self.biomes.count } }
public var current: Biome? { didSet { self.delegate?.switched(to: self.current) } }
public var delegate: BiomeManagerDelegate?

public var keys: Set<String> {
get {
var unversalKeys = Set<String>()

for biome in self.biomes {
biome.properties.keys.forEach { unversalKeys.insert($0) }
}

return unversalKeys
}
}

public static func register(_ biome: Biome) throws {
if shared.biomes.contains(biome) {
throw BiomeError.previouslyRegistered
}
extension Biome {
public static func load(fromPath url: URL?, using decoder: BridgedDecoder) throws -> Self {
guard let url = url else { throw BiomeError.missingResource }

if shared.count == 0 {
shared.current = biome
}

shared.biomes.insert(biome)
}

public static func remove(_ biome: Biome) throws {
guard shared.biomes.contains(biome) else {
throw BiomeError.notRegistered
}

shared.biomes.remove(biome)
}

public func clear() {
self.current = nil
self.biomes.removeAll()
let data = try Data(contentsOf: url)
let biome = try decoder.decode(Self.self, from: data)
return biome
}
}

// MARK: -
// MARK: Biome
public class Biome {
fileprivate var properties: [String: Any] = [:]

public private(set) var name: String = ""
public var count: Int { get { return properties.keys.count } }

public init(named biomeName: String) {
self.name = biomeName
}

public init(with provider: BiomeProvider) {
self.name = provider.biomeName
self.properties = provider.mappedPropertyDictionary()
}

public func get(_ key: String) -> Any? {
return self.properties[key]
}

public func set(_ key: String, value: Any?) {
self.properties[key] = value
}
}
public typealias BiomeData = (identifier: String, keys: Int)

// MARK: -
// MARK: Equatable
extension Biome: Equatable {
public static func ==(lhs: Biome, rhs: Biome) -> Bool {
return lhs.name == rhs.name
}
}
// MARK: BridgedDecoder

// MARK: -
// MARK: Hashable
extension Biome: Hashable {
public var hashValue: Int { get { return self.name.hash } }
public protocol BridgedDecoder {
func decode<T>(_ type: T.Type, from data: Data) throws -> T where T : Decodable
}

extension JSONDecoder: BridgedDecoder { }
extension PropertyListDecoder: BridgedDecoder { }
64 changes: 33 additions & 31 deletions Biome/Classes/BiomeDataSource.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,71 +11,73 @@ import Foundation
#if os(iOS) || os(watchOS) || os(tvOS)
// MARK: -
// MARK: BiomeDataSource
public class BiomeDataSource: NSObject {
public class BiomeDataSource<T: Biome>: NSObject, UITableViewDataSource, UITableViewDelegate {
internal weak var manager: BiomeManager?
internal var biomes: [Biome]
internal var biomeData: [BiomeData] = []

public init(biomeManager: BiomeManager) {
self.manager = biomeManager
self.biomes = Array(biomeManager.biomes)
if let group = biomeManager.group(for: HashableType<T>()) {
biomeData = group.biomeData
}
}

fileprivate func biome(at index: Int) -> Biome? {
guard index >= 0 && index < self.biomes.count else {
fileprivate func data(at index: Int) -> BiomeData? {
guard index >= 0 && index < self.biomeData.count else {
return nil
}

return self.biomes[index]
return self.biomeData[index]
}

fileprivate func viewModel(for biome: Biome) -> BiomeViewModel {
let isActive = self.manager?.current == biome
let string = biome.count == 1 ? "%d key" : "%d keys"
return BiomeViewModel(name: biome.name,
subtitle: String.init(format: string, biome.count),
fileprivate func viewModel(for data: BiomeData) -> BiomeViewModel {
let currentBiome = self.manager?.current(for: T.self)
let isActive = currentBiome?.identifier == data.identifier

let string = 1 == data.keys ? "%d key" : "%d keys"
return BiomeViewModel(name: data.identifier,
subtitle: String.init(format: string, data.keys),
active: isActive)
}
}

// MARK: -
// MARK: UITableViewDataSource
extension BiomeDataSource: UITableViewDataSource {

// MARK: -
// MARK: UITableViewDataSource
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.biomes.count
return self.biomeData.count
}

public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.cell(tableView: tableView)
if let biome = self.biome(at: indexPath.row) {
if let biome = self.data(at: indexPath.row) {
let viewModel = self.viewModel(for: biome)
cell.update(with: viewModel)
}

return cell
}

private func cell(tableView: UITableView) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "cell")

if cell == nil {
cell = UITableViewCell(style: .subtitle, reuseIdentifier: "cell")
}

return cell!
}
}

// MARK: -
// MARK: UITableViewDelegate
extension BiomeDataSource: UITableViewDelegate {
// MARK: -
// MARK: UITableViewDelegate
public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let biome = self.biome(at: indexPath.row)
self.manager?.current = biome

do {
try manager?.select(type: T.self, index: indexPath.row)
} catch let error {
print("ERROR: \(error)")
}

var indexSet = IndexSet()
indexSet.insert(0)

tableView.reloadSections(indexSet, with: .automatic)
}
}
Expand Down
Loading

0 comments on commit e581d72

Please sign in to comment.