7

I'm working on a pull-to-refresh on iOS with Swift.
I have an array with city names, cityNames = ["Chicago", "New York City"]
I implemented a pull-to-refresh to fetch temperature data from the internet. So every time I trigger the pull-to-refresh, it will go to the internet and get the temperature for each city in the cityNames array.
Here is the code for pull-to-refresh

var weatherDetail = [Weather]()
// Pull to refresh
func refreshData() {
    var cityNames = [String]()
    for (index, _) in weatherDetail.enumerate() {
        let info = weatherDetail[index]
        cityNames.append(info.cityName)
    }
    print(cityNames)
    weatherDetail.removeAll()
    for city in cityNames {
        self.forwardGeocoding(city)
    }
    weatherCityTable.reloadData()
    refreshControl.endRefreshing()
}

In the code above, weatherDetail is a array of model(I'm not sure how to phrase this, but Weather is a model, which contains city names, temperature, sun rise time, high/low temperature.
forwardGeocoding is a function that get the geo coordination for a city then sends a request to get the weather data for that city.
The pull-to-refresh works, the issue I'm encountering is, for the first 2,3 times when I pull, it works with no problem. But as I pull more times, the array will suddenly change to cityNames = ["Chicago", "Chicago"]
Thank you for your help, please let me know if you need more information.
UPDATE:
I removed weatherDetail.removeAll(), try to just append the same data to the array. After the refresh, it prints out "Chicago", "New York City", "Chicago", "Chicago". If I refresh it more times, it prints out something like "Chicago", "New York City", "Chicago", "Chicago", "Chicago", "Chicago"

f_qi
  • 689
  • 8
  • 21

3 Answers3

5

Is forwardGeocoding synchronous? When does weatherDetail get set/updated?

It looks to me like you have some sort of synchronicity issue going on here, probably exacerbated by latency.

Michael
  • 1,213
  • 6
  • 9
4

Using enumerate() and append() to do this is not a good approach ,there is a more elegance and error-proof way to achieve this:

let cityNames:[String] = weatherDetail.map { weather -> String in
     weather.cityName
}

Or just write:

let cityNames:[String] = weatherDetail.map { $0.cityName }
wj2061
  • 6,778
  • 3
  • 36
  • 62
3

If city names are repeated twice, that means that information in weatherDetail array is repeated twice too. Try printing weatherDetail before printing cityNames. If weatherDetail is repeated twice, then you should locate the code that adds the same Weather objects twice and eliminate it.

For testing purposes, locate every place that modifies weatherDetail, and before those statements put weatherDetail.removeAll(). If that removes your problem, then search for the code that adds redundant info to weatherDetail.

xinatanil
  • 1,085
  • 2
  • 13
  • 23
  • The issue is not the city names are repeated twice, it got replaced to the same value. – f_qi Apr 03 '16 at 20:23
  • Did you try printing `weatherDetail` before `cityNames`? Does it contain the same `Weather` info in all elements? Did you test your bug on an array with 5-10 objects? `cityNames` is just a result of mapping `weatherDetail`, so I'm pretty sure you have repeating values in your `weatherDetail`, and that's the root of all evil. – xinatanil Apr 03 '16 at 20:27
  • Since `weatherDetail` is made with a model, when I print it out, all I got is `[, ]`. When I test it with 5-10 objects, the array will become `["Chicago", "Chicago", "Chicago", "New York", "New York", "Washington", "Washington", "Washington", "Beijing"]` While I originally put in 9 different cities. – f_qi Apr 03 '16 at 20:33
  • print in a loop `weather.cityName`, something like this: `for weatherInfo in weatherDetail { print(weatherInfo.cityName) }` . If you see repeating values, then the trouble is in your weatherDetail array and you should try to find where you put the same values again and again. – xinatanil Apr 03 '16 at 20:36
  • When I print it out, I got different city names, no repeating value. I used `for weather in weatherDetail { print(weather.cityName) }`. Therefore, it means the original loop contains error. At least it provides me a direction. – f_qi Apr 03 '16 at 20:44
  • Is the implementation of refreshData() complete? I'm 99% sure that it's impossible for cityNames to contain different city names. Could you please try this piece of code right in the beginning of method: http://pastebin.com/L6WL6MjX . If the content of print is different, then I'm 99% sure you're doing something wrong. – xinatanil Apr 03 '16 at 20:57
  • I put the piece of code in the beginning of the method, I got the following `New York Chicago Los Angles Mosco Albany ["New York", "Chicago", "Los Angles", "Mosco", "Albany"]` – f_qi Apr 03 '16 at 21:00
  • Okay, now please replace your function with this one http://pastebin.com/LeuyS9wa . If that doesn't help, I give up. – xinatanil Apr 03 '16 at 21:05
  • Thank you for the help! I appreciate that. I put the code in, here is the result. `["New York", "Chicago", "Los Angles", "Mosco", "Albany"] ["Los Angles", "Los Angles", "Los Angles", "Los Angles", "Los Angles"] ` When I refresh it for the first time, it changed from 5 different cities to all LA, but still prints the 5 different cities. Then I refreshed it for the second time, it print all LA. – f_qi Apr 03 '16 at 21:08
  • Now I am 100% sure that weatherDetail simply contains the same cities. If you show me the full code of your view controller, I might be able to spot your bug. – xinatanil Apr 03 '16 at 21:11
  • https://github.com/qi1f/JWeather/blob/master/JWeather/JWeather/ViewController.swift This is the vie controller. – f_qi Apr 03 '16 at 21:15
  • There's a very suspicious method `setWeather(weather: Weather)` which is the only place that modifies your weatherDetail. I'd look for the bug there. I give up, I'll just go to sleep. – xinatanil Apr 03 '16 at 21:31
  • I'll look into that. Thanks anyway. – f_qi Apr 03 '16 at 21:33