Is this bad practice?

I am a “newbie” to Coding and Swift. To better understand the Code I have started breaking it up into chunks and formatting as per my example below. My questions are 1) is “Is this bad practice”? 2) “Is it likely to lead to problems later on”?


let location = LocationHelper.currentLocation

class LocationHelper: NSObject, ObservableObject {

    

static let shared = LocationHelper()

static let DefaultLocation = CLLocationCoordinate2D(

latitude: (

thisCardPositionLatidude),

longitude: (

thisCardPositionLongitude))

static var currentLocation: CLLocationCoordinate2D {

guard let location = shared.locationManager.location else {

return DefaultLocation

}

return location.coordinate

}

    

private let locationManager = CLLocationManager()

    

private override init() {

super.init()

locationManager.delegate = self

locationManager.desiredAccuracy = kCLLocationAccuracyBest

locationManager.requestWhenInUseAuthorization()

locationManager.startUpdatingLocation()

}

}



extension LocationHelper: CLLocationManagerDelegate {

    

func locationManager(_ manager: CLLocationManager,

didUpdateLocations locations: [CLLocation]) { }

    

public func locationManager(_ manager: CLLocationManager,

didFailWithError error: Error) {

print("Location manager failed with error: \(error.localizedDescription)")

}

    

public func locationManager(_ manager: CLLocationManager,

didChangeAuthorization status: CLAuthorizationStatus) {

print("Location manager changed the status: \(status)")

}

}
Answered by Claude31 in 744615022

A good practice is to use code formatter to get proper identation…😉

let location = LocationHelper.currentLocation

class LocationHelper: NSObject, ObservableObject {
    
    static let shared = LocationHelper()
    
    static let DefaultLocation = CLLocationCoordinate2D(
        latitude: thisCardPositionLatidude,
        longitude: thisCardPositionLongitude)
    
    static var currentLocation: CLLocationCoordinate2D {
        
        guard let location = shared.locationManager.location else { return DefaultLocation }
        
        return location.coordinate
    }
    
    private let locationManager = CLLocationManager()
    
    private override init() {
        
        super.init()
        
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.requestWhenInUseAuthorization()
        locationManager.startUpdatingLocation()
    }
    
}


extension LocationHelper: CLLocationManagerDelegate {
    
    func locationManager(_ manager: CLLocationManager,
                         didUpdateLocations locations: [CLLocation]) { }
    
    public func locationManager(_ manager: CLLocationManager,
                                didFailWithError error: Error) {
        
        print("Location manager failed with error: \(error.localizedDescription)")
    }
    
    public func locationManager(_ manager: CLLocationManager,
                                didChangeAuthorization status: CLAuthorizationStatus) {
        
        print("Location manager changed the status: \(status)")
    }
    
}

I suppose your question is about extension ?

  • it is not a bad practice, on the contrary this is a very common practice
  • I personally usually have the func directly in the class, but that's a personal choice.

There are differences however,

Consider this example:

struct WithoutExtension {
    var x : Int = 10
    
    init(value: Int) {
        self.x = value
    }
}

struct WithExtension {
    var x : Int = 10
}

extension WithExtension {
    
    init(value: Int) {
        self.x = value
    }
}

let with = WithExtension()
let with2 = WithExtension(value: 20)
let without = WithoutExtension()    // Error: Missing argument for parameter 'value' in call
let without2 = WithoutExtension(value: 20)   

Or convenience init for classes

class WithoutExtension {
    var x : Int = 10
    
    init(value: Int) {
        self.x = value
    }
}

class WithExtension {
    var x : Int = 10
}

extension WithExtension {
    
    convenience init(value: Int) {
        self.x = value
    }
}

let with = WithExtension()
let with2 = WithExtension(value: 20)
let without = WithoutExtension()    // Error: Missing argument for parameter 'value' in call
let without2 = WithoutExtension(value: 20)

In both cases:

let without = WithoutExtension()   

will not compile, with error: Error: Missing argument for parameter 'value' in call But

let with = WithExtension()

will compile. Note: you don't need parenthesis round latitude or longitude parameters.

Accepted Answer

A good practice is to use code formatter to get proper identation…😉

let location = LocationHelper.currentLocation

class LocationHelper: NSObject, ObservableObject {
    
    static let shared = LocationHelper()
    
    static let DefaultLocation = CLLocationCoordinate2D(
        latitude: thisCardPositionLatidude,
        longitude: thisCardPositionLongitude)
    
