-Avertissement-
Je suis extrêmement novice en développement iOS et Swift, mais je ne suis pas particulièrement novice en programmation.
J'ai une application iOS
de base avec des éléments Swift3
.
J'ai créé un fichier plist
avec certaines entrées que je veux lire et afficher dans mon application. (Aucun accès en écriture n'est nécessaire)
Comment pouvez-vous lire une valeur pour une clé donnée pour un fichier plist
intégré, dans Swift3?
Cela me semble une question très simple, mais une série de recherches me fait remettre en question toute mon approche conceptuelle.
Des conseils utiles seraient appréciés.
De la même manière que vous l'avez fait dans Swift 2.3 ou une version antérieure inférieure, la syntaxe est modifiée.
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] {
}
}
Remarque: Dans Swift, il est préférable d'utiliser le type générique Array and Dictionary de Swift au lieu de NSArray
et NSDictionary
.
Edit: Au lieu de NSArray(contentsOfFile: path)
et NSDictionary(contentsOfFile:)
, nous pouvons également utiliser PropertyListSerialization.propertyList(from:)
pour lire les données du fichier plist
.
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)
}
}
Comme Swift 4 introduit Codable
Étape 1: chargez le fichier Plist à partir du paquet.
Étape 2: Utilisez PropertyListDecoder pour le décodage des valeurs de liste de propriétés en types sémantiques Decodable
.
Étape 3: Créer une structure codable
Code complet -
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)
}
}
Exemple de fichier Plist -> https://Gist.github.com/janeshsutharios/4b0fb0e3edeff961d3e1f2829eb518db
Voici un exemple pour obtenir BundleID à partir de la pliste Info:
var appBundleID = "Unknown Bundle ID"
if let bundleDict = Bundle.main.infoDictionary,
let bundleID = bundleDict[kCFBundleIdentifierKey as String] as? String {
appBundleID = bundleID
}
De la même manière, vous pouvez facilement accéder à n'importe quelle clé. Cette approche convient aux projets à objectifs multiples.
Voici une implémentation de Swift 3, basée sur la réponse de 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
}
Dans le fichier 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
}
Dans 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()
}
}
}
Vous pouvez également lire la valeur directement à partir de votre fichier plist simplement
let value = Bundle.init(for: AppDelegate.self).infoDictionary?["your plist key name"] as? Any
Pour Swift 3.0, le code suivant est directement ciblé sur la clé. Où comme dict object donnera tout ce qui sera là dans votre fichier 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
}