Adding container view

This commit is contained in:
Selim Mustafaev 2023-08-01 17:53:24 +03:00
parent b28f77a8ab
commit b64927ebc2
4 changed files with 79 additions and 22 deletions

View File

@ -5,6 +5,9 @@ import PackageDescription
let package = Package( let package = Package(
name: "YadUI", name: "YadUI",
platforms: [
.iOS(.v16)
],
products: [ products: [
.library(name: "YadUI", targets: ["YadUI"]), .library(name: "YadUI", targets: ["YadUI"]),
], ],

View File

@ -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<Src, SrcView, Dst, DstView>(_ prop: ReferenceWritableKeyPath<SrcView,Src>,
to dstTag: Int,
dstProp: KeyPath<DstView,Published<Dst>.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
}
}

View File

@ -22,8 +22,6 @@ public class Stack: UIView {
private var allConstraints: [NSLayoutConstraint] = [] private var allConstraints: [NSLayoutConstraint] = []
private var cancellables: [AnyCancellable] = []
var dStart: NSLayoutConstraint.Attribute { var dStart: NSLayoutConstraint.Attribute {
axis == .vertical ? .top : .leading axis == .vertical ? .top : .leading
} }
@ -119,21 +117,4 @@ public class Stack: UIView {
addConstraint(src: lastView, srcAttr: dStart, dst: currentView, dstAttr: dEnd, constant: spacing) addConstraint(src: lastView, srcAttr: dStart, dst: currentView, dstAttr: dEnd, constant: spacing)
} }
@available(iOS 16.0.0, *)
public func bind<Src, Dst, U>(_ prop: ReferenceWritableKeyPath<Stack,Src>,
to dstTag: Int,
dstProp: KeyPath<U,Published<Dst>.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
}
} }

View File

@ -22,15 +22,19 @@ extension Stack.Alignment: InitConvertible {
class ViewController: UIViewController { class ViewController: UIViewController {
let child = TestView()
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
let child = buildView()
view.addSubview(child) view.addSubview(child)
child.pin(toSafeArea: view, insets: .init(all: 16)) child.pin(toSafeArea: view, insets: .init(all: 16))
} }
}
@RootViewBuilder func buildView() -> UIView { class TestView: ContainerView {
override func getBody() -> UIView {
VStack(alignment: .start, spacing: 16) { VStack(alignment: .start, spacing: 16) {
UILabel() UILabel()
.text("qwe") .text("qwe")
@ -45,7 +49,7 @@ class ViewController: UIViewController {
YASegmentedControl(items: ["Left", "Center", "Right"]) YASegmentedControl(items: ["Left", "Center", "Right"])
.tag(100) .tag(100)
} }
.bind(\.alignment, to: 100, dstProp: \YASegmentedControl.$selectedIndex) .bind(\VStack.alignment, to: 100, dstProp: \YASegmentedControl.$selectedIndex)
} }
} }