-免責事項-
iOSとSwiftの開発は非常に新しいですが、プログラミングは特に新しいものではありません。
Swift3
要素を含む基本的なiOS
アプリケーションがあります。
アプリケーションで読み取り、表示したいエントリを含むplist
ファイルを作成しました。 (書き込みアクセスは不要です)
Swift3でバンドルされているplist
ファイルの特定のキーの値をどのように読み取ることができますか?
これは私には本当に単純な質問のように思えますが、たくさんの検索をすることで、概念的なアプローチ全体に疑問を抱かせています。
役に立つヒントをいただければ幸いです。
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] {
}
}
注:Swiftでは、NSArray
およびNSDictionary
の代わりにSwiftのジェネリック型の配列と辞書を使用することをお勧めします。
編集:NSArray(contentsOfFile: path)
およびNSDictionary(contentsOfFile:)
の代わりに PropertyListSerialization.propertyList(from:)
を使用して、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)
}
}
Swift 4はCodableを導入するため
ステップ1:バンドルからPlistファイルをロードします
ステップ2:PropertyListDecoderを使用して、プロパティリスト値をセマンティックDecodable
タイプにデコードします。
ステップ3:コード化可能な構造体を作成する
完全なコード-
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)
}
}
サンプルPlistファイル-> https://Gist.github.com/janeshsutharios/4b0fb0e3edeff961d3e1f2829eb518db
以下は、Info plistからBundleIDを取得する方法の例です。
var appBundleID = "Unknown Bundle ID"
if let bundleDict = Bundle.main.infoDictionary,
let bundleID = bundleDict[kCFBundleIdentifierKey as String] as? String {
appBundleID = bundleID
}
同じ方法で、任意のキーに簡単にアクセスできます。このアプローチは、多くのターゲットプロジェクトに適しています。
Nirav D's answer に基づいたSwift 3の実装です。
/// 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
}
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
}
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()
}
}
}
また、単にplistファイルから値を直接読み取ることもできます。
let value = Bundle.init(for: AppDelegate.self).infoDictionary?["your plist key name"] as? Any
Swift 3.0の場合、キーを直接ターゲットとするコードに従う。 dict objectは、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
}