@@ -3,6 +3,7 @@ import UIKit | |||||
@UIApplicationMain | @UIApplicationMain | ||||
class AppDelegate: UIResponder, UIApplicationDelegate | class AppDelegate: UIResponder, UIApplicationDelegate | ||||
{ | { | ||||
let bus = Bus.Service() | |||||
var window: UIWindow? | var window: UIWindow? | ||||
func application( | func application( | ||||
@@ -89,63 +90,4 @@ public extension Bus { | |||||
} | } | ||||
} | } | ||||
} | } | ||||
// 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() | |||||
} | |||||
} | |||||
} | |||||
*/ | */ |
@@ -0,0 +1,54 @@ | |||||
import Foundation | |||||
enum MeetupId { | |||||
enum Keys: String, RawRepresentable { | |||||
case meetupIdTextApp | |||||
case meetupIdTextUI | |||||
} | |||||
static func shouldFormat(_ s: String) -> String? { | |||||
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() | |||||
} | |||||
} | |||||
*/ | |||||
} |
@@ -7,29 +7,21 @@ final class VM: ObservableObject { | |||||
var subscriptions = Set<AnyCancellable>() | var subscriptions = Set<AnyCancellable>() | ||||
init() { | init() { | ||||
// Уведомляем об изменении текста. | |||||
$text | |||||
.sink { [weak self] v in self?.changeText.send(v) } | |||||
.store(in: &subscriptions) | |||||
// Интерпретируем текст с задержкой, потому что: | // Интерпретируем текст с задержкой, потому что: | ||||
// 1. смена @Published в ту же секунду игнорируется | // 1. смена @Published в ту же секунду игнорируется | ||||
// полем ввода, т.е. нужна задержка | // полем ввода, т.е. нужна задержка | ||||
// 2. ожидаем окончания ввода (спама), чтобы | // 2. ожидаем окончания ввода (спама), чтобы | ||||
// обработать введённое без потерь из-за конфликта | // обработать введённое без потерь из-за конфликта | ||||
// старых данных и новых. | // старых данных и новых. | ||||
changeText | |||||
$text | |||||
.debounce(for: .seconds(0.3), scheduler: DispatchQueue.main) | .debounce(for: .seconds(0.3), scheduler: DispatchQueue.main) | ||||
.sink { [weak self] v in | .sink { [weak self] v in | ||||
/* | |||||
guard | guard | ||||
let out = MeetupId.shouldFormat(v), | let out = MeetupId.shouldFormat(v), | ||||
v != out | v != out | ||||
else { | else { | ||||
return | return | ||||
} | } | ||||
*/ | |||||
let out = v | |||||
/**/print("ИГР TFCVM.init changeT in/out: '\(v)'/'\(out)'") | /**/print("ИГР TFCVM.init changeT in/out: '\(v)'/'\(out)'") | ||||
self?.text = out | self?.text = out | ||||
} | } | ||||