Memory leak createCGImage in iOS9.2 - uiimageview

I am using the following which works properly earlier. But I am getting the memory leak in iOS 9.2 and Xcode 7.
var context: CIContext!
var currentFilter: CIFilter!
context = CIContext(options: nil)
currentFilter = CIFilter(name: "CIGaussianBlur")
let beginImage = CIImage(image: back)
currentFilter.setValue(beginImage, forKey: kCIInputImageKey)
let cgimg = context.createCGImage(currentFilter.outputImage!, fromRect: rec)
let processedImage = UIImage(CGImage: cgimg)
back = processedImage
Screenshot of memory leak as follows
Please let me know how can I remove this memory leak.

Related

Converting from UIImage to a SwiftUI Image results in a blank image of the same size

I am trying to convert a UIImage to a SwiftUI Image using the init(uiImage:) initializer. My UIImage itself is created from a CIImage generated by a CIQRCodeGenerator CIFilter. I am running my code on a Playground in Xcode 11.1 GM seed 1. Here is the entirety of my code:
import SwiftUI
import UIKit
func qrCodeImage(for string: String) -> Image? {
let data = string.data(using: String.Encoding.utf8)
guard let qrFilter = CIFilter(name: "CIQRCodeGenerator") else { return nil }
qrFilter.setValue(data, forKey: "inputMessage")
guard let ciImage = qrFilter.outputImage else { return nil }
let uiImage = UIImage(ciImage: ciImage)
let image = Image(uiImage: uiImage)
return image
}
let image = qrCodeImage(for: "fdsa")
And here is the result:
Even when I transform the image with CGAffineTransform(scaleX: 10, y: 10), the resulting SwiftUI Image at the end is still the same size, but blank.
Following solution provided in: Generating QR Code with SwiftUI shows empty picture
Here is the code:
var ciContext = CIContext()
func qrCodeImage(for string: String) -> Image? {
let data = string.data(using: String.Encoding.utf8)
guard let qrFilter = CIFilter(name: "CIQRCodeGenerator") else { return nil }
qrFilter.setValue(data, forKey: "inputMessage")
guard let ciImage = qrFilter.outputImage else { return nil }
let cgImage = ciContext.createCGImage(ciImage, from: ciImage.extent)
let uiImage = UIImage(cgImage: cgImage!)
let image = Image(uiImage: uiImage)
return image
}
let image = qrCodeImage(for: "fdsa")
Result:
screenshot in swift playground
Can confirm I encounter the same issue with a SwiftUI Image using a UIImage initialized from data. Can verify that the image is loaded when paused in debugging, but it does not display in the SwiftUI Image.
This solution worked for me: explicitly specify the image rendering mode. In my case I added the following: .renderingMode(.original)
#Eugene remark worked for me:
let image = Image(uiImage: uiImage).renderingMode(.original)

LTR to RTL in iOS Application [without closing Application]

