将文本块粘贴到 UITextView 中时会触发什么事件?粘贴文本时我需要修改 textView 的框架。
这是我用来检测 UITextView 中的粘贴事件的方法:
// Set this class to be the delegate of the UITextView. Now when a user will paste a text in that textview, this delegate will be called.
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
// Here we check if the replacement text is equal to the string we are currently holding in the paste board
if ([text isEqualToString:[UIPasteboard generalPasteboard].string]) {
// code to execute in case user is using paste
} else {
// code to execute other wise
}
return YES;
}
如果粘贴板中有长句子,则通过
if string == UIPasteboard.general.string
检查粘贴板的字符串需要几秒钟。进行此检查时,用户会看到键盘被冻结。
我的解决办法是检查新字符的长度是否大于1。
如果它长于 1,则该字符串来自粘贴板。
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if string.characters.count > 1{
//User did copy & paste
}else{
//User did input by keypad
}
return true
}
你的 UITextView 将调用它的 UITextViewDelegate 方法
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
如果已设立代表。当在键盘上键入字符时以及将文本粘贴到文本视图中时都会调用此函数。粘贴的文本是 replacementText 参数。
尝试子类化 UITextview,并重写此函数。
public override func paste(_ sender: Any?)
这在
中运行完美Xcode 11x 迅捷 5x
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if text.contains(UIPasteboard.general.string ?? "") {
return false
}
return true
}
当用户尝试粘贴到文本字段时,if条件将执行
此代码将停止粘贴
适用于 Swift5.1
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if let paste = UIPasteboard.general.string, text == paste {
print("paste")
} else {
print("normal typing")
}
return true
}
textView(_, shouldChangeTextIn, replacementText)
。如果您每次都会读取 UIPasteboard.general.string
值,用户将看到系统警报,表明应用程序在输入每个字母后访问了粘贴板。
为了避免这个问题,你可以创建 UITextView 的子类并覆盖其中的
paste(_)
函数。每次用户尝试粘贴内容时,系统都会调用此函数一次。
使用下一次调用
textView(_, shouldChangeTextIn, replacementText)
来处理粘贴事件。
var isPastingContent = false // helper variable
open override func paste(_ sender: Any?) {
isPastingContent = true // next call of `shouldChangeTextIn` will be for the paste action
super.paste(sender)
}
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if isPastingContent { // if we detected paste event
// paste detected, do what you want here
let pasteboardContent = UIPasteboard.general.string // you can get pasteboard content here safely. System alert will be shown only once.
isPastingContent = false // toggle helper value back to false
}
}
carlos16196 是一个很好的方法,但我也会通过将
[text isEqualToString:[UIPasteboard generalPasteboard].string]
更改为 [text containsString:[UIPasteboard generalPasteboard].string]
来调整它
通过这样做,您将检测用户何时在文本视图中粘贴不在 UIPasteboard 中的其他键入文本之后。
这是代码:
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
// Here we check if the replacement text is equal to the string we are currently holding in the paste board
if ([text containsString:[UIPasteboard generalPasteboard].string]) {
// code to execute in case user is using paste
} else {
// code to execute other wise
}
return YES;
}
iOS 13 与
Combine
public extension UITextView {
var textDidChangePublisher: AnyPublisher<String, Never> {
NotificationCenter.default
.publisher(for: UITextView.textDidChangeNotification, object: self)
.compactMap { $0.object as? UITextView }
.compactMap(\.text)
.eraseToAnyPublisher()
}
var attributedTextDidChangePublisher: AnyPublisher<NSAttributedString, Never> {
NotificationCenter.default
.publisher(for: UITextView.textDidChangeNotification, object: self)
.compactMap { $0.object as? UITextView }
.compactMap(\.attributedText)
.eraseToAnyPublisher()
}
}
var cancellable = Set<AnyCancellable>()
textView.textDidChangePublisher
.removeDuplicates()
.sink { [weak self] newValue in
guard let self = self else { return }
// what you want
}
.store(in: &cancellable)
这是我能够让它发挥作用的唯一方法。我使用了文本字段,但相同的概念仍然适用于文本视图。
在下面的
shouldChangeCharactersIn
委托方法中,我将 string
参数转换为 NSString,然后又转换回 String。然后我将它与粘贴的任何内容进行比较。其他所有内容都在代码上方的注释中。
// 1. class property for anything that was copied and will be pasted
var pasted: String?
// 2. When the user first taps the textfield set the above class property to the copied text (if there is any)
func textFieldDidBeginEditing(_ textField: UITextField) {
// 3. set it here
pasted = UIPasteboard.general.string // this is what was copied and will be pasted
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
guard let safeText = textField.text else { return true }
let currentString: NSString = safeText as NSString
let newString: NSString = currentString.replacingCharacters(in: range, with: string) as NSString
let str = newString as String
// 4. compare the above str constant to the pasted variable
if str == self.pasted {
print("pasted")
} else {
print("typed")
}
return true
}
func textFieldDidEndEditing(_ textField: UITextField) {
// 5. when the user is finished with the textField set the pasted property to nil
pasted = nil
}
这就是我用来检测粘贴图像的方法:
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
if (UIPasteboard.generalPasteboard.image &&
[UIPasteboard.generalPasteboard.string.lowercaseString isEqualToString:text.lowercaseString]) {
//Pasted image
return NO;
}
return YES;
}
在 SWIFT 4 中:
func textViewDidChange(_ textView: UITextView) {
if(textView.text == UIPasteboard.general.string)
{
//Text pasted
}
}