/JNMentionTextView

A powerful UITextView supporting special characters such as [ #, @ ] as Smart Fields

Primary LanguageSwiftMIT LicenseMIT

JNMentionTextView

CI Status Version License Platform

JNMentionTextView A subclass of UITextView providing a ‘Mention’ annotations in to your iOS app; Annotations which refers to names of individuals or entities and treated as a single unit and can be styled differently from the rest of the text.

Preview

Requirements

  • Xcode 14.3.1
  • iOS 11.0+
  • Swift 5.8+

Installation

JNMentionTextView is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod 'JNMentionTextView'

Usage:

  • Import JNMentionTextView module
import JNMentionTextView
  • Initalization:

    • Storyboard: Manually, you can add a UITextView instance to your Xib, set 'JNMentionTextView' class and connect @IBOutlet reference.

    • Programmatically: Init ‘JNMentionTextView’ UITextView instance programatically.

    let textView = JNMentionTextView()
    self.view.addSubview(textView)
  • Setup:

    • Setup the mention replacements: as dictionary of special characters used in mention process [ #, @ ] with their crossponding style.
    self.textView.mentionReplacements = ["@": [NSAttributedString.Key.foregroundColor: UIColor.blue,NSAttributedString.Key.font: UIFont.systemFont(ofSize: 17.0)]]
    • Setup the placeHolder : Custom Textview that has a placeholder with their corresponding style.

    • Setup the data list: The list of entities that you can select, as instance of class / struct which confirms to the JNMentionPickable protocol by implementing his methods:

      • getPickableTitle: return the title of entities which you can select.
      getPickableTitle() -> String
      • getPickableIdentifier: used to uniquely identify the entities - Entity id -.
      getPickableIdentifier() -> String
    • Setup the data list picker options:

       self.textView.setup(options: JNMentionOptions()
      • Options Customization: Customize the data list apperance (Picker View):

        • backgroundColor: picker view background color.
        • viewPositionMode: can support one or more of three view modes:
          • Up
          • Down
          • Automatic
          JNMentionOptions(
           backgroundColor: UIColor.white,
           viewPositionMode: JNMentionPickerViewPositionwMode.automatic)

JNMentionTextViewDelegate

  • Your class must use the JNMentionTextViewDelegate Protocol and conform to it by implementing its required methods in JNMentionTextViewDelegate:
self.textView.mentionDelegate = self
  • Retrieve Data For Symbol: In this method retrieve data of JNMentionPickable objects as the data list to be picked according to search text that had been typed in textview also this opeartion will be async and the loading activity indictor will appear in Picker view.
func jnMentionTextView(retrieveDataFor symbol: String, using searchString: String, compliation: (([JNMentionPickable]) -> ()) {
     var data = self.data[symbol] ?? []
     if !searchString.isEmpty {
         data = data.filter({ $0.getPickableTitle().lowercased().contains(searchString.lowercased())})
     }
     
     return compliation(data)
 }
  • Get Mention Item For Symbol: In this method retrieve JNMentionPickable object to be converted to mention annotation in the setSmartText method
 func jnMentionTextView(getMentionItemFor symbol: String, id: String) -> JNMentionPickable? {
     for item in self.data[symbol] ?? [] {
         if item.getPickableIdentifier() == id {
             return item
         }
     }
     
     return nil
 }
  • Get Source ViewController For PickerView to be presented on: In this method return the super view controller to present the picker data list Viewcontroller (Popover view controller)
     func sourceViewControllerForPickerView() -> UIViewController {
         return self
     }
  • Height For Picker View Controller : Optional method to return the height of data picker list.

       func heightForPickerView() -> CGFloat {
           return 100.0
       }
  • Custom Picker TableViewCell: Optional method to return your custom UITableViewCell for the data picker list, if didn't implement this method we use our TableViewCell.

       func cell(for item: JNMentionEntityPickable, tableView: UITableView) -> UITableViewCell {
           let cell = UITableViewCell()
           cell.textLabel?.text = item.getPickableTitle()
           return cell
       }

    Important: To Register Your custom cell use this Method:

        public func registerTableViewCell(_ nib: UINib?, forCellReuseIdentifier identifier: String) 
  • Height For Picker TableViewCell: Optional method to return the height of UITableViewCell in the data picker list.

       func heightForCell(for item: JNMentionEntityPickable, tableView: UITableView) -> CGFloat {
           return 50.0
       }

Helper Methods:

  • Retrieve Mention List: You can retrieve the list of mentioned items with their range (location, length) and special symbol string in TextView by calling the class method in the JNMentionTextView:
   getMentionedItems(from attributedString: NSAttributedString, symbol: String = "") -> [JNMentionEntity]
  • Get Smart Replacement: Used to retrieve smart attributed string (encrich string with mention annotations) from a simple string contains special characters with unique pickable ids: as an example:
    Consider the String as template that retured from the BackEnd has this format and want to set this in textview to be readable with smart fields:

  • This agreement is made between @client_name and @compnay_name

  • And the Smart Fields are:

    • client_name
    • compnay_name
  • This Class methods will help you to genereate the attributtedstring to be used to set the attributtedString in TextView

    getSmartReplacement(text: String, data: [String: [JNMentionPickable]], normalAttributes: [NSAttributedString.Key: Any],       mentionReplacements: [String: [NSAttributedString.Key : Any]]) -> NSAttributedString
  • Resign First Responder: This method is a wrapper of resignFirstResponder for UITextView, but it handle the dismissal of Picker ViewController

        public func resignFirstResponder(completion: (() -> ())? = nil)

Example

To run the example project, clone the repo, and run pod install from the Example directory first.

Author

Jayel Zaghmoutt, Mohammad Nabulsi & Mohammad Ihmouda

License

JNMentionTextView is available under the MIT license. See the LICENSE file for more info.