From 4c55f9bcb4fc2af7bac73fd4bc47ff89d8e3c440 Mon Sep 17 00:00:00 2001 From: Logan Cautrell Date: Wed, 23 Aug 2017 12:57:43 -0500 Subject: [PATCH] Update Near for beta 5. (#1) Add table views, make UI nicer. --- .gitignore | 1 + Near.xcodeproj/project.pbxproj | 34 ++-- .../UserInterfaceState.xcuserstate | Bin 25975 -> 36935 bytes Near/Base.lproj/LaunchScreen.storyboard | 24 ++- Near/Base.lproj/Main.storyboard | 147 ++++++++++++++---- Near/DetailsViewController.swift | 91 +++++++++++ ...troller.swift => MainViewController.swift} | 146 +++++++++-------- Near/NearFieldCommunicator.swift | 5 +- Near/TableViewCell.swift | 20 +++ 9 files changed, 351 insertions(+), 117 deletions(-) create mode 100644 .gitignore create mode 100644 Near/DetailsViewController.swift rename Near/{ViewController.swift => MainViewController.swift} (60%) create mode 100644 Near/TableViewCell.swift diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e43b0f9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store diff --git a/Near.xcodeproj/project.pbxproj b/Near.xcodeproj/project.pbxproj index 2f3193e..1c04747 100755 --- a/Near.xcodeproj/project.pbxproj +++ b/Near.xcodeproj/project.pbxproj @@ -7,9 +7,11 @@ objects = { /* Begin PBXBuildFile section */ + B2378A7D1F4DDF2F003050FD /* TableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2378A7C1F4DDF2F003050FD /* TableViewCell.swift */; }; + B2378A7F1F4DE0F6003050FD /* DetailsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2378A7E1F4DE0F6003050FD /* DetailsViewController.swift */; }; B27DAC8C1EE6FD1D009A9653 /* CoreNFC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B28DF23F1EE6FB42005EA143 /* CoreNFC.framework */; }; B28DF22B1EE6F845005EA143 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B28DF22A1EE6F845005EA143 /* AppDelegate.swift */; }; - B28DF22D1EE6F845005EA143 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B28DF22C1EE6F845005EA143 /* ViewController.swift */; }; + B28DF22D1EE6F845005EA143 /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B28DF22C1EE6F845005EA143 /* MainViewController.swift */; }; B28DF2301EE6F845005EA143 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B28DF22E1EE6F845005EA143 /* Main.storyboard */; }; B28DF2321EE6F845005EA143 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B28DF2311EE6F845005EA143 /* Assets.xcassets */; }; B28DF2351EE6F845005EA143 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B28DF2331EE6F845005EA143 /* LaunchScreen.storyboard */; }; @@ -17,11 +19,13 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - B24196011EF2E3480051437F /* NFCReader.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; name = NFCReader.entitlements; path = "../../../../Downloads/NFC-Reader-for-iPhone-CoreNFC--master/NFCReader.entitlements"; sourceTree = ""; }; + B2378A7A1F4CA1D4003050FD /* NFCReader.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NFCReader.entitlements; sourceTree = ""; }; + B2378A7C1F4DDF2F003050FD /* TableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableViewCell.swift; sourceTree = ""; }; + B2378A7E1F4DE0F6003050FD /* DetailsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailsViewController.swift; sourceTree = ""; }; B27DAC8B1EE6FCBB009A9653 /* FileProvider.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FileProvider.framework; path = System/Library/Frameworks/FileProvider.framework; sourceTree = SDKROOT; }; B28DF2271EE6F845005EA143 /* Near.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Near.app; sourceTree = BUILT_PRODUCTS_DIR; }; B28DF22A1EE6F845005EA143 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - B28DF22C1EE6F845005EA143 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + B28DF22C1EE6F845005EA143 /* MainViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewController.swift; sourceTree = ""; }; B28DF22F1EE6F845005EA143 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; B28DF2311EE6F845005EA143 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; B28DF2341EE6F845005EA143 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; @@ -62,14 +66,16 @@ B28DF2291EE6F845005EA143 /* Near */ = { isa = PBXGroup; children = ( - B24196011EF2E3480051437F /* NFCReader.entitlements */, B28DF22A1EE6F845005EA143 /* AppDelegate.swift */, - B28DF22C1EE6F845005EA143 /* ViewController.swift */, + B2378A7A1F4CA1D4003050FD /* NFCReader.entitlements */, + B28DF22C1EE6F845005EA143 /* MainViewController.swift */, + B2378A7E1F4DE0F6003050FD /* DetailsViewController.swift */, B28DF22E1EE6F845005EA143 /* Main.storyboard */, B28DF2311EE6F845005EA143 /* Assets.xcassets */, B28DF2331EE6F845005EA143 /* LaunchScreen.storyboard */, B28DF2361EE6F845005EA143 /* Info.plist */, B28DF23C1EE6F875005EA143 /* NearFieldCommunicator.swift */, + B2378A7C1F4DDF2F003050FD /* TableViewCell.swift */, ); path = Near; sourceTree = ""; @@ -115,7 +121,7 @@ TargetAttributes = { B28DF2261EE6F845005EA143 = { CreatedOnToolsVersion = 9.0; - ProvisioningStyle = Manual; + ProvisioningStyle = Automatic; }; }; }; @@ -155,9 +161,11 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - B28DF22D1EE6F845005EA143 /* ViewController.swift in Sources */, + B28DF22D1EE6F845005EA143 /* MainViewController.swift in Sources */, + B2378A7D1F4DDF2F003050FD /* TableViewCell.swift in Sources */, B28DF22B1EE6F845005EA143 /* AppDelegate.swift in Sources */, B28DF23D1EE6F875005EA143 /* NearFieldCommunicator.swift in Sources */, + B2378A7F1F4DE0F6003050FD /* DetailsViewController.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -292,15 +300,15 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = Near/NFCReader.entitlements; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = R5JUTH26F4; INFOPLIST_FILE = Near/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.punchthrough.Near; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = "93658457-b763-4f75-a739-ae8fa5648b75"; - PROVISIONING_PROFILE_SPECIFIER = near; + PROVISIONING_PROFILE = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; SDKROOT = iphoneos11.0; SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -312,15 +320,15 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = R5JUTH26F4; INFOPLIST_FILE = Near/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.punchthrough.Near; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = "93658457-b763-4f75-a739-ae8fa5648b75"; - PROVISIONING_PROFILE_SPECIFIER = near; + PROVISIONING_PROFILE = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; SDKROOT = iphoneos11.0; SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/Near.xcodeproj/project.xcworkspace/xcuserdata/logancautrell.xcuserdatad/UserInterfaceState.xcuserstate b/Near.xcodeproj/project.xcworkspace/xcuserdata/logancautrell.xcuserdatad/UserInterfaceState.xcuserstate index 70c69d4d58d3bd7c06b342b4b51e561ca39c48eb..8adf0fc9f797db8f618a54dec90775958fe2c426 100755 GIT binary patch literal 36935 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 XiyD>;I`xF;CH&*gNWZ;58+!jQNYXEF diff --git a/Near/Base.lproj/LaunchScreen.storyboard b/Near/Base.lproj/LaunchScreen.storyboard index fdf3f97..8dc6947 100755 --- a/Near/Base.lproj/LaunchScreen.storyboard +++ b/Near/Base.lproj/LaunchScreen.storyboard @@ -1,7 +1,11 @@ - - + + + + + - + + @@ -16,7 +20,21 @@ + + + + + + + + + diff --git a/Near/Base.lproj/Main.storyboard b/Near/Base.lproj/Main.storyboard index 88fc1bc..af52dfb 100755 --- a/Near/Base.lproj/Main.storyboard +++ b/Near/Base.lproj/Main.storyboard @@ -1,17 +1,18 @@ - + - + + - + - + @@ -20,40 +21,128 @@ - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda. - - - - - + - + + + + + + + + - - + - + + + + + + + + + + + + + + + + + + + - + diff --git a/Near/DetailsViewController.swift b/Near/DetailsViewController.swift new file mode 100644 index 0000000..f56e101 --- /dev/null +++ b/Near/DetailsViewController.swift @@ -0,0 +1,91 @@ +// +// DetailsViewController.swift +// Near +// +// Created by LOGAN CAUTRELL on 8/23/17. +// Copyright © 2017 Punch Through Design LLC. All rights reserved. +// + +import UIKit +import CoreNFC + +let reuseId = "reuseId" + +class DetailsViewController: UIViewController { + + @IBOutlet weak var tableView: UITableView! + + var messages = [NFCNDEFMessage]() + + override func viewDidLoad() { + super.viewDidLoad() + tableView.register(UITableViewCell.self, forCellReuseIdentifier: reuseId) + tableView.rowHeight = 25.0 + tableView.reloadData() + } +} + +extension DetailsViewController : UITableViewDataSource { + + func messageAndRecord(atSection section: Int) -> (NFCNDEFMessage, NFCNDEFPayload)? { + var counter = 0 + for message in messages { + for record in message.records { + if counter == section { + return (message, record) + } + counter = counter + 1 + } + } + return nil + } + + func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + let messageRecord = messageAndRecord(atSection: section) + guard let message = messageRecord?.0, let record = messageRecord?.1 else { + return nil + } + return "Message \(messages.index(of: message) ?? 0) : Record \(message.records.index(of: record) ?? 0)" + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return 7 + } + + func numberOfSections(in tableView: UITableView) -> Int { + return messages.reduce(0) { (count, message) -> Int in + return count + message.records.count + } + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: reuseId, for: indexPath) + cell.textLabel?.font = UIFont(name: "Menlo-Regular", size: 11.0) + guard let record = messageAndRecord(atSection: indexPath.section)?.1 else { + return cell + } + + let index = indexPath.row % 7 + switch index { + case 0: + cell.textLabel?.text = "typeNameFormat : \(string(fromTypeNameFormat: record.typeNameFormat))" + case 1: + cell.textLabel?.text = "type : \(record.type)" + case 2: + cell.textLabel?.text = "typeString : \(string(fromData: record.type))" + case 3: + cell.textLabel?.text = "identifier : \(record.identifier)" + case 4: + cell.textLabel?.text = "identifierString : \(string(fromData: record.identifier))" + case 5: + cell.textLabel?.text = "payload : \(record.payload)" + case 6: + cell.textLabel?.text = "payloadString : \(string(fromData: record.payload))" + default: + cell.textLabel?.text = "invalid" + } + return cell + } +} + + diff --git a/Near/ViewController.swift b/Near/MainViewController.swift similarity index 60% rename from Near/ViewController.swift rename to Near/MainViewController.swift index d9e54a6..2eba20d 100755 --- a/Near/ViewController.swift +++ b/Near/MainViewController.swift @@ -9,70 +9,27 @@ import UIKit import CoreNFC -class ViewController: UIViewController { - - @IBOutlet weak var titleLabel: UILabel! - @IBOutlet weak var textView: UITextView! +class MainViewController: UIViewController { + fileprivate let reuseId = "reuseId" + @IBOutlet weak var tableView: UITableView! + var nfc: NearFieldCommunicator! - var count = 0 - - override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { - fatalError("init(coder:) has not been implemented") - } - - required init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - } + var messagesList = [[NFCNDEFMessage]]() override func viewDidLoad() { super.viewDidLoad() - self.textView.text = "" nfc = NearFieldCommunicator(delegate: self) - } - - override func didReceiveMemoryWarning() { - super.didReceiveMemoryWarning() - // Dispose of any resources that can be recreated. - } - - @IBAction func goTapped(_ sender: Any) { - self.nfc.createSession() + tableView.register(MainTableViewCell.self, forCellReuseIdentifier: reuseId) } - func handleTags(tags: [NFCNDEFMessage]) { - for tag in tags { - self.textView.text.append("\(tag)\n") - for record in tag.records { - self.textView.text.append(" Record:\n") - self.textView.text.append(" typeNameFormat : \(string(fromTypeNameFormat: record.typeNameFormat))\n") - self.textView.text.append(" type : \(record.type)\n") - self.textView.text.append(" typeString : \(string(fromData: record.type))\n") - self.textView.text.append(" identifier : \(record.identifier)\n") - self.textView.text.append(" identifierString : \(string(fromData: record.identifier))\n") - self.textView.text.append(" payload : \(record.payload)\n") - self.textView.text.append(" payloadString : \(string(fromData: record.payload))\n") - } - } + @IBAction func scanTapped(_ sender: Any) { + self.nfc.createSession() } -} -func string(fromTypeNameFormat: NFCTypeNameFormat) -> String { - switch fromTypeNameFormat { - case .empty: - return "empty" - case .nfcWellKnown: - return "nfcWellKnown" - case .media: - return "media" - case .absoluteURI: - return "absoluteURI" - case .nfcExternal: - return "nfcExternal" - case . unknown: - return "unknown" - case .unchanged: - return "unchanged" + func handleTags(tags: [NFCNDEFMessage]) { + messagesList.append(tags) + tableView.reloadData() } } @@ -80,10 +37,9 @@ func string(fromData: Data) -> String { return String(data: fromData, encoding: .utf8) ?? "can't decode" } -extension ViewController: NFCProtocol { +extension MainViewController: NFCProtocol { func ready() -> Void { - self.titleLabel.text = "READY!" } /*! @@ -97,13 +53,6 @@ extension ViewController: NFCProtocol { */ public func readerSession(_ session: NFCNDEFReaderSession, didInvalidateWithError error: Error) { print("\(error)") - - self.count = self.count + 1 - - DispatchQueue.main.async { - self.titleLabel.text = "Error \(self.count)" - self.textView.text.append("errror \(error.localizedDescription)\n") - } } /*! @@ -121,8 +70,7 @@ extension ViewController: NFCProtocol { self.handleTags(tags: messages) } } - - + /*! * @method readerSessionDidBecomeActive: * @@ -134,9 +82,8 @@ extension ViewController: NFCProtocol { public func readerSessionDidBecomeActive(_ session: NFCReaderSession) { print("readerSessionDidBecomeActive") - } - + /*! * @method readerSession:didDetectTags: * @@ -148,7 +95,70 @@ extension ViewController: NFCProtocol { public func readerSession(_ session: NFCReaderSession, didDetect tags: [NFCTag]) { print("didDetect tags: \(tags)") - + } +} + +extension MainViewController : UITableViewDataSource { + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return messagesList.count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: reuseId, for: indexPath) + let tags = messagesList[indexPath.row] + cell.textLabel?.text = formatTagsCount(tags: tags) + cell.detailTextLabel?.text = formatTagsDetails(tags: tags) + return cell } + func formatTagsCount(tags: [NFCNDEFMessage]) -> String { + return tags.count == 1 ? "1 Message" : "\(tags.count) Messages" + } + + func formatTagsDetails(tags: [NFCNDEFMessage]) -> String { + return tags.reduce("") { (result, message) -> String in + let messages = message.records.reduce("", { (records, record) -> String in + return "\(records), \(string(fromTypeNameFormat: record.typeNameFormat))" + }).dropFirst(2).toString() + return "\(result), (\(messages))" + }.dropFirst(2).toString() + } +} + +extension MainViewController : UITableViewDelegate { + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + guard let details = storyboard?.instantiateViewController(withIdentifier:"DetailsViewController") as? DetailsViewController else { + print("can't make details view controller") + return + } + details.messages = messagesList[indexPath.row] + navigationController?.pushViewController(details, animated: true) + tableView.deselectRow(at: indexPath, animated: true) + } +} + + +extension Substring { + func toString() -> String { + return String(self) + } +} + +func string(fromTypeNameFormat: NFCTypeNameFormat) -> String { + switch fromTypeNameFormat { + case .empty: + return "empty" + case .nfcWellKnown: + return "nfcWellKnown" + case .media: + return "media" + case .absoluteURI: + return "absoluteURI" + case .nfcExternal: + return "nfcExternal" + case . unknown: + return "unknown" + case .unchanged: + return "unchanged" + } } diff --git a/Near/NearFieldCommunicator.swift b/Near/NearFieldCommunicator.swift index f05c065..caa9ff1 100755 --- a/Near/NearFieldCommunicator.swift +++ b/Near/NearFieldCommunicator.swift @@ -28,10 +28,7 @@ class NearFieldCommunicator: NSObject { if let aSession = session { aSession.invalidate() } - session = NFCNDEFReaderSession(delegate: delegate, queue: nil, invalidateAfterFirstRead: false) - session.invalidate() - session = NFCNDEFReaderSession(delegate: delegate, queue: nil, invalidateAfterFirstRead: false) - print("is ready \(session.isReady)") + session = NFCNDEFReaderSession(delegate: delegate, queue: nil, invalidateAfterFirstRead: true) self.session.begin() } diff --git a/Near/TableViewCell.swift b/Near/TableViewCell.swift new file mode 100644 index 0000000..5bd3421 --- /dev/null +++ b/Near/TableViewCell.swift @@ -0,0 +1,20 @@ +// +// TableViewCell.swift +// Near +// +// Created by LOGAN CAUTRELL on 8/23/17. +// Copyright © 2017 Punch Through Design LLC. All rights reserved. +// + +import UIKit + +class MainTableViewCell: UITableViewCell { + + override init(style: UITableViewCellStyle, reuseIdentifier: String?) { + super.init(style: .subtitle, reuseIdentifier: reuseIdentifier) + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +}