Я создаю приложение, которое позволяет пользователям добавлять временную метку к фотографии. Когда выбрано фото из ролика камеры, мое приложение иногда сбой, и Xcode отображает ошибку: «Сообщение от отладчика: завершено из-за проблемы с памятью». Я обнаружил, что он сработает, если я попытаюсь добавить временную метку к очень большому изображению или если я неоднократно на отметке времени на одно и то же изображение.Завершена из-за проблемы с памятью при сохранении измененного изображения в камере.
Ниже приведен код, который, по моему мнению, имеет отношение к проблеме. Кроме того, here - это ссылка на весь проект.
Вот как к метке добавляется метка времени. Я помещаю комментарии, где он падает. Он не всегда сбой в одной строке кода. Я не могу понять, почему мой код приводит к сбою в ошибке памяти.
func textToImage(drawText text: NSString, inImage image: UIImage, atPoint point: CGPoint) -> UIImage {
let color = UserDefaults.standard.colorForKey(key: "color")!
let font = UserDefaults.standard.value(forKey: "font") as! String
let size = UserDefaults.standard.value(forKey: "size") as! Int
let fontAndSize = UIFont(name: font, size: CGFloat(size))!
let location = Locations(rawValue: UserDefaults.standard.value(forKey: "location") as! String)!
let scale = UIScreen.main.scale
UIGraphicsBeginImageContextWithOptions(image.size, false, scale)
// sometimes terminates here
let textFontAttributes = [
NSFontAttributeName: fontAndSize,
NSForegroundColorAttributeName: color
] as [String : Any]
image.draw(in: CGRect(origin: CGPoint.zero, size: image.size))
let rectSize = text.boundingRect(with: CGSize(width:CGFloat(MAXFLOAT), height: CGFloat(MAXFLOAT)), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: textFontAttributes, context: nil).size
// sometimes terminates here
if location == .topRight || location == .bottomRight || location == .center || location == .topCenter || location == .bottomCenter {
// Calculate the text size
if location == .center || location == .topCenter || location == .bottomCenter {
// Subtract half the text width from the x origin
let rect = CGRect(x:point.x-(rectSize.width/2), y:point.y-(rectSize.height/2), width:rectSize.width, height: rectSize.height)
text.draw(in: rect, withAttributes: textFontAttributes)
} else {
// Subtract the text width from the x origin
let rect = CGRect(x:point.x-rectSize.width, y:point.y-(rectSize.height/2), width:rectSize.width, height: rectSize.height)
text.draw(in: rect, withAttributes: textFontAttributes)
}
} else {
let rect = CGRect(x:point.x, y:point.y-(rectSize.height/2), width:rectSize.width, height: rectSize.height)
text.draw(in: rect, withAttributes: textFontAttributes)
}
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}
func selectPhotoFromCameraRoll(mediaType: String) {
imagePicker.sourceType = .photoLibrary
if mediaType == "Video" {
imagePicker.mediaTypes = [kUTTypeMovie as String]
}
newMedia = false
present(imagePicker, animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let mediaType = info[UIImagePickerControllerMediaType] as? String {
if mediaType.isEqual((kUTTypeImage as String)) {
if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
let width = pickedImage.size.width
let height = pickedImage.size.height
let location = Locations(rawValue: UserDefaults.standard.value(forKey: "location") as! String)!
var point = CGPoint(x: 0, y: 0)
switch location {
case .topLeft:
point = CGPoint(x: 30, y: 50)
case .topRight:
point = CGPoint(x: width - 30, y: 50)
case .bottomLeft:
point = CGPoint(x: 30, y: height - 50)
case .bottomRight:
point = CGPoint(x: width - 30, y: height - 50)
case .center:
point = CGPoint(x: width/2, y: height/2)
case .topCenter:
point = CGPoint(x: width/2, y: 50)
case .bottomCenter:
point = CGPoint(x: width/2, y: height - 50)
}
let savedFormat = UserDefaults.standard.value(forKey: "format") as! String
var date = Date()
if !currentDateBool {
date = UserDefaults.standard.value(forKey: "selectedDate") as! Date
}
let timestampText = getFormattedDateFromFormatType(formatType: savedFormat, date: date) as NSString
let timestampImage = textToImage(drawText: timestampText, inImage: pickedImage, atPoint: point)
if newMedia {
UIImageWriteToSavedPhotosAlbum(timestampImage, self, #selector(image(_:didFinishSavingWithError:contextInfo:)), nil)
} else {
UIImageWriteToSavedPhotosAlbum(timestampImage, self, #selector(image(_:didFinishSavingWithError:contextInfo:)), nil)
}
}
} else if mediaType.isEqual((kUTTypeMovie as String)) {
if let videoUrl = info[UIImagePickerControllerMediaURL] as? NSURL {
if let videoPath = videoUrl.relativePath {
if newMedia {
UISaveVideoAtPathToSavedPhotosAlbum(videoPath, nil, nil, nil)
}
}
}
}
}
dismiss(animated: true, completion: nil)
}
func image(_ image: UIImage, didFinishSavingWithError error: NSError?, contextInfo: UnsafeRawPointer) {
if let error = error {
// we got back an error!
let ac = UIAlertController(title: "Save error", message: error.localizedDescription, preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .default))
present(ac, animated: true)
} else {
let ac = UIAlertController(title: "Saved!", message: "Your altered image has been saved to your photos.", preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .default))
present(ac, animated: true)
}
}
Благодарим за ответ! У вас есть рекомендация относительно того, как я должен лечить изображение. – chickenparm
Спасибо. Я буду смотреть в рамки фотографий, поскольку у меня нет большого опыта в этом. Можете ли вы указать мне в правильном направлении и сказать мне, если я вообще не буду использовать UIGraphicsBeginImageContextWithOptions? – chickenparm
Извините, если я не согласен с моим вопросом. Пользователь имеет существующую фотографию в своем ролике. Пользователь хотел бы добавить текст даты/времени на фотографию. Единственное, что я хочу изменить, это добавить текст к фотографии. Мой код выше открывает рулон камеры, позволяя пользователю выбрать фотографию, добавить текст к фотографии и сохранить новую версию этой фотографии в рулоне камеры, которая включает в себя текст даты/времени на фотографии. – chickenparm