Skip to content

Instantly share code, notes, and snippets.

@neknalb
Created July 29, 2022 17:33
Show Gist options
  • Save neknalb/c89a13b3bffc17ed4f08ff4176dc35e1 to your computer and use it in GitHub Desktop.
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
// 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