Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
eimantas committed Dec 4, 2020
0 parents commit 45deb50
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.DS_Store
/.build
/Packages
/*.xcodeproj
xcuserdata/
7 changes: 7 additions & 0 deletions .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 29 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// swift-tools-version:5.3
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "Swappable",
platforms: [.iOS(.v13)],
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
.library(
name: "Swappable",
targets: ["Swappable"]),
],
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages this package depends on.
.target(
name: "Swappable",
dependencies: []),
.testTarget(
name: "SwappableTests",
dependencies: ["Swappable"]),
]
)
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# swappable

A description of this package.
75 changes: 75 additions & 0 deletions Sources/Swappable/Swappable.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import UIKit
import SwiftUI

extension EnvironmentObject {
var hasValue: Bool {
Mirror(reflecting: self).children.contains { ($0.value is ObjectType) }
}
}

class ViewSwap<S>: ObservableObject where S: View, S: Swappable {

init<V>(with customView: @escaping (S.InputType) -> V, insteadOf _: S.Type)
where V: View {
self.view = { AnyView(customView($0)) }
}

let view: (S.InputType) -> AnyView
}

struct SwappedIfNeeded<S>: View where S: View, S: Swappable {

@EnvironmentObject var swap: ViewSwap<S>

let input: S.InputType
let content: S.DefaultBody

init(input: S.InputType, content: S.DefaultBody) {
self.input = input
self.content = content
}

var body: some View {
Group {
if _swap.hasValue {
swap.view(input)
} else {
content
}
}
}
}


public protocol Swappable {

associatedtype InputType
var input: InputType { get }
init(input: InputType)

associatedtype DefaultBody : View
@ViewBuilder var defaultBody: DefaultBody { get }
}

public extension View {

func swapView<V, S>(_ initV : @escaping (S.InputType) -> V, insteadOf typeS: S.Type) -> some View
where S: View, S: Swappable,
V: View {
environmentObject(ViewSwap<S>(with: initV, insteadOf: typeS))
}

@available(*, unavailable, message: "Init parameters must match!")
func swapView<V, S, P>(_ initV : (P) -> V, insteadOf typeS: S.Type) -> some View
where S: View, S: Swappable,
V: View {
self
}
}

extension Swappable where Self: View {

var body: some View {
SwappedIfNeeded<Self>(input: input, content: defaultBody)
}
}
7 changes: 7 additions & 0 deletions Tests/LinuxMain.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import XCTest

import swappableTests

var tests = [XCTestCaseEntry]()
tests += swappableTests.allTests()
XCTMain(tests)
7 changes: 7 additions & 0 deletions Tests/SwappableTests/SwappableTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import XCTest
@testable import Swappable

final class SwappableTests: XCTestCase {

static var allTests: [(String, ()->())] = []
}
9 changes: 9 additions & 0 deletions Tests/SwappableTests/XCTestManifests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import XCTest

#if !canImport(ObjectiveC)
public func allTests() -> [XCTestCaseEntry] {
return [
testCase(swappableTests.allTests),
]
}
#endif

0 comments on commit 45deb50

Please sign in to comment.