I am trying to make a calendar in swift starting from this great example. So far I managed to show the grid and all the supplementary views customizing UICollectionViewLayout. The problem is when I am trying to add the events in the calendar. Both the day row and the calendar are in the same NSMutableDictionary which has a key that represent the date (String) using this format 2016-10-12. The objective c code is
-(void)groupEventsBySection{
//toDeviceTimezoneDateString simply take a Date and make a string
_eventsBySection = [mEvents groupBy:#"StartDate.toDeviceTimezoneDateString"].mutableCopy;
// after groupBy is performed _eventsBySection contains only those keys found in mEvents with inside an array of objects {
// "2016-10-12" = (
// "<MSEvent: 0x60000004a680>",
// "<MSEvent: 0x60000004a380>");
// "2016-10-13" = (
// "<MSEvent: 0x600000049b10>");
// "2016-10-17" = (
// "<MSEvent: 0x600000049fc0>");
// }
NSDate* date = [NSDate today:#"device"]; // today's date
if(self.daysToShow == 1 && _eventsBySection.count == 1){
date = [NSDate parse:_eventsBySection.allKeys.firstObject];
}
//here it adds the remaining "daysToShow" if the key doesn't already exist in the MutableDictionary.
for(int i = 0; i< self.daysToShow; i++){
if(![_eventsBySection.allKeys containsObject:date.toDeviceTimezoneDateString]){
[_eventsBySection setObject:#[] forKey:date.toDeviceTimezoneDateString];
}
date = [date addDay]; // this just add one day to date
}
}
it's quite clear so far. The problem is when I try to change the groupBy function which in objective c is:
- (NSDictionary*)groupBy:(NSString*)keypath{
return [self groupBy:keypath block:^NSString *(id object, NSString *key) {
return key;
}];
}
- (NSDictionary*)groupBy:(NSString*)keypath block:(NSString*(^)(id object, NSString* key))block{
NSMutableDictionary *result = [NSMutableDictionary new];
NSString* finalKeypath = [NSString stringWithFormat:#"%#.#distinctUnionOfObjects.self",keypath];
NSArray *distinct = [self valueForKeyPath:finalKeypath];
[distinct each:^(NSString* value) {
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"%K = %#", keypath,value];
NSArray *objects = [self filteredArrayUsingPredicate:predicate];
[result setObject:objects forKey:block(objects[0],value)];
}];
return result;
}
- (NSDictionary*)expand:(NSString*)keypath{
return [self expand:keypath unique:NO];
}
So far this is what I have done in swift:
I have this class which in the original code is MSEvent
class Event : NSObject {
var title:String?
var location:String?
var startTime:Date?
var endTime:Date?
var duration:Int?
var subtitle:String?
init(startTime: Date, duration: Int, title: String, subtitle: String) {
super.init()
self.startTime = startTime
self.duration = duration
self.title = title
self.subtitle = subtitle
}
I create some fake events:
override func viewDidLoad() {
let today = Date()
let event1 = Event(startTime: today, duration: 60, title: "prova", subtitle: "HEllo")
let event2 = Event(startTime: today, duration: 60, title: "prova", subtitle: "HEllo")
let event3 = Event(startTime: today.dateByAddingDays(days: 1), duration: 60, title: "prova", subtitle: "HEllo")
var array:[Event] = []
array.append(event1)
array.append(event2)
array.append(event3)
calendarView.setEvents(events: array)
}
func setEvents(events:[Event]){
mEvents = events as NSArray
print(mEvents)
//this right now returns the 3 event objects I added:
// (
// "<myapp.Event: 0x60800032ba40>",
// "<myapp.Event: 0x60800032bae0>",
// "<myapp.Event: 0x60800032bcc0>"
// )
self.forceReload(reloadEvent: true) //force reload eventually call the groupEventsBy days
}
func groupEventsByDays(){
// of course everything works without the next line of code
eventsBySection = mEvents.groupBy(keypath: "startTime").mutableCopy() as! NSMutableDictionary
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
var date = dateFormatter.date(from: "2016-10-01")
// right now daysToShow is equal to 30
for _ in 0..<daysToShow{
eventsBySection.setObject([], forKey: self.setFormatDate(date: date!) as NSCopying)
date = self.addDay(date: date!)
}
}
here is the problem. This is my extension.
extension NSArray{
func groupBy(keypath:NSString)->NSDictionary{
return self.groupBy(keypath: keypath, block: { (object, key) -> NSString in
return key
})
}
func groupBy(keypath:NSString,block:#escaping ((_ object: Any, _ key:NSString )-> NSString))-> NSDictionary{
let result:NSMutableDictionary = NSMutableDictionary()
let finalKeypath = String.localizedStringWithFormat("%#.distinctUnionOfObjects.self", keypath)
let distinct:NSArray = self.value(forKey: finalKeypath) as! NSArray
(distinct as AnyObject).each(operation: { (value) in
let predicate = NSPredicate(format: "%K = %#", keypath,value as! CVarArg)
let objects = self.filtered(using: predicate)
result.setObject(objects, forKey: (block(objects[0], value as! NSString)))
})
return result;
}
func each(operation:#escaping ((_ object: AnyObject)-> Void)){
self.enumerateObjects({ (object, idx, stop) in
operation(object as AnyObject)
})
}
}
it crashes with the error this class is not key value coding-compliant for the key startTitle.distinctUnionOfObjects.self.'
I have tried to use map like this
let startDate = array.map ({ $0.startTime })
I managed to get all the date (no distinct though) but I have no idea how to achieve the same result shown in the above code using swift.
I finally managed to do what the above objective c code does with #distinctUnionOfObjects.sel. I am not really sure this is an elegant way of doing it though. All comments or better answers are welcome.
extension Collection {
func find( predicate: (Self.Iterator.Element) throws -> Bool) rethrows -> Self.Iterator.Element? {
return try index(where: predicate).map({self[$0]})
}
}
override func viewDidLoad() {
super.viewDidLoad()
let event1 = Event(startTime: today!, duration: 60, title: "prova", subtitle: "HEllo")
let event2 = Event(startTime: (today?.dateByAddingDays(days: 5))!, duration: 60, title: "prova", subtitle: "HEllo")
let event3 = Event(startTime: (today?.dateByAddingDays(days: 1))!, duration: 60, title: "prova", subtitle: "HEllo")
let event4 = Event(startTime: todayLater!, duration: 60, title: "prova", subtitle: "HEllo")
var array:[Event] = []
array.append(event1)
array.append(event2)
array.append(event3)
array.append(event4)
// I create an array with all the date/startTime
let startTime = array.map ({ $0.startTime })
let dict:NSMutableDictionary = [:]
for date in startTime {
//find the objects for that date
let object = array.find(predicate: {$0.startTime?.toDeviceDateString() == date?.toDeviceDateString()})
//check if that key/date exist in the dictionary
if var val:[Event] = dict[(date?.setFormatDate())!] as! [Event]? {
//if it does I simply add the object to the array
val.append(object!)
dict.setObject(val, forKey: date?.setFormatDate() as! NSCopying)
} else {
print("key is not present in dict")
//otherwise I add a new array with that object inside for the date/key
dict.setObject([object], forKey: date?.setFormatDate() as! NSCopying)
}
}
calendarView.setEvents(events: dict)
}
func setEvents(events:NSMutableDictionary){
//slots events hold the events objects
slotEvents = events
self.forceReload(reloadEvent: true)
}
func groupEventsByDays(){
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
var date = dateFormatter.date(from: "2016-10-01")
for _ in 0..<daysToShow{
if let val:[Event] = slotEvents[(date?.setFormatDate())!] as! [Event]? {
eventsBySection.setObject(val, forKey: date?.setFormatDate() as! NSCopying)
}else{
eventsBySection.setObject([], forKey: date?.setFormatDate() as! NSCopying)
}
date = self.addDay(date: date!)
}
print("after\(eventsBySection)")
//Which print
//{
//"2016-10-01" = (
// );
//"2016-10-02" = (
// );
// "2016-10-03" = (
// "Optional(<myapp.Event: 0x6000001242e0>)",
// "<myapp.Event: 0x6000001242e0>"
// );
// "2016-10-04" = (
// "Optional(<myapp.Event: 0x600000124600>)"
// );
// "2016-10-05" = (
// );
// "2016-10-06" = (
// );
// "2016-10-07" = (
// );
// "2016-10-08" = (
// "Optional(<myapp.Event: 0x600000124240>)"
// );
// "2016-10-09" = (
// );
//.... and so on up to 30 days
}
Related
Below is my function which is not changing the return Value. How do I get the function to return the modified returnVal?
func RecieveActivitySummary() -> HKActivitySummary {
var returnVal = HKActivitySummary()
self.makeQuery() { (summary) in
returnVal = summary //attempting to alter returnVal
print(returnVal) //prints out returnVal object that I want with data (seemingly modified)
}
print(returnVal) //prints out unmodified returnVal
return returnVal //then goes on to return an empty returnVal object
}
Here is my makeQuery() function if it helps address the problem:
func makeQuery(completion: #escaping (_ summary : HKActivitySummary) -> ()) {
let calendar = NSCalendar.current
let endDate = Date()
guard let startDate = calendar.date(byAdding: .day, value: 0, to: endDate) else {
fatalError("error")
}
let units: Set<Calendar.Component> = [.day, .month, .year, .era]
var startDatecomps = calendar.dateComponents(units, from: startDate)
startDatecomps.calendar = calendar
var endDatecomps = calendar.dateComponents(units, from: endDate)
endDatecomps.calendar = calendar
let summariesWithinRange = HKQuery.predicate(forActivitySummariesBetweenStart: startDatecomps, end: endDatecomps)
let query = HKActivitySummaryQuery(predicate: summariesWithinRange) {
(sample, results, error) -> Void in
if let results = results {
var summary = results[0]
completion(summary)
}
}
healthstore.execute(query)
}
I'm trying to load sleep data from healthkit.
after retrieving some data, I converted it into Double type to use chart, and reflected them on setChart function.
But here's some problem.
To successfully show on chart, my function should executed in order.
Ideal order is : retrieve data, convert data -> setchart
but the order is not kept.
I read some articles about dispatchqueue, but still I can't solve the problem.
What should I do to solve this problem? \
override func viewDidLoad() {
super.viewDidLoad()
//선행작업
DispatchQueue.global(qos: .userInteractive).sync {
print("1")
self.retrieveSleepAnalysis()
}
DispatchQueue.global(qos: .default).sync {
print("2")
self.recentSleepStartHourDouble = self.stringTimeToDouble(stringTime: self.recentSleepStartHour)
self.wakeUp = self.wakeupTimeCalcuation(start: self.recentSleepStartHourDouble, end: self.resultToSleepAmount)
}
DispatchQueue.main.async {
// self.recentSleepStartHourDouble = self.stringTimeToDouble(stringTime: self.recentSleepStartHour)
// self.wakeUp = self.wakeupTimeCalcuation(start: self.recentSleepStartHourDouble, end: self.resultToSleepAmount)
self.setChart(days: self.recentSleepDate.reversed(), sleepTimes: self.recentSleepStartHourDouble.reversed(), wakeupTimes:
public func retrieveSleepAnalysis() {
// first, we define the object type we want
if let sleepType = HKObjectType.categoryType(forIdentifier: HKCategoryTypeIdentifier.sleepAnalysis) {
// print(sleepType)
// Use a sortDescriptor to get the recent data first
let sortDescriptor = NSSortDescriptor(key: HKSampleSortIdentifierEndDate, ascending: false)
// we create our query with a block completion to execute
let query = HKSampleQuery(sampleType: sleepType, predicate: nil, limit: 7, sortDescriptors: [sortDescriptor]) { (query, tmpResult, error) -> Void in
if error != nil {
// something happened
return
}
if let result = tmpResult {
for item in result {
if let sample = item as? HKCategorySample {
let value = (sample.value == HKCategoryValueSleepAnalysis.inBed.rawValue) ? "InBed" : "Asleep"
print("Healthkit sleep: \(sample.startDate) \(sample.endDate) - value: \(value)")
let sleepHour = Calendar.current.component(.hour, from: sample.startDate)
print("현지시각으로 잠든시간 \(sleepHour)")
if sleepHour < 19 && sleepHour > 12{
print("낮잠")
}
else{
self.resultToSleepAmount.append(CFDateGetTimeIntervalSinceDate(sample.endDate as CFDate, sample.startDate as CFDate)/3600)
let myDateFormatter = DateFormatter()
myDateFormatter.dateFormat = "MM / dd"
myDateFormatter.locale = Locale(identifier: "ko_KR")
let sleepDate = myDateFormatter.string(from: sample.startDate)
self.recentSleepDate.append(sleepDate)
let myHourFormatter = DateFormatter()
myHourFormatter.dateFormat = "HHmm"
myHourFormatter.locale = Locale(identifier: "ko_KR")
let sleepStartHour = myHourFormatter.string(from: sample.startDate)
self.recentSleepStartHour.append(sleepStartHour)
print("잠든 시간은 몇시몇분? \(sleepStartHour)")
let sleepEndHour = myHourFormatter.string(from: sample.endDate)
self.recentSleepEndHour.append(sleepEndHour)
}
}
print("total amount of sleep time : \(self.resultToSleepAmount), 현재 크기는 : \(self.resultToSleepAmount.count)")
}
}
}
// finally, we execute our query
healthStore.execute(query)
}
this is my respone
{
activeFromDate = "01/01/2017";
terminateDate = “02/05/2019”;
}
{
activeFromDate = "01/01/2013";
terminateDate = "<null>";
}
{
activeFromDate = "01/01/2017";
terminateDate = "02/05/2018";
}
{
activeFromDate = "07/01/2012";
terminateDate = "<null>";
}
{
activeFromDate = "01/01/2017";
terminateDate = "02/05/2019";
}
this is my code
let answerArray = NSMutableArray()
for i in 0..<arr.count
{
let dict = Dictionary[i] as! NSDictionary
let name1 = dict.value(forKey:"terminateDate") as! String
if(name1 == "")
{
print (answerArray.add(dict))
}
}
this is my nsdictionary response
how to get array count if terminatedDate is null and terminatedDate is greater than today date?
I have created a sample to read json file placed in your project. and have integrated the code as per your requirement.
Json File
{"Status":"success","Data":[
{"activeFromDate":"01/01/2017","terminateDate":"02/05/2019"},
{"activeFromDate":"01/01/2013","terminateDate":null},
{"activeFromDate":"01/01/2017","terminateDate":"02/05/2018"},
{"activeFromDate":"07/01/2012","terminateDate":null},
{"activeFromDate":"01/01/2017","terminateDate":"02/05/2016"},
{"activeFromDate":"01/01/2017","terminateDate":"02/05/2019"}
]
}
In your View Controller
import UIKit
class HomeViewController: UIViewController {
let answerArray = NSMutableArray()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
jsonParsingFromFile()
}
func jsonParsingFromFile()
{
let path: NSString = Bundle.main.path(forResource: "tjw", ofType: "json")! as NSString
let data : NSData = try! NSData(contentsOfFile: path as String, options: NSData.ReadingOptions.dataReadingMapped)
self.startParsing(data: data)
}
func startParsing(data :NSData)
{
let dict: NSDictionary!=(try! JSONSerialization.jsonObject(with: data as Data, options: JSONSerialization.ReadingOptions.mutableContainers)) as? NSDictionary
//print(dict)
guard let dataArr:NSArray = dict.value(forKey: "Data") as? NSArray else {
return
}
print(dataArr.count)
for i in 0..<dataArr.count{
guard let currentDict:NSDictionary = dataArr[i] as? NSDictionary else {
return
}
let activeFromDateStr:String = currentDict.value(forKey: "activeFromDate") as? String ?? ""
let terminateDateStr:String = currentDict.value(forKey: "terminateDate") as? String ?? ""
print(activeFromDateStr, terminateDateStr)
if terminateDateStr != ""{
let date2 = convertToDate(dateStr: terminateDateStr)
let today = Date()
if date2>today{
answerArray.add(currentDict)
}
}else{
answerArray.add(currentDict)
}
}
print(answerArray)
}
func convertToDate(dateStr:String)->Date{
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd/MM/yyyy"
dateFormatter.locale = Locale(identifier: "en_IN")
let date = dateFormatter.date(from: dateStr)!
return date
}
}
There was a similarly named topic but the example was an error due to user mistake. I believe this example is an actual XCode issue.
I was following a treehouse tutorial and in the spirit of swift 2.0 I used guard statements instead of if lets in the initializer. My code was identical to the instruction except for the use of guard statements. It had one error that said "return from initializer without initializing all stored properties". Once I changed it to if let statements, it worked. Perhaps I made a mistake somewhere but I stared at it for atleast an hour, no properties were left un-initialized.
I made the properties equal to nil in the else clauses just in case but that didnt affect anything.
struct DailyWeather {
let maxTemp: Int?
let minTemp: Int?
let humidity: Int?
let precipChance: Int?
var summary: String?
var icon: UIImage? = UIImage(named: "default.png")
var largeIcon: UIImage? = UIImage(named: "default_large.png")
var sunriseTime: String?
var sunsetTime: String?
var day: String?
let dateFormatter = NSDateFormatter()
init(dailyWeatherDictionary: [String:AnyObject]) {
minTemp = dailyWeatherDictionary["temperatureMin"] as? Int
maxTemp = dailyWeatherDictionary["temperatureMax"] as? Int
guard let humidityFloat = dailyWeatherDictionary["humidity"] as? Double else { humidity = nil ; return }
humidity = Int(humidityFloat * 100)
guard let precipFloat = dailyWeatherDictionary["precipProbability"] as? Double else { precipChance = nil ; return }
precipChance = Int(precipFloat * 100)
summary = dailyWeatherDictionary["summary"] as? String
guard let
iconString = dailyWeatherDictionary["icon"] as? String,
iconEnum = Icon(rawValue: iconString) else { icon = nil ; largeIcon = nil ; return }
(icon, largeIcon) = iconEnum.toImage()
guard let sunriseDate = dailyWeatherDictionary["sunriseTime"] as? Double else { sunriseTime = nil ; return }
sunriseTime = timeStringFromUnixTime(sunriseDate)
guard let sunsetDate = dailyWeatherDictionary["sunsetTime"] as? Double else { sunsetTime = nil ; return }
sunsetTime = timeStringFromUnixTime(sunsetDate)
guard let time = dailyWeatherDictionary["time"] as? Double else { day = nil ; return }
day = dayStringFromUnixTime(time)
}
func timeStringFromUnixTime(unixTime: Double) -> String {
let date = NSDate(timeIntervalSince1970: unixTime)
dateFormatter.dateFormat = "hh:mm a"
return dateFormatter.stringFromDate(date)
}
func dayStringFromUnixTime(unixTime: Double) -> String {
let date = NSDate(timeIntervalSince1970: unixTime)
dateFormatter.locale = NSLocale(localeIdentifier: NSLocale.currentLocale().localeIdentifier)
dateFormatter.dateFormat = "EEEE"
return dateFormatter.stringFromDate(date)
}
}
let's have
struct S {
var i: Int?
init(b: Bool){
guard b == false else { return }
//if b == true { return }
i = 0 // if b == true, this statement doesn't execute
}
}
let s1 = S(b: true)
let s2 = S(b: false)
print(s1, s2) // S(i: nil) S(i: Optional(0))
because var i: Int? has a default value nil, even though i = 0 is not reachable if parameter of init is true, the compiler doesn't complain.
struct S {
let i: Int?
init(b: Bool){
guard b == false else { return }
//if b == true { return }
i = 0 // if b == true, this statement doesn't execute
}
}
will NOT compile, with error: return from initializer without initializing all stored properties and note: 'self.i' not initialized, because constant let i: Int? doesn't have any default value
Your trouble is, that you return from init. Normally, avoid return from an initializer if your initializer is not fail-able / init? /. In case of fail-able init? the only accepted return value is nil.
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?
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.