    static var currentLocation: CLLocationCoordinate2D {
        
        guard let location = shared.locationManager.location else { return DefaultLocation }
        
        return location.coordinate
    }
    
    private let locationManager = CLLocationManager()
    
    private override init() {
        
        super.init()
        
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.requestWhenInUseAuthorization()
        locationManager.startUpdatingLocation()
    }
    
}


extension LocationHelper: CLLocationManagerDelegate {
    
    func locationManager(_ manager: CLLocationManager,
                         didUpdateLocations locations: [CLLocation]) { }
    
    public func locationManager(_ manager: CLLocationManager,
                                didFailWithError error: Error) {
        
        print("Location manager failed with error: \(error.localizedDescription)")
    }
    
    public func locationManager(_ manager: CLLocationManager,
                                didChangeAuthorization status: CLAuthorizationStatus) {
        
        print("Location manager changed the status: \(status)")
    }
    
}

I suppose your question is about extension ?

  • it is not a bad practice, on the contrary this is a very common practice
  • I personally usually have the func directly in the class, but that's a personal choice.

There are differences however,

Consider this example:

struct WithoutExtension {
    var x : Int = 10
    
    init(value: Int) {
        self.x = value
    }
}

struct WithExtension {
    var x : Int = 10
}

extension WithExtension {
    
    init(value: Int) {
        self.x = value
    }
}

let with = WithExtension()
let with2 = WithExtension(value: 20)
let without = WithoutExtension()    // Error: Missing argument for parameter 'value' in call
let without2 = WithoutExtension(value: 20)   

Or convenience init for classes

class WithoutExtension {
    var x : Int = 10
    
    init(value: Int) {
        self.x = value
    }
}

class WithExtension {
    var x : Int = 10
}

extension WithExtension {
    
    convenience init(value: Int) {
        self.x = value
    }
}

let with = WithExtension()
let with2 = WithExtension(value: 20)
let without = WithoutExtension()    // Error: Missing argument for parameter 'value' in call
let without2 = WithoutExtension(value: 20)

In both cases:

let without = WithoutExtension()   

will not compile, with error: Error: Missing argument for parameter 'value' in call But

let with = WithExtension()

will compile. Note: you don't need parenthesis round latitude or longitude parameters.

Also, standard practice is that type names start with a capital letter and all other names start with a lowercase letter:

static let defaultLocation = CLLocationCoordinate2D( /* ... */ )
//         ^

Great advice in this thread. For static data, what do folks think about moving them out of the class and into a structure? The data is global, or at least common across all class instances. Not always feasible. However, this way multiple static structures can be located in a "Statics.swift" and reduce class line counts.

import Cocoa

///relocate static data away from instance specific data
struct OurFavorites {
    static var food = "Orange"
    static var number = 21
    static var flag = true
}

class MyLikes {
    /// unnecessary but helpful:  tightly couple a class's static data  to the class instance
    let ourFavorites = OurFavorites.self

    var myFavoriteWord:String
    
    init(myFavoriteWord:String) {
        self.myFavoriteWord = myFavoriteWord 
    }

    ///without ourFavorites,  OurFavorites.food works too.
    func display() {
        print("\(myFavoriteWord) \(ourFavorites.food)")
    }
}

var a = MyLikes(myFavoriteWord: "Happy")
var b = MyLikes(myFavoriteWord: "Nice")

a.display()
b.display()

OurFavorites.food="Apple"

a.display()
b.display()

@const_void That's a different point, better be a new thread …

It is always good and less error prone to structure data in struct instead of having them in disparate constants or var.

Similarly, creating enum is more robust than having individual cases defined by constants.

And of course, if the struct is used in several places in the app, it is better to declare it globally.

However, if the properties of the struct can change, you need to take care of concurrency issues. In such a case it is better to define a singleton.

 am a “newbie” to Coding and Swift. To better understand the Code I have started breaking it up into chunks and formatting as per my example below. My questions are 1) is “Is this bad practice”? 2) “Is it likely to lead to problems later on”?

hey @GMacD53

I don’t understand why the answers are about structs versus enums versus……. when my question was about reformatting the code into chunks and in line?

Class properties are code.

In general, over time, you may find you want to modularize your code to simplify what the compiler / git has to do on code change..

  • Move static class properties into a struct -> new file
  • Move the global-> new file.
  • Refactor common code into helper functions -> new file

These all reduce the number of lines in your class. Xcode is very powerful as well - code folding, auto-indent, class browser, holding down the command key while moving the mouse, right click -> find symbol etc to quickly navigate have all helped me. have fun + good luck!

Is this bad practice?
 
 
Q