-1

I am trying to make an app similar to Notes app. I have a UITextView to display NSAttributedString. I am able to add photos using NSTextAttachment and it all works fine.

Now when a user taps on a photo, I want to present a new UIViewController which will show the desired photo in full screen. How do I achieve this? Notes app has this exact behaviour.

FE_Tech
  • 1,534
  • 13
  • 25
  • Does this answer your question? [How to detect touch on NSTextAttachment](https://stackoverflow.com/questions/19318092/how-to-detect-touch-on-nstextattachment) – chirag90 Feb 05 '20 at 13:28
  • It's not possible with UITextView. If you want to click on image, then you need to stop UITextView user interaction. If you stop interaction, then UITextView is not editable. So with UITextView you are unable to achieve your requirement. It's waste of time. Notes app functionality is different. It uses textview, but not fully. – phani Feb 05 '20 at 13:33

1 Answers1

1

Here is what I did once I get the image from didFinishPickingMediaWithInfo I get the image URL

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        picker.dismiss(animated: true)
        //1 Make a NSAttachmentVariable
        let attachment = NSTextAttachment()
        guard let image = info[.editedImage] as? UIImage else {
            print("No image found")
            return
        }
        //2 get the ImageURL
        guard let imageURL = info[.imageURL] as? URL else  {
            print("No url")
            return
        }
        //3 optional Resize the image
        let resizedImage =  self.resizeImage(image: image, targetSize: CGSize(width: txtView.frame.size.width, height: 200))
        //4 add the fetched image to the attachment created earlier to display on text view
        attachment.image = resizedImage
        //5 insert the attachment to the textview
        let attString = NSMutableAttributedString(attachment: attachment)
        txtView.textStorage.insert(attString, at: txtView.selectedRange.location)
        //6 get the range of the whole image from the textview string
        let range = NSString(string: attString.string).range(of: attString.string, options: String.CompareOptions.caseInsensitive)

        //7 add the fetched image url we got earlier at //2 to the attachment 
        attString.addAttribute(.link, value: imageURL, range: range)
        //8 add the attributed text to the text view
        txtView.attributedText = attString

    }

Now use shouldInteractWith from textview to open the image from the url don't forget to add UITextViewDelegate as an extension to your controller

 func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
        let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
        let newViewController = storyBoard.instantiateViewController(withIdentifier: "Details") as! DetailsImage
        let data = try? Data(contentsOf: URL)

        if let imageData = data {
            newViewController.image = UIImage(data: imageData)!
        }

        self.present(newViewController, animated: true, completion: nil)

        //UIApplication.shared.open(URL)
        return false
    }

This is used to open urls from your text view now we are using the url we got, changing it to data and setting an image variable from another view controller to the returned data

Here is the other viewController


 import UIKit
  class DetailsImage: UIViewController{

    var image = UIImage()
    @IBOutlet weak var imgView: UIImageView!
    override func viewDidLoad() {
        imgView.image = image
    }
 }


IMPORTANT Note:

The tap cannot be very brief, which means quick taps are ignored by iOS. If you find this annoying you might consider something like this: https://gist.github.com/benjaminbojko/c92ac19fe4db3302bd28.

That's it U can set navigation button on the newly opened VC to go back to the vc of the textView