parse-platformoptional-variables

Why is my Swift string variable returning nil?


I am trying to use Parse to create a simple tableview that triggers the URLs of PDF documents that I have uploaded to the Parse Cloud.

In the code below, my variable thePDFFile does output a URL correctly to the console. But when I try to return that variable, it comes up nil and the app crashes.

I am pretty sure that I am not unwrapping an optional correctly, but I can't see where.

The function with the error is named GrabPDF()->String.

import UIKit
import Parse
import Bolts
import AVFoundation
import AVKit

public var AudioPlayer = AVPlayer()
public var SelectedSong = Int()

var theFile:String!
var thePDFFile:String!




class TableViewController: UITableViewController, AVAudioPlayerDelegate {

var iDArray = [String]()
var NameArray = [String]()
var PDFArray = [String]()
var PDFFileArray = [PFObject]()


override func viewDidLoad() {
    super.viewDidLoad()

    var ObjectIDQuery = PFQuery(className:"Recordings")
    ObjectIDQuery.findObjectsInBackgroundWithBlock({
        (objectsArray : [AnyObject]?, error: NSError?) -> Void in

        var objectIDs = objectsArray as! [PFObject]
        for i in 0...objectIDs.count-1{

            self.iDArray.append(objectIDs[i].valueForKey("objectId") as! String)
            self.NameArray.append(objectIDs[i].valueForKey("RecordingName") as! String)
            self.PDFArray.append(objectIDs[i].valueForKey("PDFFileName") as! String)


            self.tableView.reloadData()

                }



            })

        }



func grabSong() {

    var SongQuery = PFQuery(className:"Recordings")
    SongQuery.getObjectInBackgroundWithId(iDArray[SelectedSong], block: {
        (object : PFObject?, error : NSError?) -> Void in

        if let AudioFileURLTemp = object?.objectForKey("RecordingFile")?.url {
            AudioPlayer = AVPlayer(URL: NSURL(string: AudioFileURLTemp!))
            AudioPlayer.play()
            theFile = AudioFileURLTemp



            }



        })


    }

func grabPDF() -> String {

    var PDFQuery = PFQuery(className:"Recordings")

    PDFQuery.getObjectInBackgroundWithId(iDArray[SelectedSong], block: {
        (object: PFObject?, error : NSError?) -> Void in

        if let PDFFileURLTemp = object?.objectForKey("PDFFile")?.url {

            println(PDFFileURLTemp)


            let thePDFFile = PDFFileURLTemp! as String


            println("The value of thePDFFile is \(thePDFFile)")



        }

                })

    return thePDFFile

}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return iDArray.count
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    var cell = tableView.dequeueReusableCellWithIdentifier("Cell") as! UITableViewCell
    cell.textLabel?.text = NameArray[indexPath.row]

    return cell

}

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

    SelectedSong = indexPath.row
    grabSong()
    grabPDF()
}



override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

    if segue.identifier == "WebView" {
        if let VC2 = segue.destinationViewController as? WebViewController {
            if let indexPath = tableView.indexPathForSelectedRow()?.row {


                VC2.sentData = theFile

            }
        }
    }

}




override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

}


Solution

  • You're shadowing thePDFFile with that let. The shadow is popped off the stack when you pass the closing brace and you're returning the instance variable which was not set