UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

Cannot use instance member 'property' within property initializer; property initializers run before 'self' is available

Forums > SwiftUI

I'm making a weather app and wanted to implement changing location to different cities and I'm getting this error: Cannot use instance member 'city' within property initializer; property initializers run before 'self' is available Is there some way to initialize this "city" variable before the property initializer? Here's my code:

struct API {
    var city = "London"

    //: [Get your API Key here](https://openweathermap.org/api "Open Weather Map API")
    static let key = URLQueryItem(name: "APPID", value: .apiKey)

    //MARK: URL EndPoints
    static var baseURL = URLComponents(string: .url)
    var searchString = URLQueryItem(name: .query, value: city)

    //Basic Weather URL
    func locationForecast() -> URL?  {
        API.baseURL?.queryItems?.append(searchString)
        API.baseURL?.queryItems?.append(API.key)
        return API.baseURL?.url
    }
}

1      

Capslock puts the horse before the cart:

Is there some way to initialize this "city" variable before the property initializer?

Commit this rule to memory! All vars in a struct must be initialized before you can use any of them.

You are attempting to initialize the searchString var using the city var. You can't use the city var until all the vars in the struct have been initialized.

This might be a great use case for computed vars.

struct API {
    // Cool! Define a city! It's the first to get initialized.
    // Plot twist!  It may NOT be the first var initialized.
    var city = "Cottington" // Don't forget your towel!

    // Swift must initialize ALL vars in a struct, 
    // before the struct can be used.
    // Whilst this is AFTER the city declaration above, Swift does
    // NOT guarantee the order in which vars are initialized.
    // Consequently, Swift cannot create the var badQueryItem
    // because it uses another var named city.
    // Indeed, city may not yet exist.
    var badQueryItem = URLQueryItem(name: "City", value: city)

    // Computed vars are not calculated until needed.
    // This will happen after a struct is initialized.
    var queryCityItem: URLQueryItem {
        URLQueryItem(name: "City", value: city)
    }
}

Keep coding!

Please return here and share with the community how you solved this problem.

Variable Names

Also, take a moment and review your var names.

If my team were providing feedback during a sprint code review, we might question variable and function names.

  1. Why does the function locationForecast() return a URL? Its name suggests it returns a weather forecast for a location! Consider renaming to locationURL and perhaps making it a computed var.
  2. Variable searchString is not a String at all. It's a URLQueryItem object. Plus it's configured only for a city. Consider renaming to cityQueryItem.

1      

hi,

the problem is that you are trying to use the value of API.city in URLQueryItem to set the value of API.searchString (i.e., before the struct is completely initialized).

the following should work: use an explicit initializer. (by the way, i assume you have defined String.query, String.url, and String.apiKey.)

struct API {

    static let key = URLQueryItem(name: "APPID", value: .apiKey)
    static var baseURL = URLComponents(string: .url)

    var city: String
    var searchString: URLQueryItem

    init(city: String) {
        self.city = "London"
        searchString = URLQueryItem(name: .query, value: city)
    }

    func locationForecast() -> URL?  {
        API.baseURL?.queryItems?.append(searchString)
        API.baseURL?.queryItems?.append(API.key)
        return API.baseURL?.url
    }
}

hope that helps,

DMG

1      

Hacking with Swift is sponsored by Essential Developer

SPONSORED Join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer! Hurry up because it'll be available only until April 28th.

Click to save your free spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.