Does Cassini CS193P code work on a simulator but crashes to a device? "Message from the debugger: completed due to a memory error"

I am looking at the Stanford CS193P online course doing ios dev. Lecture 9 is devoted to UIScrollView/ delegation with a simple url UIImagefetch app. The mentioned application works fine in the simulator, but it starts, then it crashes on a real device (iPhone5) after trying to get img with the following:

Message from the debugger: completed due to a memory error

I went back to my code, re-read about delegation, searched the SO (I found a similar thread, I made sure that my design scheme was not activated by zombies). I updated my device, my compiler / os, and I'm a little worried that it might prevent this from working on the device ... An example class can be downloaded from Stanford at https://web.stanford.edu/class/cs193p/cgi-bin /drupal/system/files/sample_code/Cassini.zip , but this code behaves the same! It was originally written for ios 8.1 and we are on 8.4, are there any known issues?

for image controller:

import UIKit

class ImageViewController: UIViewController, UIScrollViewDelegate
{
    // our Model
    // publicly settable
    // when it changes (but only if we are on screen)
    //   we'll fetch the image from the imageURL
    // if we're off screen when this happens (view.window == nil)
    //   viewWillAppear will get it for us later
    var imageURL: NSURL? {
        didSet {
            image = nil
            if view.window != nil {
                fetchImage()
            }
        }
    }

    // fetches the image at imageURL
    // does so off the main thread
    // then puts a closure back on the main queue
    //   to handle putting the image in the UI
    //   (since we aren't allowed to do UI anywhere but main queue)
    private func fetchImage()
    {
        if let url = imageURL {
            spinner?.startAnimating()
            let qos = Int(QOS_CLASS_USER_INITIATED.value)
            dispatch_async(dispatch_get_global_queue(qos, 0)) { () -> Void in
                let imageData = NSData(contentsOfURL: url) // this blocks the thread it is on
                dispatch_async(dispatch_get_main_queue()) {
                    // only do something with this image
                    // if the url we fetched is the current imageURL we want
                    // (that might have changed while we were off fetching this one)
                    if url == self.imageURL { // the variable "url" is capture from above
                        if imageData != nil {
                            // this might be a waste of time if our MVC is out of action now
                            // which it might be if someone hit the Back button
                            // or otherwise removed us from split view or navigation controller
                            // while we were off fetching the image
                            self.image = UIImage(data: imageData!)
                        } else {
                            self.image = nil
                        }
                    }
                }
            }
        }
    }

    @IBOutlet private weak var spinner: UIActivityIndicatorView!

    @IBOutlet private weak var scrollView: UIScrollView! {
        didSet {
            scrollView.contentSize = imageView.frame.size // critical to set this!
            scrollView.delegate = self                    // required for zooming
            scrollView.minimumZoomScale = 0.03            // required for zooming
            scrollView.maximumZoomScale = 1.0             // required for zooming
        }
    }

    // UIScrollViewDelegate method
    // required for zooming
    func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
        return imageView
    }

    private var imageView = UIImageView()

    // convenience computed property
    // lets us get involved every time we set an image in imageView
    // we can do things like resize the imageView,
    //   set the scroll view contentSize,
    //   and stop the spinner
    private var image: UIImage? {
        get { return imageView.image }
        set {
            imageView.image = newValue
            imageView.sizeToFit()
            scrollView?.contentSize = imageView.frame.size
            spinner?.stopAnimating()
        }
    }

    // put our imageView into the view hierarchy
    // as a subview of the scrollView
    // (will install it into the content area of the scroll view)
    override func viewDidLoad() {
        super.viewDidLoad()
        scrollView.addSubview(imageView)
    }

    // for efficiency, we will only actually fetch the image
    // when we know we are going to be on screen
    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        if image == nil {
            fetchImage()
        }
    }
}
+4
source share
1 answer

, ( , ) , "" . iOS →

Cassini (wave_earth_mosaic_3.jpg(9999 × 9999), pia03883-full.jpg(14400 × 9600)) "" . .

Cassini, 2.

(, Swift 2.0):

     ...
       if imageData != nil {
                        // this might be a waste of time if our MVC is out of action now
                        // which it might be if someone hit the Back button
                        // or otherwise removed us from split view or navigation controller
                        // while we were off fetching the image
                        if let imageSource = UIImage(data: imageData!) {
                            self.image = self.imageResize(imageSource)
                        }
                    } else {
                        self.image = nil
                    }
   ...

   func imageResize (imageOriginal:UIImage) -> UIImage {
    let image = imageOriginal.CGImage

    let width = CGImageGetWidth(image) / 2
    let height = CGImageGetHeight(image) / 2
    let bitsPerComponent = CGImageGetBitsPerComponent(image)
    let bytesPerRow = CGImageGetBytesPerRow(image)
    let colorSpace = CGImageGetColorSpace(image)
    let bitmapInfo = CGImageGetBitmapInfo(image)

    let context = CGBitmapContextCreate(nil, width, height, bitsPerComponent, bytesPerRow, colorSpace, bitmapInfo.rawValue)

    CGContextSetInterpolationQuality(context, CGInterpolationQuality.High)

    CGContextDrawImage(context, CGRect(origin: CGPointZero, size: CGSize(width: CGFloat(width), height: CGFloat(height))), image)

    let scaledImage = UIImage(CGImage: CGBitmapContextCreateImage(context)!)

    return scaledImage
}

, .

SWIFT 2.0:

Info.plist, HTTP

<key>NSAppTransportSecurity</key>
<dict>
  <!--Include to allow all connections (DANGER)-->
  <key>NSAllowsArbitraryLoads</key>
      <true/>
</dict>
+2

Source: https://habr.com/ru/post/1606007/


All Articles