Reading plist resource from your iOS Framework library
Currently at my work i'm writing a lot of XCUITest
tests and therefore have to work closely to iOS development field and Swift ( which is exciting). However, moving from Scala/Java/Python field into this new language is a bit challenging, since iOS world works a lot different. So, in order to better understand how things work and how to write nice Swift code, i decided to start converting my Scala fabricator library into swift version . One issue that i recently faced was that i created some words.plist
resource file where i was storing around 10k of different english words in order to generate random words, sentences, paragraphs out of it. When i started reading about how to get data from plist
files, i was able to find solutions that would suggest to use something like
let url = Bundle.main.url(forResource: nameForTarget, ofType: "plist")
guard let fileContent = NSDictionary(contentsOf: URL) as? [String: Any] else {
error()
}
However, i was getting a nil in url
variable because it couldn't find the resource. I tried different variations , but the only solution that worked for me was :
static func getValue<T: Any>(of key: String,
from resourceName: String,
withExtension extention: String = "plist",
as type: T.Type) -> T? {
guard let URL = Bundle(for: self).url(forResource: resourceName, withExtension: extention) else {
print("I was not able to find \(resourceName).\(extention) resource file")
return nil
}
guard let fileContent = NSDictionary(contentsOf: URL) as? [String: Any] else {
print("I was not able to read \(key) content and convert it into [String: Any]")
return nil
}
return fileContent[key] as? T
}
This method allows you to read any data from plist
file and convert it to what you need :)
P.S. if you're writing unit tests for your library( like i do and you should do it too), then don't forget in XCode for your unit test target to go to Target -> Build Phases -> Copy Bundle Resources
and include your plist
file. Otherwise you'll get into a trouble :)