UITextView 延迟滚动添加图像
UITextView lags scrolling with added images
我有一个 UITextView
,我可以在其中添加图像,使用 ImagePickerController。
如果里面只有文字,它是流畅的,但在添加 3 或 4 张图片后,它在内容中滚动时变得迟钝。
我在添加图像时将其压缩到最低质量,但我一定是做错了什么,因为它仍然滞后于第三张图像。
代码如下:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
guard let _image = info[UIImagePickerControllerOriginalImage] as? UIImage else { return }
self.dismiss(animated: true, completion: nil)
// Compress the retrieved image
let compressedImage = UIImage(data: _image.lowestQualityJPEGNSData!)
//create and NSTextAttachment and add your image to it.
let attachment = NSTextAttachment()
let oldWidth = compressedImage?.size.width // scales it within the UITextView
let scaleFactor = oldWidth! / (bodyEditText.frame.size.width - 10); // adjusts the desired padding
attachment.image = UIImage(cgImage: (compressedImage?.cgImage!)!, scale: scaleFactor, orientation: .up)
//put your NSTextAttachment into and attributedString
let attString = NSAttributedString(attachment: attachment)
//add this attributed string to the current position.
bodyEditText.textStorage.insert(attString, at: bodyEditText.selectedRange.location)
}
extension UIImage {
var uncompressedPNGData: Data? { return UIImagePNGRepresentation(self) }
var highestQualityJPEGNSData: Data? { return UIImageJPEGRepresentation(self, 1.0) }
var highQualityJPEGNSData: Data? { return UIImageJPEGRepresentation(self, 0.75) }
var mediumQualityJPEGNSData: Data? { return UIImageJPEGRepresentation(self, 0.5) }
var lowQualityJPEGNSData: Data? { return UIImageJPEGRepresentation(self, 0.25) }
var lowestQualityJPEGNSData:Data? { return UIImageJPEGRepresentation(self, 0.0) }
}
可能是什么原因导致了这个问题以及如何解决这个问题?
感谢您的帮助
编辑
多亏了 Duncan C,我已经设法消除了整个延迟并大大提高了渲染图像的性能。
因此,我已将我的 imagePickerController
替换为以下内容:
let size = __CGSizeApplyAffineTransform(_image.size, CGAffineTransform.init(scaleX: 0.3, y: 0.3))
let hasAlpha = false
let scale: CGFloat = 0.0 // Automatically use scale factor of main screen
UIGraphicsBeginImageContextWithOptions(size, !hasAlpha, scale)
_image.draw(in: CGRect(origin: CGPoint.zero, size: size))
let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
let att = NSTextAttachment()
att.image = scaledImage
//put your NSTextAttachment into and attributedString
let attString = NSAttributedString(attachment: att)
//add this attributed string to the current position.
bodyEditText.textStorage.insert(attString, at: bodyEditText.selectedRange.location)
你误用了比例因子。这是为了处理正常、视网膜和@3x 视网膜图像的 1x、2x 和 3x 缩放。
按照您的操作方式,系统每次要绘制一个图像时都必须将全尺寸图像渲染到您的边界矩形中。如果图像比您显示的尺寸大得多,则会浪费大量内存和处理时间。
首先尝试简单地将图像视图的 contentMode
设置为 .scaleAspectFit
并在图像视图中安装原始图像,而不要乱用比例因子。看看它的表现如何。
如果这不能提供可接受的性能,您应该将起始图像渲染到屏幕外图形上下文中,该上下文是图像的目标大小,并将重新渲染的图像安装到图像视图中。您可以使用 UIGraphicsBeginImageContextWithOptions()
或各种其他技术来调整图像的大小以供显示。
查看此 link 以获取有关图像缩放和调整大小的信息:
这样做不是最佳做法。 UITextViews 适用于文本而非所有视图。
您需要制作一个自定义 UIView,其中包含 1、textview 2、UICollectionView 用于大量图像。
通过这种方式,您也可以在整个项目的许多地方重复使用此自定义视图
我有一个 UITextView
,我可以在其中添加图像,使用 ImagePickerController。
如果里面只有文字,它是流畅的,但在添加 3 或 4 张图片后,它在内容中滚动时变得迟钝。
我在添加图像时将其压缩到最低质量,但我一定是做错了什么,因为它仍然滞后于第三张图像。
代码如下:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
guard let _image = info[UIImagePickerControllerOriginalImage] as? UIImage else { return }
self.dismiss(animated: true, completion: nil)
// Compress the retrieved image
let compressedImage = UIImage(data: _image.lowestQualityJPEGNSData!)
//create and NSTextAttachment and add your image to it.
let attachment = NSTextAttachment()
let oldWidth = compressedImage?.size.width // scales it within the UITextView
let scaleFactor = oldWidth! / (bodyEditText.frame.size.width - 10); // adjusts the desired padding
attachment.image = UIImage(cgImage: (compressedImage?.cgImage!)!, scale: scaleFactor, orientation: .up)
//put your NSTextAttachment into and attributedString
let attString = NSAttributedString(attachment: attachment)
//add this attributed string to the current position.
bodyEditText.textStorage.insert(attString, at: bodyEditText.selectedRange.location)
}
extension UIImage {
var uncompressedPNGData: Data? { return UIImagePNGRepresentation(self) }
var highestQualityJPEGNSData: Data? { return UIImageJPEGRepresentation(self, 1.0) }
var highQualityJPEGNSData: Data? { return UIImageJPEGRepresentation(self, 0.75) }
var mediumQualityJPEGNSData: Data? { return UIImageJPEGRepresentation(self, 0.5) }
var lowQualityJPEGNSData: Data? { return UIImageJPEGRepresentation(self, 0.25) }
var lowestQualityJPEGNSData:Data? { return UIImageJPEGRepresentation(self, 0.0) }
}
可能是什么原因导致了这个问题以及如何解决这个问题?
感谢您的帮助
编辑
多亏了 Duncan C,我已经设法消除了整个延迟并大大提高了渲染图像的性能。
因此,我已将我的 imagePickerController
替换为以下内容:
let size = __CGSizeApplyAffineTransform(_image.size, CGAffineTransform.init(scaleX: 0.3, y: 0.3))
let hasAlpha = false
let scale: CGFloat = 0.0 // Automatically use scale factor of main screen
UIGraphicsBeginImageContextWithOptions(size, !hasAlpha, scale)
_image.draw(in: CGRect(origin: CGPoint.zero, size: size))
let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
let att = NSTextAttachment()
att.image = scaledImage
//put your NSTextAttachment into and attributedString
let attString = NSAttributedString(attachment: att)
//add this attributed string to the current position.
bodyEditText.textStorage.insert(attString, at: bodyEditText.selectedRange.location)
你误用了比例因子。这是为了处理正常、视网膜和@3x 视网膜图像的 1x、2x 和 3x 缩放。
按照您的操作方式,系统每次要绘制一个图像时都必须将全尺寸图像渲染到您的边界矩形中。如果图像比您显示的尺寸大得多,则会浪费大量内存和处理时间。
首先尝试简单地将图像视图的 contentMode
设置为 .scaleAspectFit
并在图像视图中安装原始图像,而不要乱用比例因子。看看它的表现如何。
如果这不能提供可接受的性能,您应该将起始图像渲染到屏幕外图形上下文中,该上下文是图像的目标大小,并将重新渲染的图像安装到图像视图中。您可以使用 UIGraphicsBeginImageContextWithOptions()
或各种其他技术来调整图像的大小以供显示。
查看此 link 以获取有关图像缩放和调整大小的信息:
这样做不是最佳做法。 UITextViews 适用于文本而非所有视图。
您需要制作一个自定义 UIView,其中包含 1、textview 2、UICollectionView 用于大量图像。
通过这种方式,您也可以在整个项目的许多地方重复使用此自定义视图