Overview
Comment: | iOS: Make more use of native Swift types |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
5d68f3d40a8d51848be36846102c8eb4 |
User & Date: | js on 2019-06-19 23:15:26 |
Other Links: | manifest | tags |
Context
2019-12-28
| ||
22:46 | Adjust to ObjFW changes check-in: 31d77b5098 user: js tags: trunk | |
2019-06-19
| ||
23:15 | iOS: Make more use of native Swift types check-in: 5d68f3d40a user: js tags: trunk | |
23:11 | Adjust to ObjFW changes check-in: 1b57a79561 user: js tags: trunk | |
Changes
Modified iOS/AddSiteController.swift from [209b94f8a1] to [7294aad127].
︙ | ︙ | |||
58 59 60 61 62 63 64 | preferredStyle: .alert) alert.addAction( UIAlertAction(title: "OK", style: .default, handler: nil)) controller.present(alert, animated: true, completion: nil) } @IBAction func done(_ sender: Any) { | | | | < < < < | < < < < < < < < < | | | 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | preferredStyle: .alert) alert.addAction( UIAlertAction(title: "OK", style: .default, handler: nil)) controller.present(alert, animated: true, completion: nil) } @IBAction func done(_ sender: Any) { guard let name = nameField?.text else { return } guard let lengthString = lengthField?.text else { return } guard name.count > 0 else { showAlert(controller: self, title: "Name missing", message: "Please enter a name.") return } guard let length = UInt(lengthString), length >= 3, length <= 64 else { showAlert(controller: self, title: "Invalid length", message: "Please enter a number between 3 and 64.") return } guard let siteStorage = mainViewController?.siteStorage else { return } guard !siteStorage.hasSite(name) else { showAlert(controller: self, title: "Site Already Exists", message: "Please pick a name that does not exist yet.") return } siteStorage.setSite(name, length: length, isLegacy: legacySwitch?.isOn ?? false, keyFile: self.keyFile) mainViewController?.reset() navigationController?.popViewController(animated: true) } @IBAction func cancel(_ sender: Any) { navigationController?.popViewController(animated: true) } |
︙ | ︙ |
Modified iOS/MainViewController.swift from [9c2bb5d1c2] to [2595a319b1].
︙ | ︙ | |||
21 22 23 24 25 26 27 | */ import UIKit import ObjFW class MainViewController: UIViewController, UISearchBarDelegate, UITableViewDelegate, UITableViewDataSource { | | | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | */ import UIKit import ObjFW class MainViewController: UIViewController, UISearchBarDelegate, UITableViewDelegate, UITableViewDataSource { public var sites: [String] = [] public var siteStorage = SiteStorage() @IBOutlet var searchBar: UISearchBar? @IBOutlet var tableView: UITableView? override func viewDidLoad() { super.viewDidLoad() |
︙ | ︙ | |||
47 48 49 50 51 52 53 | return sites.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "site") ?? UITableViewCell(style: .default, reuseIdentifier: "site") | | | | 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | return sites.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "site") ?? UITableViewCell(style: .default, reuseIdentifier: "site") cell.textLabel?.text = sites[indexPath.row] return cell } func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { sites = siteStorage.sites(withFilter: searchBar.text) tableView?.reloadData() } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { self.performSegue(withIdentifier: "showDetails", sender: self) } |
︙ | ︙ |
Modified iOS/ShowDetailsController.swift from [028af44e3c] to [3b6682d3d0].
︙ | ︙ | |||
28 29 30 31 32 33 34 | @IBOutlet var nameField: UITextField? @IBOutlet var lengthField: UITextField? @IBOutlet var legacySwitch: UISwitch? @IBOutlet var keyFileField: UITextField? @IBOutlet var passphraseField: UITextField? public var mainViewController: MainViewController? | | | | | | | 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | @IBOutlet var nameField: UITextField? @IBOutlet var lengthField: UITextField? @IBOutlet var legacySwitch: UISwitch? @IBOutlet var keyFileField: UITextField? @IBOutlet var passphraseField: UITextField? public var mainViewController: MainViewController? private var name: String = "" private var length: UInt = 0 private var isLegacy: Bool = false private var keyFile: String? = nil override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) guard let mainViewController = self.mainViewController else { return } guard let tableView = mainViewController.tableView else { return } let siteStorage = mainViewController.siteStorage guard let indexPath = tableView.indexPathForSelectedRow else { return } name = mainViewController.sites[indexPath.row] length = siteStorage.length(forSite: name) isLegacy = siteStorage.isLegacy(site: name) keyFile = siteStorage.keyFile(forSite: name) nameField?.text = name lengthField?.text = "\(length)" legacySwitch?.isOn = isLegacy keyFileField?.text = keyFile tableView.deselectRow(at: indexPath, animated: true) } func textFieldShouldReturn(_ textField: UITextField) -> Bool { textField.resignFirstResponder() return false |
︙ | ︙ | |||
130 131 132 133 134 135 136 | } } } private func generateWithCallback(_ block: (_: NSMutableString) -> ()) { let generator: PasswordGenerator = isLegacy ? LegacyPasswordGenerator() : NewPasswordGenerator() | | | > | | 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | } } } private func generateWithCallback(_ block: (_: NSMutableString) -> ()) { let generator: PasswordGenerator = isLegacy ? LegacyPasswordGenerator() : NewPasswordGenerator() generator.site = name.ofObject generator.length = size_t(length) if let keyFile = keyFile { guard let documentDirectory = NSSearchPathForDirectoriesInDomains( .documentDirectory, .userDomainMask, true).first else { print("Could not get key files: No documents directory") return } let keyFilePath = documentDirectory.ofObject.appending(keyFile.ofObject) generator.keyFile = OFMutableData(contentsOfFile: keyFilePath) } let passphraseText = (passphraseField?.text ?? "") as NSString let passphrase = of_strdup(passphraseText.utf8String!)! generator.passphrase = UnsafePointer<CChar>(passphrase) |
︙ | ︙ |
Modified iOS/SiteStorage.swift from [0a36bee6de] to [0072dc8d4f].
︙ | ︙ | |||
20 21 22 23 24 25 26 | * POSSIBILITY OF SUCH DAMAGE. */ import ObjFW import ObjFWBridge class SiteStorage: OFObject { | < < < | | | | | | > | > > > | | | < > | | < < < < < | < | | | | < < < < < > > | | | < | < | | | | | < < | | < | < < < | | < > | | > > | | | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | * POSSIBILITY OF SUCH DAMAGE. */ import ObjFW import ObjFWBridge class SiteStorage: OFObject { private static let lengthField = NSNumber(value: 0) private static let legacyField = NSNumber(value: 1) private static let keyFileField = NSNumber(value: 2) private var path: OFString private var storage: [String: [NSNumber: AnyObject]] private var sites: [String] override init() { let fileManager = OFFileManager.default let userDataPath = OFSystemInfo.userDataPath! if !fileManager.directoryExists(atPath: userDataPath) { fileManager.createDirectory(atPath: userDataPath) } let path = userDataPath.appendingPathComponent( OFString(utf8String: "sites.msgpack")) var storage: [String: [NSNumber: AnyObject]]? = nil OFException.try({ let decoded = (OFData(contentsOfFile: path).messagePackValue) as? OFDictionary<OFString, OFDictionary<OFNumber, AnyObject>> storage = (decoded?.nsObject as? [String: [NSNumber: AnyObject]]) ?? [:] }, catch: { (OFException) in storage = [:] }) self.path = path self.storage = storage! self.sites = self.storage.keys.sorted() } func sites(withFilter filter: String?) -> [String] { return storage.keys.sorted().filter({ (name) in if let filter = filter { return name.localizedCaseInsensitiveContains(filter) } return true }) } func hasSite(_ name: String) -> Bool { return (storage[name] != nil) } func length(forSite name: String) -> UInt { guard let site = storage[name] else { OFInvalidArgumentException().throw() } return (site[SiteStorage.lengthField] as! NSNumber).uintValue } func isLegacy(site name: String) -> Bool { guard let site = storage[name] else { return false } return (site[SiteStorage.legacyField] as! NSNumber).boolValue } func keyFile(forSite name: String) -> String? { guard let site = storage[name] else { return nil } guard let keyFile = site[SiteStorage.keyFileField], !(keyFile is NSNull) else { return nil } return keyFile as? String } func setSite(_ name: String, length: UInt, isLegacy: Bool, keyFile: String?) { var siteDictionary: [NSNumber: AnyObject] = [ SiteStorage.lengthField: NSNumber(value: length), SiteStorage.legacyField: NSNumber(value: isLegacy), ] siteDictionary[SiteStorage.keyFileField] = keyFile as AnyObject? storage[name] = siteDictionary self.update() } func removeSite(_ name: String) { storage[name] = nil self.update() } private func update() { let ofStorage = (storage as NSDictionary).ofObject ofStorage.messagePackRepresentation.write(toFile: path) sites = storage.keys.sorted() } } |