Swift - How to get text formatting in a text editor like in the notes app? SwiftUI
You can create a custom TextView UIViewRepresentable and set allowsEditingTextAttributes to true there:
create a new Swift file called TextView.swift
import SwiftUI
struct TextView: UIViewRepresentable {
@Binding var attributedText: NSMutableAttributedString
@State var allowsEditingTextAttributes: Bool = false
@State var font: UIFont?
func makeUIView(context: Context) -> UITextView {
UITextView()
}
func updateUIView(_ uiView: UITextView, context: Context) {
uiView.attributedText = attributedText
uiView.allowsEditingTextAttributes = allowsEditingTextAttributes
uiView.font = font
}
}
Then you can add it to your content view:
import SwiftUI
struct ContentView: View {
@State var attributedText = NSMutableAttributedString(string: "")
var body: some View {
TextView(attributedText: $attributedText, allowsEditingTextAttributes: true, font: .systemFont(ofSize: 32))
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
SwiftUI TextEditor - save the state after completion of editing
I don't know exactly what you mean to save once the editing is done. Here are two possible approaches I found.
Note:
In the following demos, the text with blue background displays the saved text.
1. Saving when user dismisses keyboard
Solution: Adding a tap gesture to let users dismiss the keyboard when tapped outside of the TextEditor
. Call save()
at the same time.
Code:
struct ContentView: View {
@State private var text: String = ""
@State private var savedText: String = ""
var body: some View {
VStack(spacing: 20) {
Text(savedText)
.frame(width: 300, height: 200, alignment: .topLeading)
.background(Color.blue)
TextEditor(text: $text)
.frame(width: 300, height: 200)
.border(Color.black, width: 1)
.onTapGesture {}
}
.onTapGesture { hideKeyboardAndSave() }
}
private func hideKeyboardAndSave() {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
save()
}
private func save() {
savedText = text
}
}
2. Saving after no changes for x seconds
Solution: Using Combine
with .debounce
to publish and observe only after x
seconds have passed with no further events.
I have set x
to 3.
Code:
struct ContentView: View {
@State private var text: String = ""
@State private var savedText: String = ""
let detector = PassthroughSubject<Void, Never>()
let publisher: AnyPublisher<Void, Never>
init() {
publisher = detector
.debounce(for: .seconds(3), scheduler: DispatchQueue.main)
.eraseToAnyPublisher()
}
var body: some View {
VStack(spacing: 20) {
Text(savedText)
.frame(width: 300, height: 200, alignment: .topLeading)
.background(Color.blue)
TextEditor(text: $text)
.frame(width: 300, height: 200)
.border(Color.black, width: 1)
.onChange(of: text) { _ in detector.send() }
.onReceive(publisher) { save() }
}
}
private func save() {
savedText = text
}
}
SwiftUI - how to copy text to clipboard?
Use the following - put shown text into pasteboard for specific type (and you can set as many values and types as needed)
Update: for Xcode 13+, because of "'kUTTypePlainText' was deprecated in iOS 15.0..." warning
import UniformTypeIdentifiers
Text(self.BLEinfo.sendRcvLog)
.onTapGesture(count: 2) {
UIPasteboard.general.setValue(self.BLEinfo.sendRcvLog,
forPasteboardType: UTType.plainText.identifier)
}
for older versions:
import MobileCoreServices // << for UTI types
// ... other code
Text(self.BLEinfo.sendRcvLog)
.onTapGesture(count: 2) {
UIPasteboard.general.setValue(self.BLEinfo.sendRcvLog,
forPasteboardType: kUTTypePlainText as String)
}
Using iOS 5 rich text editor
The iOS 5 rich text edit control is also present in the notes app in iOS 4 (make a rich text note on the computer and sync it to see).
This is a custom Apple-made control which they use in their own apps, but it is not published in any official developer API. It's probably in the SDK somewhere, but because it is undocumented, even if you find it and use it, Apple will reject your app.
Basically, if you want a rich text control you will have to make your own.
Edit: Try using this: https://github.com/omnigroup/OmniGroup/tree/master/Frameworks/OmniUI/iPad/Examples/TextEditor/. I haven't used it, so I don't know how well it will work. (Link from this question)
How to use Attributed String in SwiftUI
iOS 15 and Swift 5.5
Text
now supports markdown and also you can create custom attributes:
You can even get defined attributes remotely like:
iOS 13 and 14
You can combine multiple Text
objects together with a simple +
operator and that will handle some of the attributions:
Each one can have multiple and specific modifiers
A fully supported fallback!
Since it doesn't support directly on Text
(till iOS 15), you can bring the UILabel
there and modify it in anyway you like:
Implementation:
struct UIKLabel: UIViewRepresentable {
typealias TheUIView = UILabel
fileprivate var configuration = { (view: TheUIView) in }
func makeUIView(context: UIViewRepresentableContext<Self>) -> TheUIView { TheUIView() }
func updateUIView(_ uiView: TheUIView, context: UIViewRepresentableContext<Self>) {
configuration(uiView)
}
}
Usage:
var body: some View {
UIKLabel {
$0.attributedText = NSAttributedString(string: "HelloWorld")
}
}
Related Topics
How to Migrate Core Data's Data to App Group's Data
Properly Using Firebase Cloud Functions and Stripe
How to Call a Generic Swift Function When None of the Arguments Provides the Generic Type
Xcode Error - Undefined Symbols for Architecture X86_64
Correct Way to Call "Realloc" in Swift with a Float Array
How to Detect If a Observable Has Not Emitted Any Events for Specific Time in Rxswift
Safari App Extension Crashes After a Few Seconds for Hello World Project
Updating Fetchedresultscontroller for Predicate Set by Uisearchbar
Swift Get Nsdata of a Video from Photos Library
Loop Over Multiple Uialertcontroller'S
Nstableview Inside Nspopover Looks Different as Standalone
Dynamic Uicollectionview Inside Dynamic Uitableviewcell
Swift Convert Decimal Coordinate into Degrees, Minutes, Seconds, Direction
Firebase Auth Internal Error on Login Attempt