Why is my Swift string variable returning nil?

192 Views Asked by At

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.
}

}

1

There are 1 best solutions below

3
On BEST ANSWER

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