ButtonMasterBot
ButtonMasterBot

Reputation: 317

Definition of Global Variable Resetting

I have a class designed to take the temperature data from an API for a specific date and add it to a dictionary. The URL for the API is stored in a global variable called baseURL. It is defined at the beginning as an empty string, but is later changed. My class is below:

import UIKit
import Foundation
typealias ServiceResponse = (JSON, NSError?) -> Void

class WeatherManager: NSObject {

var baseURL: String = ""
var data: String = ""
static let sharedInstance = WeatherManager()


func getRandomUser(onCompletion: (JSON) -> Void) {
    println("Starting getRandomUser")
    let route = self.baseURL
    println(self.baseURL)
    makeHTTPGetRequest(route, onCompletion: { json, err in
        onCompletion(json as JSON)
    })
}

func makeHTTPGetRequest(path: String, onCompletion: ServiceResponse) {
    let request = NSMutableURLRequest(URL: NSURL(string: path)!)

    let session = NSURLSession.sharedSession()

    let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
        let json:JSON = JSON(data: data)
        onCompletion(json, error)
        if error != nil {
            println("No Error")
        } else {
            println("Error")
        }
    })
    task.resume()
}

func addData() {
    WeatherManager.sharedInstance.getRandomUser { json in
        var jsonData = json["response"]["version"]
        self.data = "\(jsonData)"
        dispatch_async(dispatch_get_main_queue(),{
            let alert = UIAlertView()
            alert.title = "Weather Data Update"
            if self.data != "null" {
                println("Value:\(self.data)")
                alert.message = "The weather data was updated successfully."
                alert.addButtonWithTitle("OK")
                alert.show()
            } else {
                println("Error Reading Data")
                println(self.data)
                alert.message = "HealthTrendFinder encountered an error while updating data."
                alert.addButtonWithTitle("OK")
                alert.show()
            }
        })
    }
}

func updateWeatherHistory() {
    println(self.baseURL)
    let calendar: NSCalendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
    println("Weather Updating...")
    // This sets the start date to midnight of the current date if no start date has been set.
    if StorageManager.getValue(StorageManager.StorageKeys.WeatherStartDate) == nil {
        let startDate: NSDate = calendar.startOfDayForDate(NSDate())
        StorageManager.setValue(startDate, forKey: StorageManager.StorageKeys.WeatherStartDate)

    }

    // This adds a data array if it hasn't been created yet.
    if StorageManager.getValue(StorageManager.StorageKeys.WeatherData) == nil {
        StorageManager.setValue([:], forKey: StorageManager.StorageKeys.WeatherData)

    }

    var weatherData: [NSDate: NSObject] = StorageManager.getValue(StorageManager.StorageKeys.WeatherData)! as! [NSDate : NSObject]
    let startMidnight: NSDate = StorageManager.getValue(StorageManager.StorageKeys.WeatherStartDate) as! NSDate
    let currentMidnight: NSDate = calendar.startOfDayForDate(NSDate())
    let daysFromStartDate: Int = calendar.components(NSCalendarUnit.CalendarUnitDay, fromDate: startMidnight, toDate: currentMidnight, options: nil).day
    println("Starting Loop")
    for i: Int in 0..<daysFromStartDate {

        let dateToBeExamined: NSDate = calendar.dateByAddingUnit(NSCalendarUnit.CalendarUnitDay, value: i, toDate: startMidnight, options: nil)!
        if weatherData[dateToBeExamined] == nil {
            let calendarUnits: NSCalendarUnit = .CalendarUnitDay | .CalendarUnitMonth | .CalendarUnitYear
            let components = NSCalendar.currentCalendar().components(calendarUnits, fromDate: dateToBeExamined)
            var month: String
            var day: String
            if components.month < 10 {
                month = "0\(components.month)"
            } else {
                month = "\(components.month)"
            }
            if components.day < 10 {
                day = "0\(components.day)"
            } else {
                day = "\(components.day)"
            }
            var dateString = "\(components.year)\(month)\(day)"
            self.baseURL = "http://api.wunderground.com/api/91e65f0fbb35f122/history_\(dateString)/q/OR/Portland.json"
            println(self.baseURL)
            var get: () = WeatherManager.sharedInstance.addData()
            println(get)
            weatherData[dateToBeExamined] = self.data




            // There is no data for the NSDate dateForInspection. You need to pull data and add it to the dictionary.
        } else {
            // Data exists for the specified date, so you don't need to do anything.
        }
    }
    println("Loop has finished or been skipped")

}

}

The problem is, baseURL reverts to an empty string when getRandomUser is executed, after baseURL is set to the URL. Why is this happening, and how do I fix it?

Upvotes: 0

Views: 90

Answers (1)

Aaron Rasmussen
Aaron Rasmussen

Reputation: 13316

Your code is unnecessarily complex, making it hard to diagnose the problem without more information. But here is a suggestion:

Try making it impossible to instantiate more than one instance of your WeatherManager singleton:

class WeatherManager {

    private static let _sharedInstance = WeatherManager()

    private init() { super.init() }

    static func sharedInstance() -> WeatherManager {
        return _sharedInstance
    }
}

When you are working from outside WeatherManager, you access it by calling:

let wm = WeatherManager.sharedInstane()

Then, when you are working inside WeatherManager, make sure that all your references are to self - i.e., self.baseURL = ... or self.updateWeatherHistory(), instead of WeatherManager.sharedInstance.baseURL = ..., etc.

Though your code is complicated, I think what is going on is you actually have two instances of WeatherManager in play. You are setting the value of baseURL on one, but not the other. If you want it to be a singleton, you need to make it impossible to create more than one.

Upvotes: 1

Related Questions