I removed the tildar and fed a absolute path "file:///Users/yimin/Downloads/test1.xml" as URL, but the problem persists.
Did you make this change literally? That is, write this:
let inputPath = "file:///Users/yimin/Downloads/test1.xml"
let inputURL = URL(fileURLWithPath: inputPath)
If so, that’s still not correct (sorry I didn’t point this out last time).
URL.init(fileURLWithPath:)
expects a path, so you should write this:
let inputPath = "/Users/yimin/Downloads/test1.xml"
let inputURL = URL(fileURLWithPath: inputPath)
You could have used
URL.init(string:)
but I recommend that you stick with
init(fileURLWithPath:)
because it takes care of some wacky edge cases.
As to why this traps, that seems to be the result of weird interactions between the Swift wrapper and the Foundation implementation. Given that
XMLParser.init(contentsOf:)
is a failable initialiser, I would expect it to respond to a bogus file URL by either:
I’ve filed a bug about this (r. 28691540).
The obvious workaround here is to not subclass
XMLParser
(see below). Alternatively, you could call
init(data:)
or
init(stream:)
.
Why XMLParser should not be inherited in this way?
Consider the following
XMLParser
delegate methods:
parser(_:didStartElement:namespaceURI:qualifiedName:attributes:)
parser(_:didEndElement:namespaceURI:qualifiedName:)
These are absolutely critical to how
XMLParser
works; essentially the parser calls these delegate methods as it enters and leaves the various XML elements.
Now, look at the public API for
XMLParser
itself. There’s no equivalent:
didStartElement(_:namespaceURI:qualifiedName:attributes:)
didEndElement(_:namespaceURI:qualifiedName:)
methods to override. So, how is your subclass going to function at all? Your only option is to make
MusicXMLParser
its own delegate. There’s nothing inherently wrong about that but it does limit your options. For example, the SeismicXML sample that I referenced in my earlier post puts its parsing code in an
Operation
subclass, and you can’t simultaneously be a subclass of both
XMLParser
and
Operation
.
Speaking more philosophically, inheritance is one of many different programming paradigms supported by Swift. When you use library code it’s best to follow the paradigm expected by that code. So, for example:
if you’re using
Operation
, in many cases you’ll find yourself subclassing Operation
because that’s how that class is designedif you’re using
XMLParser
, you almost never subclass XMLParser
because it was designed with delegation in mind
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
let myEmail = "eskimo" + "1" + "@apple.com"