-Disclaimer-
I'm extremely new to iOS and Swift development, but I'm not particularly new to programming.
-免责声明-我对iOS和Swift开发非常陌生,但我对编程并不陌生。
I have a basic iOS
application with Swift3
elements in it.
I've created a plist
file with some entries I want to read and display in my application. (No write access is necessary)
我有一个包含Swift3元素的基本iOS应用程序。我创建了一个plist文件,其中包含一些我想在应用程序中读取和显示的条目。(不需要写访问)
How can you read a value for a given key for a bundled plist
file, in Swift3?
如何在Swift3中读取绑定plist文件的给定键的值?
This seems like a really simple question to me, but a bunch of searching is making me question my whole conceptual approach.
这对我来说似乎是一个非常简单的问题,但是大量的搜索让我对我的整个概念方法产生了疑问。
Helpful tips would be appreciated.
如果您能给我一些有用的建议,我将不胜感激。
7 个解决方案
#1
61
Same way you have done in Swift 2.3 or lower just syntax is changed.
与您在Swift 2.3或更低版本中所做的一样,只是语法被更改了。
if let path = Bundle.main.path(forResource: "fileName", ofType: "plist") {
//If your plist contain root as Array
if let array = NSArray(contentsOfFile: path) as? [[String: Any]] {
}
////If your plist contain root as Dictionary
if let dic = NSDictionary(contentsOfFile: path) as? [String: Any] {
}
}
Note: In Swift it is better to use Swift's generic type Array and Dictionary instead of NSArray
and NSDictionary
.
注意:在Swift中,最好使用Swift的泛型类型数组和字典,而不是NSArray和NSDictionary。
Edit: Instead of NSArray(contentsOfFile: path)
and NSDictionary(contentsOfFile:)
we can also use PropertyListSerialization.propertyList(from:)
to read data from plist
file.
编辑:我们也可以使用propertylistserializ.propertylist (from:)从plist文件中读取数据,而不是NSArray(contentsOfFile: path)和NSDictionary(contentsOfFile:)。
if let fileUrl = Bundle.main.url(forResource: "fileName", withExtension: "plist"),
let data = try? Data(contentsOf: fileUrl) {
if let result = try? PropertyListSerialization.propertyList(from: data, options: [], format: nil) as? [[String: Any]] { // [String: Any] which ever it is
print(result)
}
}
#2
2
Here is a Swift 3 implementation, based on Nirav D's answer:
以下是Swift 3的实现,基于Nirav D的回答:
/// Read Plist File.
///
/// - Parameter fileURL: file URL.
/// - Returns: return plist content.
func ReadPlist(_ fileURL: URL) -> [String: Any]? {
guard fileURL.pathExtension == FileExtension.plist, let data = try? Data(contentsOf: fileURL) else {
return nil
}
guard let result = try? PropertyListSerialization.propertyList(from: data, options: [], format: nil) as? [String: Any] else {
return nil
}
print(result)
return result
}
#3
2
Here is example how to get BundleID from Info plist:
下面是如何从Info plist获得BundleID的示例:
var appBundleID = "Unknown Bundle ID"
if let bundleDict = Bundle.main.infoDictionary,
let bundleID = bundleDict[kCFBundleIdentifierKey as String] as? String {
appBundleID = bundleID
}
The same way you may easily access any key. This approach is good for many-target projects.
同样,您也可以轻松访问任何密钥。这种方法适用于多目标项目。
#4
2
As Swift 4 introduces Codable
Swift 4引入了可编程性
Step 1: Load the Plist File from bundle.
步骤1:从bundle中加载Plist文件。
Step 2: Use PropertyListDecoder for the decoding of property list values into semantic Decodable
types.
步骤2:使用PropertyListDecoder将属性列表值解码为语义可解码类型。
Step 3: Create Codable Struct
步骤3:创建可编程结构体
Complete code -
完整的代码,
func setData() {
// location of plist file
if let settingsURL = Bundle.main.path(forResource: "JsonPlist", ofType: "plist") {
do {
var settings: MySettings?
let data = try Data(contentsOf: URL(fileURLWithPath: settingsURL))
let decoder = PropertyListDecoder()
settings = try decoder.decode(MySettings.self, from: data)
print("toolString is \(settings?.toolString ?? "")")
print("DeviceDictionary is \(settings?.deviceDictionary?.phone ?? "")")
print("RootPartArray is \(settings?.RootPartArray ?? [""])")
} catch {
print(error)
}
}
}
}
struct MySettings: Codable {
var toolString: String?
var deviceDictionary: DeviceDictionary?
var RootPartArray: [String]?
private enum CodingKeys: String, CodingKey {
case toolString = "ToolString"
case deviceDictionary = "DeviceDictionary"
case RootPartArray
}
struct DeviceDictionary: Codable {
var phone: String?
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
phone = try values.decodeIfPresent(String.self, forKey: .phone)
}
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
toolString = try values.decodeIfPresent(String.self, forKey: .toolString)
deviceDictionary = try values.decodeIfPresent(DeviceDictionary.self, forKey: .deviceDictionary)
RootPartArray = try values.decodeIfPresent([String].self, forKey: .RootPartArray)
}
}
Sample Plist file -> https://gist.github.com/janeshsutharios/4b0fb0e3edeff961d3e1f2829eb518db
样本Plist文件-> https://gist.github.com/janeshtharios/4b0fb0e3edeff961d3e1f2829eb518db
#5
0
For Swift 3.0, Following code directly targeting to key. Where as dict object will give everything which will be there in your plist file.
对于Swift 3.0,遵循直接针对key的代码。作为dict对象,它将提供plist文件中的所有内容。
if let path = Bundle.main.path(forResource: "YourPlistFile", ofType: "plist"), let dict = NSDictionary(contentsOfFile: path) as? [String: AnyObject] {
let value = dict["KeyInYourPlistFile"] as! String
}
#6
0
In AppDelegate File
在AppDelegate文件
var bundlePath:String!
var documentPath:String!
var plistDocumentPath:URL!
let fileManager = FileManager()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool
{
bundlePath = Bundle.main.path(forResource: "Team", ofType: "plist")
documentPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first
plistDocumentPath = URL.init(string: documentPath)?.appendingPathComponent("Team.plist")
print(plistDocumentPath.path)
if !fileManager.fileExists(atPath: plistDocumentPath.path){
do {
try fileManager.copyItem(atPath: bundlePath, toPath: plistDocumentPath.path)
} catch {
print("error Occured \(error.localizedDescription)")
}
}
return true
}
In ViewController
在ViewController
@IBOutlet weak var TeamTable: UITableView!
var appDelegate:AppDelegate!
var arrayForContacts:[[String:Any]]! // array object
override func viewDidLoad() {
super.viewDidLoad()
appDelegate = UIApplication.shared.delegate as! AppDelegate
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if appDelegate.fileManager.fileExists(atPath: appDelegate.plistDocumentPath.path){
arrayForContacts = []
if let contentOfPlist = NSArray.init(contentsOfFile: appDelegate.plistDocumentPath.path ){
arrayForContacts = contentOfPlist as! [[String:Any]]
TeamTable.reloadData()
}
}
}
#7
0
You can also read value directly from your plist file by simply
您还可以直接从plist文件中读取值
let value = Bundle.init(for: AppDelegate.self).infoDictionary?["your plist key name"] as? Any
#1
61
Same way you have done in Swift 2.3 or lower just syntax is changed.
与您在Swift 2.3或更低版本中所做的一样,只是语法被更改了。
if let path = Bundle.main.path(forResource: "fileName", ofType: "plist") {
//If your plist contain root as Array
if let array = NSArray(contentsOfFile: path) as? [[String: Any]] {
}
////If your plist contain root as Dictionary
if let dic = NSDictionary(contentsOfFile: path) as? [String: Any] {
}
}
Note: In Swift it is better to use Swift's generic type Array and Dictionary instead of NSArray
and NSDictionary
.
注意:在Swift中,最好使用Swift的泛型类型数组和字典,而不是NSArray和NSDictionary。
Edit: Instead of NSArray(contentsOfFile: path)
and NSDictionary(contentsOfFile:)
we can also use PropertyListSerialization.propertyList(from:)
to read data from plist
file.
编辑:我们也可以使用propertylistserializ.propertylist (from:)从plist文件中读取数据,而不是NSArray(contentsOfFile: path)和NSDictionary(contentsOfFile:)。
if let fileUrl = Bundle.main.url(forResource: "fileName", withExtension: "plist"),
let data = try? Data(contentsOf: fileUrl) {
if let result = try? PropertyListSerialization.propertyList(from: data, options: [], format: nil) as? [[String: Any]] { // [String: Any] which ever it is
print(result)
}
}
#2
2
Here is a Swift 3 implementation, based on Nirav D's answer:
以下是Swift 3的实现,基于Nirav D的回答:
/// Read Plist File.
///
/// - Parameter fileURL: file URL.
/// - Returns: return plist content.
func ReadPlist(_ fileURL: URL) -> [String: Any]? {
guard fileURL.pathExtension == FileExtension.plist, let data = try? Data(contentsOf: fileURL) else {
return nil
}
guard let result = try? PropertyListSerialization.propertyList(from: data, options: [], format: nil) as? [String: Any] else {
return nil
}
print(result)
return result
}
#3
2
Here is example how to get BundleID from Info plist:
下面是如何从Info plist获得BundleID的示例:
var appBundleID = "Unknown Bundle ID"
if let bundleDict = Bundle.main.infoDictionary,
let bundleID = bundleDict[kCFBundleIdentifierKey as String] as? String {
appBundleID = bundleID
}
The same way you may easily access any key. This approach is good for many-target projects.
同样,您也可以轻松访问任何密钥。这种方法适用于多目标项目。
#4
2
As Swift 4 introduces Codable
Swift 4引入了可编程性
Step 1: Load the Plist File from bundle.
步骤1:从bundle中加载Plist文件。
Step 2: Use PropertyListDecoder for the decoding of property list values into semantic Decodable
types.
步骤2:使用PropertyListDecoder将属性列表值解码为语义可解码类型。
Step 3: Create Codable Struct
步骤3:创建可编程结构体
Complete code -
完整的代码,
func setData() {
// location of plist file
if let settingsURL = Bundle.main.path(forResource: "JsonPlist", ofType: "plist") {
do {
var settings: MySettings?
let data = try Data(contentsOf: URL(fileURLWithPath: settingsURL))
let decoder = PropertyListDecoder()
settings = try decoder.decode(MySettings.self, from: data)
print("toolString is \(settings?.toolString ?? "")")
print("DeviceDictionary is \(settings?.deviceDictionary?.phone ?? "")")
print("RootPartArray is \(settings?.RootPartArray ?? [""])")
} catch {
print(error)
}
}
}
}
struct MySettings: Codable {
var toolString: String?
var deviceDictionary: DeviceDictionary?
var RootPartArray: [String]?
private enum CodingKeys: String, CodingKey {
case toolString = "ToolString"
case deviceDictionary = "DeviceDictionary"
case RootPartArray
}
struct DeviceDictionary: Codable {
var phone: String?
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
phone = try values.decodeIfPresent(String.self, forKey: .phone)
}
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
toolString = try values.decodeIfPresent(String.self, forKey: .toolString)
deviceDictionary = try values.decodeIfPresent(DeviceDictionary.self, forKey: .deviceDictionary)
RootPartArray = try values.decodeIfPresent([String].self, forKey: .RootPartArray)
}
}
Sample Plist file -> https://gist.github.com/janeshsutharios/4b0fb0e3edeff961d3e1f2829eb518db
样本Plist文件-> https://gist.github.com/janeshtharios/4b0fb0e3edeff961d3e1f2829eb518db
#5
0
For Swift 3.0, Following code directly targeting to key. Where as dict object will give everything which will be there in your plist file.
对于Swift 3.0,遵循直接针对key的代码。作为dict对象,它将提供plist文件中的所有内容。
if let path = Bundle.main.path(forResource: "YourPlistFile", ofType: "plist"), let dict = NSDictionary(contentsOfFile: path) as? [String: AnyObject] {
let value = dict["KeyInYourPlistFile"] as! String
}
#6
0
In AppDelegate File
在AppDelegate文件
var bundlePath:String!
var documentPath:String!
var plistDocumentPath:URL!
let fileManager = FileManager()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool
{
bundlePath = Bundle.main.path(forResource: "Team", ofType: "plist")
documentPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first
plistDocumentPath = URL.init(string: documentPath)?.appendingPathComponent("Team.plist")
print(plistDocumentPath.path)
if !fileManager.fileExists(atPath: plistDocumentPath.path){
do {
try fileManager.copyItem(atPath: bundlePath, toPath: plistDocumentPath.path)
} catch {
print("error Occured \(error.localizedDescription)")
}
}
return true
}
In ViewController
在ViewController
@IBOutlet weak var TeamTable: UITableView!
var appDelegate:AppDelegate!
var arrayForContacts:[[String:Any]]! // array object
override func viewDidLoad() {
super.viewDidLoad()
appDelegate = UIApplication.shared.delegate as! AppDelegate
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if appDelegate.fileManager.fileExists(atPath: appDelegate.plistDocumentPath.path){
arrayForContacts = []
if let contentOfPlist = NSArray.init(contentsOfFile: appDelegate.plistDocumentPath.path ){
arrayForContacts = contentOfPlist as! [[String:Any]]
TeamTable.reloadData()
}
}
}
#7
0
You can also read value directly from your plist file by simply
您还可以直接从plist文件中读取值
let value = Bundle.init(for: AppDelegate.self).infoDictionary?["your plist key name"] as? Any