nmdias / FeedKit

An RSS, Atom and JSON Feed parser written in Swift
MIT License
1.19k stars 174 forks source link

Crashes when trying to parse a feed URL offline #4

Closed enricenrich closed 7 years ago

enricenrich commented 8 years ago

For some reason, when trying to parse a URL in offline mode with FeedKit, the app crashes. If there's an Internet connection it works as expected.

nmdias commented 8 years ago

I can't help but wonder if this is an error in the Foundation's XMLParser. I was able to replicate the crash, and it happens when calling

Parser(contentsOf: URL)

The 'Parser' class is actually a subclass of the foundation's XMLParser, and this is nothing but a call to a convenience initializer of the XMLParser itself.

Documentation says that it should return:

An initialized NSXMLParser object or nil if an error occurs.

And there is a check for that that propagates the failable initializer:

public init?(URL: URL) {

    guard let parser = Parser(contentsOf: URL) else {
        return nil
    }

    self.parser = parser

}

I'll have to dig deeper..

enricenrich commented 8 years ago

I tried to call directly XMLParser(contentsOf: URL) and it didn't crash. So it's something in the library, not XMLParser.

nmdias commented 8 years ago

Just tried to isolate the issue:

Apparently this works:

if let parser = XMLParser(contentsOf: feedURL) {
    print("Got instance \(parser)")
}

This does not:

class Parser: XMLParser { }

if let parser = Parser(contentsOf: feedURL) {
    print("Got instance \(parser)")
}

It's clean project, with nothing but those lines of code. The issue appears to happen only to subclasses of the XMLParser.

Any ideas? I might just have to submit a bug report.

nmdias commented 8 years ago

As a temporary solution, i found that you can safely do this:

if let data = NSData(contentsOf: feedURL) as? Data {

    FeedParser(data: data).parse({ (result) in
        // do your thing
    })

}
enricenrich commented 8 years ago

Maybe it's related to overriding

override init(data: Data) {
    super.init(data: data)
    self.delegate = self
}

Did you try to remove it to see if it crashes?

nmdias commented 8 years ago

Yes, I did.

Take this example for instance:

class Parser: XMLParser { }

let feedURL = URL(string: "http://images.apple.com/main/rss/hotnews/hotnews.rss")!

if let parser = Parser(contentsOf: feedURL) {
    print("Got instance \(parser)")
}

In this example, the Parser class is not actually overriding anything. All it's doing is saying: Hello! I'm a subclass of XMLParser. Nothing else. And it still crashes!

I'll keep digging some more...

nmdias commented 8 years ago

Submitted a bug report to Apple with number 28904764 and opened up a Radar to this issue.

In the meantime I'll cook a workaround, using NSData's contentsOf init and release a fixed version.

RJiryes commented 8 years ago

Hi, any updates? Thanks!

nmdias commented 8 years ago

Hi @RJiryes

I sent crash logs to Apple after their request, about 2 days ago. We just have to wait now, and hope their next release comes with a fix.

For now, please consider the following alternative:

if let data = NSData(contentsOf: feedURL) as? Data {

    FeedParser(data: data).parse({ (result) in
        // do your thing
    })

}
alvaroblazmon commented 7 years ago

Hi, any update? thanks

nmdias commented 7 years ago

@alvarozizou

Apple engineers aren't able to reproduce this bug, and I just don't have time to go back and forward in the bug reporter with them.

You can always use the workaround described above.

I'm also working on version 6 of FeedKit, that will bypass this bug. Time however isn't much so it's taking awhile.