AccountsViewController.swift 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. //
  2. // AccountsViewController.swift
  3. // Example
  4. //
  5. // Created by kishikawa katsumi on 2014/12/25.
  6. // Copyright (c) 2014 kishikawa katsumi. All rights reserved.
  7. //
  8. // Permission is hereby granted, free of charge, to any person obtaining a copy
  9. // of this software and associated documentation files (the "Software"), to deal
  10. // in the Software without restriction, including without limitation the rights
  11. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. // copies of the Software, and to permit persons to whom the Software is
  13. // furnished to do so, subject to the following conditions:
  14. //
  15. // The above copyright notice and this permission notice shall be included in
  16. // all copies or substantial portions of the Software.
  17. //
  18. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. // THE SOFTWARE.
  25. import UIKit
  26. import KeychainAccess
  27. class AccountsViewController: UITableViewController {
  28. var itemsGroupedByService: [String: [[String: Any]]]?
  29. override func viewDidLoad() {
  30. super.viewDidLoad()
  31. }
  32. override func viewWillAppear(_ animated: Bool) {
  33. super.viewWillAppear(animated)
  34. reloadData()
  35. tableView.reloadData()
  36. }
  37. override func didReceiveMemoryWarning() {
  38. super.didReceiveMemoryWarning()
  39. }
  40. // MARK:
  41. override func numberOfSections(in tableView: UITableView) -> Int {
  42. if itemsGroupedByService != nil {
  43. let services = Array(itemsGroupedByService!.keys)
  44. return services.count
  45. }
  46. return 0
  47. }
  48. override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  49. let services = Array(itemsGroupedByService!.keys)
  50. let service = services[section]
  51. let items = Keychain(service: service).allItems()
  52. return items.count
  53. }
  54. override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
  55. let services = Array(itemsGroupedByService!.keys)
  56. return services[section]
  57. }
  58. override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  59. let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
  60. let services = Array(itemsGroupedByService!.keys)
  61. let service = services[indexPath.section]
  62. let items = Keychain(service: service).allItems()
  63. let item = items[indexPath.row]
  64. cell.textLabel?.text = item["key"] as? String
  65. cell.detailTextLabel?.text = item["value"] as? String
  66. return cell
  67. }
  68. override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
  69. let services = Array(itemsGroupedByService!.keys)
  70. let service = services[indexPath.section]
  71. let keychain = Keychain(service: service)
  72. let items = keychain.allItems()
  73. let item = items[indexPath.row]
  74. let key = item["key"] as! String
  75. keychain[key] = nil
  76. if items.count == 1 {
  77. reloadData()
  78. tableView.deleteSections(IndexSet(integer: indexPath.section), with: .automatic)
  79. } else {
  80. tableView.deleteRows(at: [indexPath], with: .automatic)
  81. }
  82. }
  83. // MARK:
  84. func reloadData() {
  85. let items = Keychain.allItems(.genericPassword)
  86. itemsGroupedByService = groupBy(items) { item -> String in
  87. if let service = item["service"] as? String {
  88. return service
  89. }
  90. return ""
  91. }
  92. }
  93. }
  94. private func groupBy<C: Collection, K: Hashable>(_ xs: C, key: (C.Iterator.Element) -> K) -> [K:[C.Iterator.Element]] {
  95. var gs: [K:[C.Iterator.Element]] = [:]
  96. for x in xs {
  97. let k = key(x)
  98. var ys = gs[k] ?? []
  99. ys.append(x)
  100. gs.updateValue(ys, forKey: k)
  101. }
  102. return gs
  103. }