d
This commit is contained in:
@@ -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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|||||||
54
src/MeetupId.swift
Normal file
54
src/MeetupId.swift
Normal file
@@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
10
src/VM.swift
10
src/VM.swift
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user