Created
July 29, 2022 17:33
-
-
Save neknalb/c89a13b3bffc17ed4f08ff4176dc35e1 to your computer and use it in GitHub Desktop.
Using Combine with debounce to update document model when editing NSAttributedString in view
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// MARK: - Model | |
struct DocumentData: Codable { | |
var title: String | |
var blocks: Array<Block> | |
... | |
} | |
// MARK: - View | |
struct DocumentView: View { | |
@Binding var documentData: DocumentData | |
@StateObject private var vm = DocumentViewViewModel() | |
init(documentData: Binding<DocumentData>) { | |
_documentData = documentData | |
} | |
var body: some View { | |
VStack { | |
TextField("Document Title", text: $documentData.title) | |
.multilineTextAlignment(.center) | |
TextView(attributedString: $vm.attributedString) | |
.onChange(of: vm.blocks, perform: | |
{ newValue in | |
print("onChange of attributedString: Update documentData.blocks accordingly") | |
documentData.blocks = newValue | |
}) | |
.onAppear { | |
print("onAppear: Create attributedString from blocks") | |
vm.attributedString = DocumentViewViewModel.attributedStringFromBlocks(documentData.blocks) | |
} | |
Spacer() | |
} | |
} | |
} | |
struct DocumentView_Preview: PreviewProvider { | |
static var previews: some View { | |
DocumentView(documentData: .constant(DocumentData.sampleData)) | |
} | |
} | |
// MARK: - ViewModel | |
import Combine | |
class DocumentViewViewModel: ObservableObject { | |
@Published var blocks = [Block]() | |
@Published var attributedString = NSAttributedString(string: "No text so far.") | |
private var cancellables = Set<AnyCancellable>() | |
init() { | |
$attributedString | |
.dropFirst() // Do we need that? | |
.debounce(for: 0.5, scheduler: RunLoop.main) | |
.sink(receiveValue: {[weak self] newValue in | |
self?.blocks = DocumentViewViewModel.blocksFromAttributedString(newValue) | |
}) | |
.store(in: &cancellables) | |
} | |
static func blocksFromAttributedString(_ attributedString: NSAttributedString) -> [Block] { | |
... | |
} | |
static func attributedStringFromBlocks(_ blocks: [Block]) -> NSAttributedString { | |
... | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment