0

I would like the MKMapItem returned from MKLocalSearch to contain an "altitude" property. In order to achieve this, I've decided to create a subclass for MKMapItem.

class MapItemGeoSpatial: MKMapItem {
    var altitude: Measurement<UnitLength>
    
    public init(placemark: MKPlacemark, altitude: Measurement<UnitLength>) {
        self.altitude = altitude
        super.init(placemark: placemark)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

While the above implementation compiles, it results in a fatal error when attempting to initialise MapItemGeoSpatial.

Fatal error: Use of unimplemented initializer 'init()' for class 'MapItemGeoSpatial'

The above error occurs during the super.init(placemark: placemark) call.

I can create an override init() for the above class, but this will require me to initialise the altitude property, which is not specified for this initialiser. Initialising altitude by specifying a dummy variable (eg. 0) overcomes this issue, but appears to be a poor workaround. Making altitude optional is another workaround, but this is not a direction I wish to take.

I'm aware that MKMapItem inherits from NSObject and I'm curious if this relation has an influence on the above observation. I would like to i) understand the root cause behind this issue and ii) determine if subclassing MKMapItem is a viable solution to the problem mentioned at the start of this post.

Ranveer
  • 21
  • 1
  • 3
  • Apologies as I did not mention this, but altitude is set by me (the source of this value is not relevant to this discussion, but it is determined by extracting the coordinates from `MKMapItem`) via the designated initialiser `. As such, I understand that `MKLocalSearch` has nothing to do with altitude, but I, as the client, found it desirable to contain this information when it is passed to other areas of my project. This is the primary reason why I chose to subclass `MKMapItem`, in an attempt to "inherit" all it's functionality and introduce my own functionality. – Ranveer Apr 28 '22 at 04:27
  • The flow diagram for this process is- `MKLocalSearch` -> `MKMapItem ` -> Determine altitude using coordinates from `MKMapItem` -> Initialise `MapItemGeoSpatial` – Ranveer Apr 28 '22 at 04:29
  • 1
    You don't need to subclass in that case. You can just wrap it. – matt Apr 28 '22 at 04:31
  • Right I see- so just encapsulate `MKMapItem` within `MapItemGeoSpatial`? Yep that's a simpler solution. – Ranveer Apr 28 '22 at 04:34

1 Answers1

0

@matt's comment suggests to wrap MKMapItem, which is a viable solution for the original question.

For those interested in the reason behind the crash, I posted the same question in the Apple Developer Forum, and one of the comments suggested a potential cause. I'll summarise it in this post.

The below diagram represents the general overview for the initialisation process in Swift (see Class Inheritance and Initialization for more information). Take note that designated initialisers can not invoke convenience initialisers from the superclass. Swift Subclass Initialisation

The process for subclassing an Objective-C object (eg. MKMapItem) in Swift however does not follow the above convention. In particular-

  1. Objective-C allows a convenience initialiser of a superclass to be invoked from a subclass
  2. Objective-C classes automatically inherit superclass initialisers (Swift requires certain conditions to be met for this to occur)

MapItemGeoSpatial from the original question does not meet the requirements from the second point above to inherit the superclass initialisers. In addition, MKMapItem.init(placemark:) appears to be a convenience initialiser as it invokes MKMapItem.init() internally (see point 1. on why MapItemGeoSpatial can call it from the designated initialiser).

The below diagram attempts to visualise the above.

enter image description here

Disclaimer

I do not use Objective-C and I don't have a good foundation in the language. The above findings are based on observations and the information gathered from the specified resources. I would appreciate if someone with a better understanding of Objective-C and Swift provides a more detailed explanation or specifies any corrections.

Ranveer
  • 21
  • 1
  • 3