When changing language within the application I need to change the application layout as per selected language.
For example, the base language is English; when the user changes it to Arabic I need to change UI as per RTL.
Is there any specific setting in storyboard or in ViewController for achieving LTR and RTL?
To Manage RTL and LTR without closing application Swift 3.0.
//RTL
UIView.appearance().semanticContentAttribute = .forceRightToLeft
UINavigationBar.appearance().semanticContentAttribute = .forceRightToLeft
//applicationNavigationController is Application Default Navigation Controller
if let applicationNavigationController = storyboard?.instantiateViewController(withIdentifier: "root") {
UIApplication.shared.keyWindow?.rootViewController = applicationNavigationController
LTR//
UIView.appearance().semanticContentAttribute = .forceLeftToRight
UINavigationBar.appearance().semanticContentAttribute = .forceLeftToRight
if let applicationNavigationController = storyboard?.instantiateViewController(withIdentifier: "root") {
UIApplication.shared.keyWindow?.rootViewController = applicationNavigationController
// Additional Tips while a deal with MMDrawer.
AppDelegate
var centerContainer:MMDrawerController?
Implement MMDrawer Code inside one ViewController.
let appdelegate=UIApplication.shared.delegate as! AppDelegate
let mainStoryboard:UIStoryboard=UIStoryboard(name: "Main", bundle: nil)
let centerViewController = mainStoryboard.instantiateViewController(withIdentifier: "HomeViewController") as! HomeViewController
let leftViewController = mainStoryboard.instantiateViewController(withIdentifier: "LeftSideMenuViewController") as! LeftSideMenuViewController
let leftSideNav = UINavigationController(rootViewController: leftViewController)
let centerNav = UINavigationController(rootViewController: centerViewController)
appdelegate.centerContainer = MMDrawerController(center: centerNav, leftDrawerViewController: leftSideNav)
appdelegate.centerContainer?.maximumLeftDrawerWidth = 250.0
appdelegate.centerContainer!.openDrawerGestureModeMask = MMOpenDrawerGestureMode.panningCenterView
appdelegate.centerContainer!.closeDrawerGestureModeMask = MMCloseDrawerGestureMode.all
//////////
self.navigationController?.pushViewController(appdelegate.centerContainer!, animated: false)

Swift Image Filter

The filtering on the photo works but I'm stuck with this problem.
When I run this code:
let originalImage = CIImage(image: imageView.image)
var filter = CIFilter(name: "CIPhotoEffectMono")
filter.setDefaults()
filter.setValue(originalImage, forKey: kCIInputImageKey)
var newImage = UIImage(CIImage: filter.outputImage)
imageView.image = newImage
The first error is:
BSXPCMessage received error for message: Connection interrupted
The second error is:
fatal error: unexpectedly found nil while unwrapping an Optional value
Then the app crashes.
How would I fix it and the errors?
Try this:
let originalImage = CIImage(image: imageView.image)
var filter = CIFilter(name: "CIPhotoEffectMono")
filter.setValue(originalImage, forKey: kCIInputImageKey)
let context = CIContext(options:nil)
let ouputImage = context.createdCGImage(filter,fromRect:filter.extend())
var newImage = UIImage(CGImage: ouputImage)
imageView.image = newImage
Your code runs fine. Your image source imageView.image is probably nil when you call it. You can try this at playground:
let myPicture = UIImage(data: NSData(contentsOfURL: NSURL(string:"http://i.stack.imgur.com/Xs4RX.jpg")!)!)!
let filter = CIFilter(name: "CIPhotoEffectMono")
filter.setValue(CIImage(image: myPicture), forKey: kCIInputImageKey)
let newImage = UIImage(CIImage: filter.outputImage)
I Found A Solution:
Updated
let originalImage = CIImage(image: imageView.image)
var filter = CIFilter(name: "CIPhotoEffectMono")
filter.setValue(originalImage, forKey: kCIInputImageKey)
let context = CIContext(options: [kCIContextUseSoftwareRenderer: true])
let outputImage = context.createCGImage(filter.outputImage, fromRect: filter.outputImage.extent())
var newImage = UIImage(CGImage: outputImage)
imageView.image = newImage
*Based on Lamar's code.
CIContext(options: nil) was causing BSXPCMessage received error for message: Connection interrupted error.
SO replace:
CIContext(options: nil) with CIContext(options: [kCIContextUseSoftwareRenderer: true])
Thanks For The Help:
Lamar
The app doesn't crash anymore.
**I have added Black n White Effect To an Image**
UIGraphicsBeginImageContext(clickedImage.bounds.size)
clickedImage.layer.renderInContext(UIGraphicsGetCurrentContext())
var image2: UIImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
origionalimage=image2;
var CIfilterName = "CIPhotoEffectTonal"
let ciContext = CIContext(options: nil)
let startImage = CIImage(image: image2)
let filter = CIFilter(name: CIfilterName)
filter.setDefaults()
filter.setValue(startImage, forKey: kCIInputImageKey)
let filteredImageData = filter.valueForKey(kCIOutputImageKey) as! CIImage
let filteredImageRef = ciContext.createCGImage(filteredImageData, fromRect: filteredImageData.extent())
var newImage = UIImage(CGImage: filteredImageRef)!
self.mediaData = UIImagePNGRepresentation(newImage )
self.videoThumbData = UIImageJPEGRepresentation(image2, 0.1)
self.clickedImage.image = newImage;

Swift - saving and retrieving images from userDefaults

I'm trying to save images retrieved from Parse.com like this:
let userImageFile = object["Image"] as PFFile
userImageFile.getDataInBackgroundWithBlock {
(imageData: NSData!, error: NSError!) -> Void in
if error == nil {
image = UIImage(data:imageData)
let imageToSave:NSData = UIImagePNGRepresentation(image)
self.saveImage(intRandomNumb, retImage: imageToSave)
}
}
where the saveImage-function looks like this:
func saveImage(imagepath:Int, retImage:NSData){
println("image is being saved")
let defaults = NSUserDefaults.standardUserDefaults()
let imagePathName = "\(imagepath)"
defaults.setObject(retImage, forKey: imagePathName)
}
and later, I'm trying to display this image like this:
var point = gestureRecognizer.locationInView(self.tv)
if let indexPath = self.tv.indexPathForRowAtPoint(point)
{
let data = mainList[indexPath.row] as SecondModel
let fileRef = data.fileReference
let intFileRef = Int(fileRef)
println(intFileRef)
let defaults = NSUserDefaults.standardUserDefaults()
let usedKeyName = "\(intFileRef)"
if let photo = defaults.objectForKey(usedKeyName) as? UIImage {
println("Image created")
let photo = defaults.objectForKey(usedKeyName) as UIImage
var imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height))
imageView.image = photo
self.view.addSubview(imageView)
}
and the "Image created" never gets printed which means the retrieving somehow doesn't work.
I'm not quite sure if you're able to save images to the userdefaults like I've done here, but that was the best I could come up with, and I couldn't find any previous questions like this for Swift.
Any suggestions on how to proceed would be appreciated.
SOLUTION: The problem was that I tried to load the image directly as a UIImage. I also had to convert the NSData to a UIImage, this all happens in the last section of the code displayed above. Finally my code looks like this:
if let photo = defaults.objectForKey("\(intFileRef)") as? NSData {
println("Image created")
let photo = defaults.objectForKey("\(intFileRef)") as NSData
let imageToView:UIImage = UIImage(data: photo)
var imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height))
imageView.image = imageToView
self.view.addSubview(imageView)
}
I hope this can help others struggling with something similar to this.
Swift 3
Hey, try this beautiful code here:
Convert your UIImage to Data.
PNG:
yourDataImagePNG = UIImagePNGRepresentation(yourUIImageHere)
JPEG :
yourDataImageJPG = UIImage(data: yourUIImageHere,scale:1.0)
Save in UserDefaults.
UserDefaults().set(yourDataImagePNG, forKey: "image")
Recover from:
UserDefaults.standard.object(forKey: "image") as! Data
I hope to help!
It seems like you do not call defaults.synchronize() so it's not written to the defaults file.

