Adding container view
This commit is contained in:
parent
b28f77a8ab
commit
b64927ebc2
@ -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"]),
|
||||||
],
|
],
|
||||||
|
|||||||
69
Sources/YadUI/Views/ContainerView.swift
Normal file
69
Sources/YadUI/Views/ContainerView.swift
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,16 +21,20 @@ 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))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestView: ContainerView {
|
||||||
|
|
||||||
@RootViewBuilder func buildView() -> UIView {
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user