Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Date Time Characteristic View Controller #2

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions BluetoothExplorer.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
objects = {

/* Begin PBXBuildFile section */
35335A2B20E16D4F006ABD4D /* DateTimeCharacteristic.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 35335A2320E16D4F006ABD4D /* DateTimeCharacteristic.storyboard */; };
35335A2D20E16D74006ABD4D /* DateTimeCharacteristicViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35335A2C20E16D74006ABD4D /* DateTimeCharacteristicViewController.swift */; };
353557C720E28CB700543440 /* InstantiableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 353557C620E28CB700543440 /* InstantiableViewController.swift */; };
353557D020E28CD200543440 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 353557CF20E28CD200543440 /* String.swift */; };
6E13E8CC20D9C7270007111B /* AdvertisementDataManagedObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E13E8CB20D9C7270007111B /* AdvertisementDataManagedObject.swift */; };
6E13E8E320D9D8290007111B /* TableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E13E8E220D9D8290007111B /* TableViewController.swift */; };
6E353A4620D7FDB200E94B73 /* CoreDataEncodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E353A4520D7FDB200E94B73 /* CoreDataEncodable.swift */; };
Expand Down Expand Up @@ -164,6 +168,10 @@
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
35335A2320E16D4F006ABD4D /* DateTimeCharacteristic.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = DateTimeCharacteristic.storyboard; sourceTree = "<group>"; };
35335A2C20E16D74006ABD4D /* DateTimeCharacteristicViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateTimeCharacteristicViewController.swift; sourceTree = "<group>"; };
353557C620E28CB700543440 /* InstantiableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstantiableViewController.swift; sourceTree = "<group>"; };
353557CF20E28CD200543440 /* String.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = String.swift; sourceTree = "<group>"; };
6E13E8CB20D9C7270007111B /* AdvertisementDataManagedObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvertisementDataManagedObject.swift; sourceTree = "<group>"; };
6E13E8E220D9D8290007111B /* TableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableViewController.swift; sourceTree = "<group>"; };
6E353A4520D7FDB200E94B73 /* CoreDataEncodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataEncodable.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -249,6 +257,7 @@
children = (
6E8C68EC20DA030900232169 /* ActivityIndicatorViewController.swift */,
6EDE00D620DB60D9002E951A /* CharacteristicViewController.swift */,
353557C620E28CB700543440 /* InstantiableViewController.swift */,
);
path = Protocols;
sourceTree = "<group>";
Expand All @@ -260,6 +269,7 @@
6E98B69E2059B51000B6F016 /* LaunchScreen.storyboard */,
6E98B6992059B51000B6F016 /* Main.storyboard */,
6EDE00CE20DB12B3002E951A /* BatteryLevelCharacteristic.storyboard */,
35335A2320E16D4F006ABD4D /* DateTimeCharacteristic.storyboard */,
6E98B69C2059B51000B6F016 /* Assets.xcassets */,
6E98B6A12059B51000B6F016 /* Info.plist */,
6E8C68EF20DA04D400232169 /* Async.swift */,
Expand Down Expand Up @@ -322,6 +332,7 @@
isa = PBXGroup;
children = (
6EDE00C820DB0EB5002E951A /* Data.swift */,
353557CF20E28CD200543440 /* String.swift */,
);
path = Extensions;
sourceTree = "<group>";
Expand All @@ -339,6 +350,7 @@
isa = PBXGroup;
children = (
6EDE00D420DB4C84002E951A /* BatteryLevelCharacteristicViewController.swift */,
35335A2C20E16D74006ABD4D /* DateTimeCharacteristicViewController.swift */,
);
path = "GATT Characteristic Editors";
sourceTree = "<group>";
Expand Down Expand Up @@ -443,7 +455,7 @@
TargetAttributes = {
6E98B6922059B51000B6F016 = {
CreatedOnToolsVersion = 9.2;
DevelopmentTeam = 4W79SG34MW;
DevelopmentTeam = RH4PC25J9C;
ProvisioningStyle = Automatic;
SystemCapabilities = {
com.apple.BackgroundModes = {
Expand Down Expand Up @@ -556,6 +568,7 @@
6E98B6A02059B51000B6F016 /* LaunchScreen.storyboard in Resources */,
6E98B69D2059B51000B6F016 /* Assets.xcassets in Resources */,
6E98B69B2059B51000B6F016 /* Main.storyboard in Resources */,
35335A2B20E16D4F006ABD4D /* DateTimeCharacteristic.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -593,6 +606,7 @@
6EFD557E20D83B8F003B75A1 /* ServiceManagedObject.swift in Sources */,
6EDE00C920DB0EB5002E951A /* Data.swift in Sources */,
6EFB3E2520D3E5A600364CA0 /* DeviceStore.swift in Sources */,
353557C720E28CB700543440 /* InstantiableViewController.swift in Sources */,
6ECCCC7320E091070054663C /* FDGapLayoutGuide.m in Sources */,
6E8C68EA20DA02DA00232169 /* UIAlertAction.swift in Sources */,
6EC0D9C720DE076A005FB128 /* Appearance.swift in Sources */,
Expand All @@ -604,6 +618,7 @@
6E8C68F020DA04D500232169 /* Async.swift in Sources */,
6E353A4620D7FDB200E94B73 /* CoreDataEncodable.swift in Sources */,
6EDE00D220DB47FD002E951A /* CustomButton.swift in Sources */,
353557D020E28CD200543440 /* String.swift in Sources */,
6EFB3E9120D3EF6C00364CA0 /* CoreDataExtensions.swift in Sources */,
6EFB3E9B20D40F2000364CA0 /* PeripheralModel.swift in Sources */,
6E8C68ED20DA030A00232169 /* ActivityIndicatorViewController.swift in Sources */,
Expand All @@ -617,6 +632,7 @@
6ECCCC7220E091070054663C /* FDStackViewLayoutArrangement.m in Sources */,
6E8C68EB20DA02DA00232169 /* AdaptiveNavigation.swift in Sources */,
6E13E8E320D9D8290007111B /* TableViewController.swift in Sources */,
35335A2D20E16D74006ABD4D /* DateTimeCharacteristicViewController.swift in Sources */,
6EDE00D720DB60D9002E951A /* CharacteristicViewController.swift in Sources */,
6EDE00C620DB0D4F002E951A /* PeripheralCharacteristicDetailViewController.swift in Sources */,
6EFB3E8D20D3ECF200364CA0 /* Model.xcdatamodeld in Sources */,
Expand Down Expand Up @@ -679,7 +695,7 @@
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = 4W79SG34MW;
DEVELOPMENT_TEAM = RH4PC25J9C;
FRAMEWORK_SEARCH_PATHS = $SRCROOT/../Carthage/Build/iOS;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = BluetoothExplorer/Info.plist;
Expand All @@ -704,7 +720,7 @@
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = 4W79SG34MW;
DEVELOPMENT_TEAM = RH4PC25J9C;
FRAMEWORK_SEARCH_PATHS = $SRCROOT/../Carthage/Build/iOS;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = BluetoothExplorer/Info.plist;
Expand Down
2 changes: 1 addition & 1 deletion BluetoothExplorer/BatteryLevelCharacteristic.storyboard
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<!--Battery Level-->
<scene sceneID="7a5-5w-4K9">
<objects>
<viewController title="Battery Level" id="9ns-IV-lIP" customClass="BatteryLevelCharacteristicViewController" customModule="BluetoothExplorer" customModuleProvider="target" sceneMemberID="viewController">
<viewController storyboardIdentifier="BatteryLevelCharacteristicViewController" title="Battery Level" id="9ns-IV-lIP" customClass="BatteryLevelCharacteristicViewController" customModule="BluetoothExplorer" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="RBe-uA-Gxd"/>
<viewControllerLayoutGuide type="bottom" id="dRZ-uC-PD8"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import CoreData
import Bluetooth
import GATT

final class BatteryLevelCharacteristicViewController: UIViewController {
final class BatteryLevelCharacteristicViewController: UIViewController, CharacteristicViewController, InstantiableViewController {

// MARK: - IB Outlets

Expand Down Expand Up @@ -67,17 +67,3 @@ final class BatteryLevelCharacteristicViewController: UIViewController {
textLabel.text = value.description
}
}

// MARK: - CharacteristicViewController

extension BatteryLevelCharacteristicViewController: CharacteristicViewController {

static func fromStoryboard() -> BatteryLevelCharacteristicViewController {

let storyboard = UIStoryboard(name: "BatteryLevelCharacteristic", bundle: .main)

let viewController = storyboard.instantiateInitialViewController() as! BatteryLevelCharacteristicViewController

return viewController
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
//
// DateTimeCharacteristicViewController.swift
// BluetoothExplorer
//
// Created by Carlos Duclos on 6/25/18.
// Copyright © 2018 PureSwift. All rights reserved.
//

import Foundation
import UIKit
import CoreData
import Bluetooth
import GATT

final class DateTimeCharacteristicViewController: UIViewController, CharacteristicViewController, InstantiableViewController {

// MARK: - IB Outlets

@IBOutlet private(set) weak var dateTimeLabel: UILabel!

@IBOutlet private(set) weak var datePicker: UIDatePicker!

// MARK: - Properties

var value = GATTDateTime(date: Date())

var valueDidChange: ((GATTDateTime) -> ())?

private lazy var minimumDate: Date = {

var dateComponents = DateComponents()
dateComponents.year = Int(GATTDateTime.Year.min.rawValue)
dateComponents.timeZone = TimeZone(identifier: "UTC")

guard let minimumDate = calendar.date(from: dateComponents)
else { fatalError("Couldn't create minimumDate") }

return minimumDate
}()

private lazy var maximumDate: Date = {

var dateComponents = DateComponents()
dateComponents.year = Int(GATTDateTime.Year.max.rawValue)
dateComponents.timeZone = TimeZone(identifier: "UTC")

guard let maximumDate = calendar.date(from: dateComponents)
else { fatalError("Couldn't create maximumDate") }

return maximumDate
}()

private lazy var calendar: Calendar = {

return Calendar(identifier: .gregorian)
}()

private lazy var timeZone: TimeZone = {

guard let timezone = TimeZone(identifier: "UTC")
else { fatalError("Couldn't create timezone") }

return timezone
}()

// MARK: - Loading

override func viewDidLoad() {
super.viewDidLoad()

datePicker.minimumDate = minimumDate
datePicker.maximumDate = maximumDate

configureView()
}

// MARK: - Actions

@IBAction func datePickerChanged(_ sender: Any) {

let dateString = CustomDateFormatter.default.string(from: datePicker.date)
dateTimeLabel.text = dateString

self.value = GATTDateTime(date: datePicker.date)
valueDidChange?(value)
}

// MARK: - Methods

func configureView() {

guard isViewLoaded else { return }

updateDatePicker()
}

func updateDatePicker() {

guard let date = value.dateComponents.date
else { return }

dateTimeLabel.text = CustomDateFormatter.default.string(from: date)
datePicker.date = date
}

}

extension DateTimeCharacteristicViewController {

struct CustomDateFormatter {

static let `default`: DateFormatter = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍🏻


let formatter = DateFormatter()
formatter.dateFormat = "MM/dd/yyyy HH:mm:ss"
return formatter
}()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,9 @@ final class PeripheralCharacteristicDetailViewController: UITableViewController
let canWrite = characteristic.properties.contains(.write)
|| characteristic.properties.contains(.writeWithoutResponse)

func load <T: CharacteristicViewController & UIViewController> (_ type: T.Type) -> T {
func load <T: CharacteristicViewController & UIViewController & InstantiableViewController> (_ type: T.Type) -> T {

let viewController = T.fromStoryboard()
let viewController: T = .instantiate()

if let data = self.value, let value = T.CharacteristicValue(data: data) {

Expand All @@ -165,6 +165,9 @@ final class PeripheralCharacteristicDetailViewController: UITableViewController
case BatteryLevelCharacteristicViewController.uuid:
viewController = load(BatteryLevelCharacteristicViewController.self)

case DateTimeCharacteristicViewController.uuid:
viewController = load(DateTimeCharacteristicViewController.self)

default:
viewController = nil
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@ protocol CharacteristicViewController: class {
/// The GATT Characteristic type this view controller can edit.
associatedtype CharacteristicValue: GATTCharacteristic

/// Initialize and load from storyboard.
static func fromStoryboard() -> Self

var view: UIView! { get }

/// The current value.
Expand All @@ -37,5 +34,6 @@ extension CharacteristicViewController {
}

let supportedCharacteristicViewControllers: [BluetoothUUID] = [
.batteryLevel
.batteryLevel,
.dateTime
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// InstantiableViewController.swift
// BluetoothExplorer
//
// Created by Carlos Duclos on 6/26/18.
// Copyright © 2018 PureSwift. All rights reserved.
//

import UIKit

protocol InstantiableViewController {

static func instantiate<T>() -> T
}

extension InstantiableViewController where Self: UIViewController {

static func instantiate<T>() -> T {
guard let storyboardName = String(describing: self).text(before: "ViewController") else {
fatalError("The controller name is not standard.")
}

let storyboard = UIStoryboard(name: storyboardName, bundle: Bundle(for: self))
let identifier = String(describing: T.self)
guard let viewController = storyboard.instantiateViewController(withIdentifier: identifier) as? T else {
fatalError("The storyboard identifier does not exist.")
}

return viewController
}

}
Loading