読者です 読者をやめる 読者になる 読者になる

【swift】uitextviewで文字数を制限したテキストコピーを実装

はじめに

uitextviewにコンテンツを表示。コンテンツの内容はコピー可能だけど全文を一括ではコピーできないようにしたい
ということでした

実装手順としては
・uitextviewのUIMenuControllerを無効にしてコピーできなくする
・文字数制限してコピー可能なUIMenuControllerを実装

実装

import UIKit

class ViewController: UIViewController, UITextViewDelegate {
    
    var textView: CustomTextView!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        textView = CustomTextView(frame: CGRectMake(10, 50, view.frame.width - 20, 500))
        textView.text = "あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめも"
        textView.delegate = self
        textView.editable = false
        view.addSubview(textView)
        
        // UIMenuControllerをカスタマイズ
        let menuItem: UIMenuItem = UIMenuItem(title: "コピー", action: #selector(ViewController.textCopy(_:)))
        UIMenuController.sharedMenuController().menuItems = [menuItem]
        UIMenuController.sharedMenuController().update()
    }
    
    // 「コピー」メニュー以外は無効に
    override func canPerformAction(action: Selector, withSender sender: AnyObject?) -> Bool {
        if action == #selector(ViewController.textCopy(_:)) {
            return true
        } else {
            return false
        }
    }
    
    // コピーメニュー時の処理を実装
    func textCopy(sender: AnyObject) {
        // uitextviewの選択中の文字列を取得
        let location = textView.selectedRange.location
        let length = textView.selectedRange.length
        let text = (textView.text as NSString).substringWithRange(NSRange(location:location,length: length))

        // 30文字以下の場合のみクリップボードにコピー
        if text.characters.count <= 30 {
            let pasteboard = UIPasteboard.generalPasteboard()
            pasteboard.setValue(text, forPasteboardType: "public.text")
        }
    }
}

class CustomTextView: UITextView {
    // 既存のUIMenuControllerを無効に
    override func canPerformAction(action: Selector, withSender sender: AnyObject?) -> Bool {
        return false
    }
}

以上です