How can you load a font (TTF) from a file using Core Text?

Prior to OSX 10.6, ATSFontActivateFromFileSpecification/ATSFontActivateFromFileReference were available and could be used to load a font from a file. I can't find anything similar in Core Text.
You can get a CTFontRef from a font file by going via a CGFontRef:
CFURLRef url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR("/path/to/font"), kCFURLPOSIXPathStyle, false);
CGDataProviderRef dataProvider = CGDataProviderCreateWithURL(url);
CGFontRef theCGFont = CGFontCreateWithDataProvider(dataProvider);
CTFontRef theCTFont = CTFontCreateWithGraphicsFont(theCGFont);
CFRelease(theCGFont);
CFRelease(dataProvider);
CFRelease(url);
// do something with the CTFontRef here
CFRelease(theCTFont);
It looks like CTFontManagerCreateFontDescriptorsFromURL is the Core Text replacement.
Here's an updated version of how to do this in 2020. Much simpler now. Used 12 as arbitrary type size.
let fontURL = URL(fileURLWithPath: "path/to/font.otf")
let fd = CTFontManagerCreateFontDescriptorsFromURL(fontURL as CFURL) as! [CTFontDescriptor]
let theCTFont = CTFontCreateWithFontDescriptor(fd[0], 12.0, nil)
NSURL *fontURL = [[NSBundle mainBundle] URLForResource:#"Crystal" withExtension:#"ttf"];
assert(fontURL);
CFErrorRef error = NULL;
if (!CTFontManagerRegisterFontsForURL((__bridge CFURLRef)fontURL, kCTFontManagerScopeProcess, &error))
{
CFShow(error);
abort();
}

Resources