|
@@ -11,6 +11,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate |
|
|
) -> Bool { |
|
|
) -> Bool { |
|
|
window = UIWindow(frame: UIScreen.main.bounds) |
|
|
window = UIWindow(frame: UIScreen.main.bounds) |
|
|
let vc = UIViewController() |
|
|
let vc = UIViewController() |
|
|
|
|
|
addSwiftUIViewAsChild(swiftUIView: V(), parent: vc.view) |
|
|
vc.view.backgroundColor = .gray |
|
|
vc.view.backgroundColor = .gray |
|
|
window?.rootViewController = vc |
|
|
window?.rootViewController = vc |
|
|
window?.backgroundColor = UIColor.white |
|
|
window?.backgroundColor = UIColor.white |
|
@@ -19,3 +20,132 @@ class AppDelegate: UIResponder, UIApplicationDelegate |
|
|
return true |
|
|
return true |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
|
|
// Bus.Pipe.swift |
|
|
|
|
|
public extension Bus { |
|
|
|
|
|
final class BindingPipe<T: Equatable>: ObservableObject { |
|
|
|
|
|
public let input = PassthroughSubject<T, Never>() |
|
|
|
|
|
public let output = PassthroughSubject<T, Never>() |
|
|
|
|
|
@Published var value: T |
|
|
|
|
|
var isInput = false |
|
|
|
|
|
var subscriptions = [AnyCancellable]() |
|
|
|
|
|
|
|
|
|
|
|
deinit { |
|
|
|
|
|
print("ИГР BusBP.DEinit(\(Unmanaged.passUnretained(self).toOpaque()))") |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
init( |
|
|
|
|
|
_ defaultValue: T, |
|
|
|
|
|
_ keyApp: String, |
|
|
|
|
|
_ keyUI: String |
|
|
|
|
|
) { |
|
|
|
|
|
value = defaultValue |
|
|
|
|
|
/**/dbg("ИГР BusBP.init(\(Unmanaged.passUnretained(self).toOpaque())) keyA: '\(keyApp)'") |
|
|
|
|
|
|
|
|
|
|
|
// TextField -> output. |
|
|
|
|
|
$value |
|
|
|
|
|
.sink { [weak self] v in |
|
|
|
|
|
assert(Thread.isMainThread) |
|
|
|
|
|
// Ignore values received from input. |
|
|
|
|
|
// Only accept UI provided values. |
|
|
|
|
|
guard |
|
|
|
|
|
let self, |
|
|
|
|
|
!self.isInput |
|
|
|
|
|
else { |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
self.output.send(v) |
|
|
|
|
|
} |
|
|
|
|
|
.store(in: &subscriptions) |
|
|
|
|
|
|
|
|
|
|
|
// input -> TextField. |
|
|
|
|
|
input |
|
|
|
|
|
.sink { [weak self] v in |
|
|
|
|
|
assert(Thread.isMainThread) |
|
|
|
|
|
guard let self else { return } |
|
|
|
|
|
/**/dbg("ИГР BusBP.init input: '\(v)'") |
|
|
|
|
|
self.isInput = true |
|
|
|
|
|
self.value = v |
|
|
|
|
|
self.isInput = false |
|
|
|
|
|
} |
|
|
|
|
|
.store(in: &subscriptions) |
|
|
|
|
|
|
|
|
|
|
|
// Оповещаем в мир об изменениях от UI. |
|
|
|
|
|
Bus.sendAsync( |
|
|
|
|
|
&subscriptions, |
|
|
|
|
|
keyUI, |
|
|
|
|
|
output.eraseToAnyPublisher() |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
Bus.receive( |
|
|
|
|
|
&subscriptions, |
|
|
|
|
|
[keyApp], |
|
|
|
|
|
{ [weak self] _, v in |
|
|
|
|
|
self?.input.send(v) |
|
|
|
|
|
/**/print("ИГР BusBP.init receive: '\(v)'") |
|
|
|
|
|
} |
|
|
|
|
|
) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// BusSlot.swift |
|
|
|
|
|
var busHolder = Bus.Service() |
|
|
|
|
|
|
|
|
|
|
|
// ======================================== |
|
|
|
|
|
// MARK: - MeetupX module |
|
|
|
|
|
// ======================================== |
|
|
|
|
|
|
|
|
|
|
|
enum MeetupId { |
|
|
|
|
|
enum Keys: String, RawRepresentable { |
|
|
|
|
|
case meetupIdTextApp |
|
|
|
|
|
case meetupIdTextUI |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static func shouldFormat(_ s: String) -> String? { |
|
|
|
|
|
return s.components(separatedBy: NSCharacterSet.decimalDigits.inverted).reduce("") { $0 + $1 } |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
final class MeetupIdFormatter { |
|
|
|
|
|
var subscriptions = [AnyCancellable]() |
|
|
|
|
|
|
|
|
|
|
|
deinit { |
|
|
|
|
|
/**/dbg("ИГР MeetupIF.DEinit") |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
init() { |
|
|
|
|
|
Bus.receive( |
|
|
|
|
|
&subscriptions, |
|
|
|
|
|
[Keys.meetupIdTextUI.rawValue], |
|
|
|
|
|
{ [weak self] k, v in self?.handleFormatting(k, v) } |
|
|
|
|
|
) |
|
|
|
|
|
/**/dbg("ИГР MeetupIF.init") |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func handleFormatting(_: String, _ value: String) { |
|
|
|
|
|
let out = MeetupId.shouldFormat(value) |
|
|
|
|
|
/**/dbg("ИГР MeetupIF.handleF out/dt: '\(out)'/'\(Date())'") |
|
|
|
|
|
Bus.Service.singleton?.send(Keys.meetupIdTextApp.rawValue, out) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
struct V: View { |
|
|
|
|
|
/*@StateObject*/ var fmt = MeetupIdFormatter() |
|
|
|
|
|
@StateObject var txt = Bus.BindingPipe("", Keys.meetupIdTextApp.rawValue, Keys.meetupIdTextUI.rawValue) |
|
|
|
|
|
|
|
|
|
|
|
var body: some View { |
|
|
|
|
|
VStack { |
|
|
|
|
|
Text("Hi, the text is: '\(txt.value)'") |
|
|
|
|
|
.fontWeight(.bold) |
|
|
|
|
|
TextField("Placeholder", text: $txt.value) |
|
|
|
|
|
.padding(8) |
|
|
|
|
|
.border(Color.blue, width: 2) |
|
|
|
|
|
} |
|
|
|
|
|
.frame(width: 320) |
|
|
|
|
|
.padding() |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |