From b64927ebc2f0ca7aa734d3d005bc7dffa554a5d2 Mon Sep 17 00:00:00 2001 From: Selim Mustafaev Date: Tue, 1 Aug 2023 17:53:24 +0300 Subject: [PATCH] Adding container view --- Package.swift | 3 ++ Sources/YadUI/Views/ContainerView.swift | 69 ++++++++++++++++++++++++ Sources/YadUI/Views/Stack/Stack.swift | 19 ------- YadUIDemo/YadUIDemo/ViewController.swift | 10 ++-- 4 files changed, 79 insertions(+), 22 deletions(-) create mode 100644 Sources/YadUI/Views/ContainerView.swift diff --git a/Package.swift b/Package.swift index 3bc8a33..40fa53c 100644 --- a/Package.swift +++ b/Package.swift @@ -5,6 +5,9 @@ import PackageDescription let package = Package( name: "YadUI", + platforms: [ + .iOS(.v16) + ], products: [ .library(name: "YadUI", targets: ["YadUI"]), ], diff --git a/Sources/YadUI/Views/ContainerView.swift b/Sources/YadUI/Views/ContainerView.swift new file mode 100644 index 0000000..33c0b1c --- /dev/null +++ b/Sources/YadUI/Views/ContainerView.swift @@ -0,0 +1,69 @@ +// +// ContainerView.swift +// +// +// Created by Мустафаев Селим Мустафаевич on 01.08.2023. +// + +import UIKit +import Combine + +open class ContainerView: UIView { + + private var body: UIView = UIView() + public var cancellables: [AnyCancellable] = [] + + public override init(frame: CGRect) { + super.init(frame: frame) + + translatesAutoresizingMaskIntoConstraints = false + + body = getBody() + body.translatesAutoresizingMaskIntoConstraints = false + addSubview(body) + body.pin(to: self) + } + + required public init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @RootViewBuilder open func getBody() -> UIView { + UIView() + } +} + +extension UIView { + + private func findContainer() -> ContainerView? { + + var currentView: UIView = self + while currentView.superview != nil { + if currentView is ContainerView { + return currentView as? ContainerView + } + currentView = currentView.superview! + } + + return nil + } + + public func bind(_ prop: ReferenceWritableKeyPath, + to dstTag: Int, + dstProp: KeyPath.Publisher>) -> Self where SrcView: UIView, Src: InitConvertible, Src.Param == Dst { + + guard let container = findContainer(), let srcView = self as? SrcView else { + return self + } + + guard let view = container.viewWithTag(dstTag) as? DstView else { + return self + } + + let pub = view[keyPath: dstProp].map { Src($0) } + pub.assign(to: prop, on: srcView) + .store(in: &container.cancellables) + + return self + } +} diff --git a/Sources/YadUI/Views/Stack/Stack.swift b/Sources/YadUI/Views/Stack/Stack.swift index b0b52b5..70d7d9b 100644 --- a/Sources/YadUI/Views/Stack/Stack.swift +++ b/Sources/YadUI/Views/Stack/Stack.swift @@ -22,8 +22,6 @@ public class Stack: UIView { private var allConstraints: [NSLayoutConstraint] = [] - private var cancellables: [AnyCancellable] = [] - var dStart: NSLayoutConstraint.Attribute { axis == .vertical ? .top : .leading } @@ -119,21 +117,4 @@ public class Stack: UIView { addConstraint(src: lastView, srcAttr: dStart, dst: currentView, dstAttr: dEnd, constant: spacing) } - - @available(iOS 16.0.0, *) - public func bind(_ prop: ReferenceWritableKeyPath, - to dstTag: Int, - dstProp: KeyPath.Publisher>) -> Self where Src: InitConvertible, Src.Param == Dst { - - // TODO: search relative to root view - guard let view = viewWithTag(dstTag) as? U else { - return self - } - - let pub = view[keyPath: dstProp].map { Src($0) } - pub.assign(to: prop, on: self) - .store(in: &cancellables) - - return self - } } diff --git a/YadUIDemo/YadUIDemo/ViewController.swift b/YadUIDemo/YadUIDemo/ViewController.swift index ecb48d8..dc31685 100644 --- a/YadUIDemo/YadUIDemo/ViewController.swift +++ b/YadUIDemo/YadUIDemo/ViewController.swift @@ -21,16 +21,20 @@ extension Stack.Alignment: InitConvertible { } class ViewController: UIViewController { + + let child = TestView() override func viewDidLoad() { super.viewDidLoad() - let child = buildView() view.addSubview(child) child.pin(toSafeArea: view, insets: .init(all: 16)) } +} + +class TestView: ContainerView { - @RootViewBuilder func buildView() -> UIView { + override func getBody() -> UIView { VStack(alignment: .start, spacing: 16) { UILabel() .text("qwe") @@ -45,7 +49,7 @@ class ViewController: UIViewController { YASegmentedControl(items: ["Left", "Center", "Right"]) .tag(100) } - .bind(\.alignment, to: 100, dstProp: \YASegmentedControl.$selectedIndex) + .bind(\VStack.alignment, to: 100, dstProp: \YASegmentedControl.$selectedIndex) } }