I have a custom UIImagePickerController
that still, after being dismissed and the variable set to nil is receiving memory warnings, and it is causing my app to crash because of it.
Here is my UIImagePickerController
import UIKit
import MobileCoreServices
class Picker: UIImagePickerController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var myView = PickerView(frame: UIScreen.mainScreen().bounds)
var takenImages = [UIImage]()
var takenImagesThumbs = [UIImage]()
override init() {
super.init()
myView.picker = self
self.delegate = self
self.sourceType = UIImagePickerControllerSourceType.Camera
self.mediaTypes = [kUTTypeImage]
self.showsCameraControls = false
self.cameraOverlayView = myView
self.cameraCaptureMode = UIImagePickerControllerCameraCaptureMode.Photo
self.setFullscreen()
myView.viewing()
}
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
func setFullscreen(){
let screenSize = UIScreen.mainScreen().bounds.size
let scale = screenSize.height / screenSize.width*3/4
let translate = CGAffineTransformMakeTranslation(0,(screenSize.height - screenSize.width*4/3)*0.5);
let fullScreen = CGAffineTransformMakeScale(scale, scale);
self.cameraViewTransform = CGAffineTransformConcat(fullScreen, translate)
}
var endFunc:((images:[UIImage], thumbs:[UIImage]) -> Void)!
var ViewController:UIViewController!
func show(vc:UIViewController, complete: ((images:[UIImage], thumbs:[UIImage]) -> Void)) {
vc.presentViewController(self, animated: true, completion: nil)
endFunc = complete
ViewController = vc
}
var closeQueue = dispatch_queue_create("areyouareyou", nil)
func close() {
let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
dispatch_async(dispatch_get_global_queue(priority, 0)) {
dispatch_async(self.closeQueue) {
self.endFunc(images: self.takenImages, thumbs: self.takenImagesThumbs)
self.takenImagesThumbs = [UIImage]()
self.takenImages = [UIImage]()
self.myView.update(self.takenImages.count)
}
}
self.removeFromParentViewController()
self.dismissViewControllerAnimated(true, completion: nil)
}
var resizequeue = dispatch_queue_create("hangingthree", nil)
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {
myView.takeButton.enabled = true
let nfo = info as NSDictionary
var image:UIImage = nfo.valueForKey(UIImagePickerControllerOriginalImage) as UIImage
takenImages.append(image)
self.myView.update(self.takenImages.count)
let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
dispatch_async(dispatch_get_global_queue(priority, 0)) {
dispatch_async(self.resizequeue) {
var theimg = Common.resizeImage(image, scaledToSize: CGSizeMake(UIScreen.mainScreen().bounds.width / 3, UIScreen.mainScreen().bounds.width / 3))
self.takenImagesThumbs.append(theimg)
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
println(self.takenImages.count)
}
}
and here is my overlayview
import UIKit
class PickerView: UIView {
var picker:Picker!
var takeButton = UIButton()
var takeButtonPath = UIBezierPath()
var takeButtonLayer = CAShapeLayer()
var takeButtonIconLayer = CAShapeLayer()
var closeButton = UIButton()
var closeButtonBgPath = UIBezierPath()
var closeButtonBgLayer = CAShapeLayer()
var bottomBar:UIVisualEffectView!
var imageCount = UILabel()
override init() {
super.init()
}
override init(frame: CGRect) {
super.init(frame: frame)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
func viewing() {
var colors = Colors()
self.backgroundColor = UIColor.clearColor()
imageCount.frame = CGRectMake(62, 0, 30, 31)
imageCount.text = "0"
imageCount.textAlignment = NSTextAlignment.Center
imageCount.font = UIFont(name: "Arial-BoldMT", size: 20)
}
override func drawRect(rect: CGRect) {
let context = UIGraphicsGetCurrentContext()
var colors = Colors()
CGContextSetLineWidth(context, 2)
CGContextSetStrokeColorWithColor(context, colors.pickerStrokeColor.CGColor)
CGContextSetFillColorWithColor(context, colors.pickerFillColor.CGColor)
var point = CGPointMake((self.bounds.width / 2), self.bounds.height - 30)
var start = CGFloat(Common.radians(0))
var end = CGFloat(Common.radians(360))
var moon = UIBezierPath()
moon.addArcWithCenter(point, radius: 45, startAngle: end, endAngle: start, clockwise: true)
moon.stroke()
moon.fill()
var left = UIBezierPath()
left.moveToPoint(CGPointMake(0, point.y))
left.addLineToPoint(CGPointMake(point.x - 45, point.y))
left.stroke()
var right = UIBezierPath()
right.moveToPoint(CGPointMake(self.bounds.width, point.y))
right.addLineToPoint(CGPointMake(point.x + 45, point.y))
right.stroke()
btnCloseing()
btnTakeing()
bottomBaring()
//add
self.addSubview(closeButton)
self.addSubview(takeButton)
}
func bottomBaring() {
var point = CGPointMake((self.bounds.width / 2), self.bounds.height - 30)
var frame = CGRectMake(0, point.y, self.bounds.width, self.bounds.height - point.y)
//blur
var blurEffect = UIBlurEffect(style: UIBlurEffectStyle.Dark)
bottomBar = UIVisualEffectView(effect: blurEffect)
bottomBar.frame = frame
//blur add
self.addSubview(bottomBar)
//vib
var vibEffect = UIVibrancyEffect(forBlurEffect: blurEffect)
var vibView = UIVisualEffectView(effect: vibEffect)
vibView.frame = CGRectMake(0, 0, frame.width, frame.height)
//add
vibView.contentView.addSubview(imageCount)
bottomBar.contentView.addSubview(vibView)
}
func btnCloseing() {
var start = CGFloat(Common.radians(0))
var end = CGFloat(Common.radians(360))
var colors = Colors()
closeButtonBgPath.addArcWithCenter(CGPointMake(0, 0), radius: 20, startAngle: start, endAngle: end, clockwise: true)
closeButtonBgLayer.bounds = CGRectMake(-40, -40, 40, 40)
closeButtonBgLayer.path = closeButtonBgPath.CGPath
closeButtonBgLayer.fillColor = colors.pickerCloseBtnFill.CGColor
closeButtonBgLayer.strokeColor = colors.pickerStrokeColor.CGColor
closeButton.frame = CGRectMake(self.bounds.width - 50, 10, 40, 40)
closeButton.layer.addSublayer(closeButtonBgLayer)
closeButton.setTitle("X", forState: UIControlState.Normal)
closeButton.setTitleColor(colors.pickerStrokeColor, forState: UIControlState.Normal)
closeButton.titleLabel?.font = UIFont(name: "Arial-BoldMT", size: 25)
closeButton.addTarget(self, action: "closePhoto", forControlEvents: UIControlEvents.TouchDown)
}
func btnTakeing() {
var start = CGFloat(Common.radians(0))
var end = CGFloat(Common.radians(360))
var point = CGPointMake((self.bounds.width / 2), self.bounds.height - 30)
takeButtonPath.addArcWithCenter(CGPointMake(0, 0), radius: 40, startAngle: start, endAngle: end, clockwise: true)
takeButtonLayer.bounds = CGRectMake(-80, -90, 80, 80)
takeButtonLayer.path = takeButtonPath.CGPath
takeButtonLayer.fillColor = Colors().pickerTakeBtnFill.CGColor
takeButtonLayer.strokeColor = UIColor.clearColor().CGColor
takeButtonIconLayer.contents = UIImage(named: "CameraIcon")?.CGImage
takeButtonIconLayer.frame = CGRectMake(26, 30, 30, 30)
takeButton.frame = CGRectMake(point.x - 40, point.y - 50, 80, 100)
takeButton.layer.addSublayer(takeButtonLayer)
takeButton.layer.addSublayer(takeButtonIconLayer)
takeButton.addTarget(self, action: "takePhoto", forControlEvents: UIControlEvents.TouchDown)
takeButton.addTarget(self, action: "takePhotoEnd", forControlEvents: UIControlEvents.TouchUpInside)
takeButton.addTarget(self, action: "takePhotoEnd", forControlEvents: UIControlEvents.TouchUpOutside)
}
func takePhoto() {
self.takeButton.enabled = false
takeButtonLayer.fillColor = Colors().pickerTakeBtnFillClick.CGColor
picker.takePicture()
}
func takePhotoEnd() {
takeButtonLayer.fillColor = Colors().pickerTakeBtnFill.CGColor
}
func closePhoto() {
picker.close()
}
func update(count: Int) {
imageCount.text = String(count)
}
}
Anyone knows the problem or how to fix it?
Your problem is that you are subclassing UIImagePickerController
which is prohibited. Read the Apple documentation:
IMPORTANT
The
UIImagePickerController
class supports portrait mode only. This class is intended to be used as-is and does not support subclassing. The view hierarchy for this class is private and must not be modified, with one exception. You can assign a custom view to thecameraOverlayView
property and use that view to present additional information or manage the interactions between the camera interface and your code.