iosswiftdidreceivememorywarning

Dissmissed UIViewController didreceivememorywarning - swift


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?


Solution

  • 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 the cameraOverlayView property and use that view to present additional information or manage the interactions between the camera interface and your code.