diff --git a/GetDibs-Bridging-Header.h b/GetDibs-Bridging-Header.h new file mode 100644 index 0000000..271cc5a --- /dev/null +++ b/GetDibs-Bridging-Header.h @@ -0,0 +1,6 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + +#import +#import \ No newline at end of file diff --git a/GetDibs.xcodeproj/project.pbxproj b/GetDibs.xcodeproj/project.pbxproj index 4173a2f..2aac7a1 100644 --- a/GetDibs.xcodeproj/project.pbxproj +++ b/GetDibs.xcodeproj/project.pbxproj @@ -7,6 +7,10 @@ objects = { /* Begin PBXBuildFile section */ + 196018671B2CA7AE00B420B7 /* BLEPeripheral.swift in Sources */ = {isa = PBXBuildFile; fileRef = 196018661B2CA7AE00B420B7 /* BLEPeripheral.swift */; }; + 196018691B2CABD200B420B7 /* AuthorizedEquipment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 196018681B2CABD200B420B7 /* AuthorizedEquipment.swift */; }; + 196018EA1B2CB99900B420B7 /* ParseUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 196018E91B2CB99900B420B7 /* ParseUI.framework */; }; + 196018EC1B2DE0F300B420B7 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 196018EB1B2DE0F300B420B7 /* Extensions.swift */; }; 1997BC5F1B2C7ABA00140A9B /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1997BC5E1B2C7ABA00140A9B /* AppDelegate.swift */; }; 1997BC611B2C7ABA00140A9B /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1997BC601B2C7ABA00140A9B /* ViewController.swift */; }; 1997BC641B2C7ABA00140A9B /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1997BC621B2C7ABA00140A9B /* Main.storyboard */; }; @@ -15,6 +19,7 @@ 1997BC751B2C7ABA00140A9B /* GetDibsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1997BC741B2C7ABA00140A9B /* GetDibsTests.swift */; }; 1997BC7F1B2C7AEF00140A9B /* BLEDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1997BC7E1B2C7AEF00140A9B /* BLEDevice.swift */; }; 1997BC811B2C889700140A9B /* EquipmentCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1997BC801B2C889700140A9B /* EquipmentCell.swift */; }; + B8A0BE882514FD1DF26E6DF9 /* Pods_GetDibs.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C79DA1FDF406CFA3592AC29D /* Pods_GetDibs.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -28,6 +33,11 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 196018661B2CA7AE00B420B7 /* BLEPeripheral.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BLEPeripheral.swift; sourceTree = ""; }; + 196018681B2CABD200B420B7 /* AuthorizedEquipment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthorizedEquipment.swift; sourceTree = ""; }; + 1960186C1B2CB69500B420B7 /* GetDibs-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "GetDibs-Bridging-Header.h"; sourceTree = ""; }; + 196018E91B2CB99900B420B7 /* ParseUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = ParseUI.framework; sourceTree = ""; }; + 196018EB1B2DE0F300B420B7 /* Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = ""; }; 1997BC591B2C7ABA00140A9B /* GetDibs.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = GetDibs.app; sourceTree = BUILT_PRODUCTS_DIR; }; 1997BC5D1B2C7ABA00140A9B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 1997BC5E1B2C7ABA00140A9B /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -40,6 +50,9 @@ 1997BC741B2C7ABA00140A9B /* GetDibsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetDibsTests.swift; sourceTree = ""; }; 1997BC7E1B2C7AEF00140A9B /* BLEDevice.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BLEDevice.swift; sourceTree = ""; }; 1997BC801B2C889700140A9B /* EquipmentCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EquipmentCell.swift; sourceTree = ""; }; + 442861A008DF10675CAED3BC /* Pods-GetDibs.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-GetDibs.release.xcconfig"; path = "Pods/Target Support Files/Pods-GetDibs/Pods-GetDibs.release.xcconfig"; sourceTree = ""; }; + 952FB4BA2490BE47A6E6528E /* Pods-GetDibs.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-GetDibs.debug.xcconfig"; path = "Pods/Target Support Files/Pods-GetDibs/Pods-GetDibs.debug.xcconfig"; sourceTree = ""; }; + C79DA1FDF406CFA3592AC29D /* Pods_GetDibs.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_GetDibs.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -47,6 +60,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 196018EA1B2CB99900B420B7 /* ParseUI.framework in Frameworks */, + B8A0BE882514FD1DF26E6DF9 /* Pods_GetDibs.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -66,6 +81,9 @@ 1997BC5B1B2C7ABA00140A9B /* GetDibs */, 1997BC711B2C7ABA00140A9B /* GetDibsTests */, 1997BC5A1B2C7ABA00140A9B /* Products */, + 4AB918BDF8FD9F6FFFC5C407 /* Pods */, + 51CFFA30ADE92384E6ED67CE /* Frameworks */, + 1960186C1B2CB69500B420B7 /* GetDibs-Bridging-Header.h */, ); sourceTree = ""; }; @@ -82,10 +100,13 @@ isa = PBXGroup; children = ( 1997BC5E1B2C7ABA00140A9B /* AppDelegate.swift */, + 196018EB1B2DE0F300B420B7 /* Extensions.swift */, 1997BC601B2C7ABA00140A9B /* ViewController.swift */, 1997BC801B2C889700140A9B /* EquipmentCell.swift */, 1997BC7E1B2C7AEF00140A9B /* BLEDevice.swift */, + 196018661B2CA7AE00B420B7 /* BLEPeripheral.swift */, 1997BC621B2C7ABA00140A9B /* Main.storyboard */, + 196018681B2CABD200B420B7 /* AuthorizedEquipment.swift */, 1997BC651B2C7ABA00140A9B /* Images.xcassets */, 1997BC671B2C7ABA00140A9B /* LaunchScreen.xib */, 1997BC5C1B2C7ABA00140A9B /* Supporting Files */, @@ -118,6 +139,24 @@ name = "Supporting Files"; sourceTree = ""; }; + 4AB918BDF8FD9F6FFFC5C407 /* Pods */ = { + isa = PBXGroup; + children = ( + 952FB4BA2490BE47A6E6528E /* Pods-GetDibs.debug.xcconfig */, + 442861A008DF10675CAED3BC /* Pods-GetDibs.release.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; + 51CFFA30ADE92384E6ED67CE /* Frameworks */ = { + isa = PBXGroup; + children = ( + 196018E91B2CB99900B420B7 /* ParseUI.framework */, + C79DA1FDF406CFA3592AC29D /* Pods_GetDibs.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -125,9 +164,12 @@ isa = PBXNativeTarget; buildConfigurationList = 1997BC781B2C7ABA00140A9B /* Build configuration list for PBXNativeTarget "GetDibs" */; buildPhases = ( + DA446B60E5603B51F93DD0BB /* Check Pods Manifest.lock */, 1997BC551B2C7ABA00140A9B /* Sources */, 1997BC561B2C7ABA00140A9B /* Frameworks */, 1997BC571B2C7ABA00140A9B /* Resources */, + AC54C86AC456340379AF294F /* Embed Pods Frameworks */, + A26B74E79688152495B5FD8C /* Copy Pods Resources */, ); buildRules = ( ); @@ -213,15 +255,66 @@ }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + A26B74E79688152495B5FD8C /* Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Copy Pods Resources"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-GetDibs/Pods-GetDibs-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + AC54C86AC456340379AF294F /* Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-GetDibs/Pods-GetDibs-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + DA446B60E5603B51F93DD0BB /* Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Check Pods Manifest.lock"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ 1997BC551B2C7ABA00140A9B /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 196018671B2CA7AE00B420B7 /* BLEPeripheral.swift in Sources */, 1997BC611B2C7ABA00140A9B /* ViewController.swift in Sources */, 1997BC7F1B2C7AEF00140A9B /* BLEDevice.swift in Sources */, + 196018691B2CABD200B420B7 /* AuthorizedEquipment.swift in Sources */, 1997BC811B2C889700140A9B /* EquipmentCell.swift in Sources */, 1997BC5F1B2C7ABA00140A9B /* AppDelegate.swift in Sources */, + 196018EC1B2DE0F300B420B7 /* Extensions.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -348,21 +441,36 @@ }; 1997BC791B2C7ABA00140A9B /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 952FB4BA2490BE47A6E6528E /* Pods-GetDibs.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + ); INFOPLIST_FILE = GetDibs/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "GetDibs-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; 1997BC7A1B2C7ABA00140A9B /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 442861A008DF10675CAED3BC /* Pods-GetDibs.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + ); INFOPLIST_FILE = GetDibs/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "GetDibs-Bridging-Header.h"; }; name = Release; }; @@ -419,6 +527,7 @@ 1997BC7A1B2C7ABA00140A9B /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; 1997BC7B1B2C7ABA00140A9B /* Build configuration list for PBXNativeTarget "GetDibsTests" */ = { isa = XCConfigurationList; @@ -427,6 +536,7 @@ 1997BC7D1B2C7ABA00140A9B /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; diff --git a/GetDibs/AppDelegate.swift b/GetDibs/AppDelegate.swift index e83c8a5..866abf7 100644 --- a/GetDibs/AppDelegate.swift +++ b/GetDibs/AppDelegate.swift @@ -7,6 +7,7 @@ // import UIKit +import Parse @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { @@ -15,7 +16,13 @@ class AppDelegate: UIResponder, UIApplicationDelegate { func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { - // Override point for customization after application launch. + let kAppID = "V5y9CHmlEF9n3wxITNogwnzvhr6TuPPwrPlY34pM" + let kClientKey = "j4peDjpdtO9MyhawlzyxRDNQxfJV6fhwGu4dAnzS" + + AuthorizedEquipment.registerSubclass(); + + Parse.setApplicationId(kAppID, clientKey: kClientKey); + return true } diff --git a/GetDibs/AuthorizedEquipment.swift b/GetDibs/AuthorizedEquipment.swift new file mode 100644 index 0000000..89a9eae --- /dev/null +++ b/GetDibs/AuthorizedEquipment.swift @@ -0,0 +1,29 @@ +// +// AuthorizedEquipment.swift +// GetDibs +// +// Created by Kevin McQuown on 6/13/15. +// Copyright (c) 2015 Windy City Lab. All rights reserved. +// + +import Parse + +class AuthorizedEquipment: PFObject, PFSubclassing +{ + class func parseClassName() -> String { + return "AuthorizedEquipment" + } + + @NSManaged var user : PFUser; + @NSManaged var machineID : String; + + class func getAuthorizedMachines(block: PFArrayResultBlock?) + { + let q = PFQuery(className: parseClassName()); + q.whereKey("user", equalTo: PFUser.currentUser()!) + + q.findObjectsInBackgroundWithBlock { (results, error) -> Void in + block!(results,error); + } + } +} diff --git a/GetDibs/BLEDevice.swift b/GetDibs/BLEDevice.swift index 9003e54..f76b18c 100644 --- a/GetDibs/BLEDevice.swift +++ b/GetDibs/BLEDevice.swift @@ -9,10 +9,12 @@ import Foundation import CoreBluetooth -//let kServiceID = "6e400001-b5a3-f393-e0a9-e50e24dcca9e" let kServiceID = "15e9a83f-88bd-41e4-8f7c-3aec6e5229e6" +let kMD5HashSalt = "6A2041DB-5942-44D7-844C-8C17D7926107" let kCBAdvDataLocalName = "kCBAdvDataLocalName" let kCBAdvDataManufacturerData = "kCBAdvDataManufacturerData" +let kCatalyzeDeviceName = "kCatalyzeDeviceName" +var sendingFirstHalf = true; private let sharedBLEDevice = BLEDevice() @@ -24,11 +26,21 @@ protocol BLEDeviceDelegate class BLEDevice : NSObject, CBCentralManagerDelegate, CBPeripheralDelegate { + var commandToSend : NSData! = nil var centralNode : CBCentralManager! = nil var serviceUUID : CBUUID! = nil; - var loopTrackPeripheral : CBPeripheral! = nil; + var peripherals : [String:BLEPeripheral] = [:] + var peripheralsArray : [BLEPeripheral] = Array(); var notifyOnUpdate : CBCharacteristic! = nil; var writeToPeripheral : CBCharacteristic! = nil; + var selectedPeripheral : BLEPeripheral? = nil; + var selectedPeripheralUUID : String = "" + { + didSet + { + selectedPeripheral = peripherals[selectedPeripheralUUID]; + } + } var deviceName : String! = nil; var deviceID : NSData! = nil; @@ -43,7 +55,7 @@ class BLEDevice : NSObject, CBCentralManagerDelegate, CBPeripheralDelegate func begin() { serviceUUID = CBUUID(string: kServiceID); - centralNode = CBCentralManager(delegate: self, queue: nil, options:["CBCentralManagerOptionRestoreIdentifierKey":"loopTrackCentralManager"]); + centralNode = CBCentralManager(delegate: self, queue: nil, options:["CBCentralManagerOptionRestoreIdentifierKey":kCatalyzeDeviceName]); } func refresh() @@ -51,38 +63,35 @@ class BLEDevice : NSObject, CBCentralManagerDelegate, CBPeripheralDelegate self.delegate.connectionStateDidUpdate() } - func sendCommand(command : String) - { - let data = command.dataUsingEncoding(NSUTF8StringEncoding) - loopTrackPeripheral.writeValue(data, forCharacteristic: writeToPeripheral, type: CBCharacteristicWriteType.WithResponse) - } - - func isConnected() -> Bool - { - return (loopTrackPeripheral != nil) - // println("Connected services: \(centralNode.retrieveConnectedPeripheralsWithServices([serviceUUID]).count)"); - // return centralNode.retrieveConnectedPeripheralsWithServices([serviceUUID]).count > 0; - } +// func sendCommand(command : String) +// { +// let data = command.dataUsingEncoding(NSUTF8StringEncoding) +// selectedPeripheral!.peripheral.writeValue(data, forCharacteristic: writeToPeripheral, type: CBCharacteristicWriteType.WithResponse) +// } - func removeConnection() + func removeConnection(forPeripheral : BLEPeripheral) { - if (loopTrackPeripheral != nil) - { - loopTrackPeripheral.setNotifyValue(false, forCharacteristic: notifyOnUpdate); - loopTrackPeripheral.setNotifyValue(false, forCharacteristic: writeToPeripheral); - centralNode.cancelPeripheralConnection(loopTrackPeripheral); - } + forPeripheral.peripheral.setNotifyValue(false, forCharacteristic: notifyOnUpdate); + forPeripheral.peripheral.setNotifyValue(false, forCharacteristic: writeToPeripheral); + centralNode.cancelPeripheralConnection(forPeripheral.peripheral); } - func createConnection() - { - centralNode.scanForPeripheralsWithServices([serviceUUID], options: nil); - } +// func toggleConnection(toPeripheral : BLEPeripheral) +// { +// if toPeripheral.isConnected +// { +// removeConnection(toPeripheral) +// } +// else +// { +// centralNode.connectPeripheral(toPeripheral.peripheral, options: nil); +// } +// } //MARK: func peripheral(peripheral: CBPeripheral!, didDiscoverServices error: NSError!) { - println("did discover services for loop track display"); + println("did discover services for peripheral"); for service in peripheral.services { println("service: \(service.UUID)") @@ -95,45 +104,97 @@ class BLEDevice : NSObject, CBCentralManagerDelegate, CBPeripheralDelegate println("didupdatevalueforcharacteristic: \(characteristic.value) -- \(messsage)"); } + func peripheral(peripheral: CBPeripheral!, didWriteValueForCharacteristic characteristic: CBCharacteristic!, error: NSError!) { +// if sendingFirstHalf +// { +// println("didWriteValue (1 of 2)"); +// sendingFirstHalf = false; +// peripheral.writeValue(commandToSend.subdataWithRange(NSMakeRange(16, 16)), forCharacteristic: writeToPeripheral, type: CBCharacteristicWriteType.WithResponse) +// } + println("didWriteValue (2 of 2)"); + + removeConnection(peripherals[peripheral.identifier.UUIDString]!); +// centralNode.cancelPeripheralConnection(peripheral) + } + func peripheral(peripheral: CBPeripheral!, didDiscoverCharacteristicsForService service: CBService!, error: NSError!) { for characteristic in service.characteristics { delegate.connectionStateDidUpdate(); switch (characteristic as! CBCharacteristic).properties { - case CBCharacteristicProperties.Notify : - peripheral.setNotifyValue(true, forCharacteristic: characteristic as! CBCharacteristic) - notifyOnUpdate = characteristic as! CBCharacteristic - println("added notify characteristic for service \(service.UUID)"); - case CBCharacteristicProperties.Write : - writeToPeripheral = characteristic as! CBCharacteristic - println("added write characteristic for service \(service.UUID)"); - default : - () + case CBCharacteristicProperties.Notify : + peripheral.setNotifyValue(true, forCharacteristic: characteristic as! CBCharacteristic) + notifyOnUpdate = characteristic as! CBCharacteristic + println("added notify characteristic for service \(service.UUID)"); + case CBCharacteristicProperties.Write : + writeToPeripheral = characteristic as! CBCharacteristic + println("added write characteristic for service \(service.UUID)"); + println("sending the following: \(commandToSend) of size: \(commandToSend.length)"); + peripheral.writeValue(commandToSend, forCharacteristic: writeToPeripheral, type: CBCharacteristicWriteType.WithResponse) + + default : + () } } } //MARK: + func addPeripheralToSetOfPeripherals(peripheral : BLEPeripheral) + { + peripherals[peripheral.peripheral.identifier.UUIDString] = peripheral + peripheralsArray.removeAll(keepCapacity: true) + for (key, value) in peripherals + { + peripheralsArray.append(value) + } + } + func centralManager(central: CBCentralManager!, didDiscoverPeripheral peripheral: CBPeripheral!, advertisementData: [NSObject : AnyObject]!, RSSI: NSNumber!) { - println("did discover loop track display"); + println("did discover peripheral \(peripheral.identifier)"); println("advertisement data: \(advertisementData)"); - self.deviceName = advertisementData[kCBAdvDataLocalName] as? String; - self.deviceID = advertisementData[kCBAdvDataManufacturerData] as? NSData; - central.stopScan(); - loopTrackPeripheral = peripheral; - loopTrackPeripheral.delegate = self; - central.connectPeripheral(loopTrackPeripheral, options: nil); + + var p = BLEPeripheral(); + p.peripheral = peripheral; + p.deviceName = advertisementData[kCBAdvDataLocalName] as? String; + + p.deviceID = (advertisementData[kCBAdvDataManufacturerData] as? NSData)?.subdataWithRange(NSMakeRange(0, 2)); + + var onOffData = (advertisementData[kCBAdvDataManufacturerData] as? NSData)!.subdataWithRange(NSMakeRange(2, 1)) + println("\(onOffData)") + p.isOn = ("\(onOffData)" == "<01>"); + addPeripheralToSetOfPeripherals(p) + + self.delegate.connectionStateDidUpdate() + peripheral.delegate = self; + } + + func timeAsString() -> String + { + return "2015-06-14-10-03" + } + func send(command : String, toPeripheral : BLEPeripheral) + { + var actualCommand = "\(command)\(kMD5HashSalt)\(timeAsString())" + var md5Hash = actualCommand.MD5() + println("sending: \(md5Hash)"); + self.commandToSend = md5Hash.dataUsingEncoding(NSUTF8StringEncoding) +// self.commandToSend = "012345678901234567890123456789".dataUsingEncoding(NSUTF8StringEncoding) + centralNode.connectPeripheral(toPeripheral.peripheral, options: nil); } func centralManager(central: CBCentralManager!, didConnectPeripheral peripheral: CBPeripheral!) { println("did connect to peripheral"); - loopTrackPeripheral.delegate = self; + let p = peripherals[peripheral.identifier.UUIDString]! + p.isConnected = true; peripheral.discoverServices(nil) } + func centralManager(central: CBCentralManager!, didDisconnectPeripheral peripheral: CBPeripheral!, error: NSError!) { println("Peripheral Disconnected..."); + let p = peripherals[peripheral.identifier.UUIDString]! + p.isConnected = false; delegate.connectionStateDidUpdate() central.scanForPeripheralsWithServices([serviceUUID], options: nil); } diff --git a/GetDibs/BLEPeripheral.swift b/GetDibs/BLEPeripheral.swift new file mode 100644 index 0000000..1a3fa67 --- /dev/null +++ b/GetDibs/BLEPeripheral.swift @@ -0,0 +1,20 @@ +// +// Peripheral.swift +// GetDibs +// +// Created by Kevin McQuown on 6/13/15. +// Copyright (c) 2015 Windy City Lab. All rights reserved. +// + +import CoreBluetooth +import Foundation + +class BLEPeripheral { + + var peripheral : CBPeripheral! = nil; + var deviceID : NSData! = nil; + var deviceName: String! = nil; + var isOn:Bool = false; + var isConnected:Bool = false; + +} diff --git a/GetDibs/Base.lproj/Main.storyboard b/GetDibs/Base.lproj/Main.storyboard index 1bee194..3f32576 100644 --- a/GetDibs/Base.lproj/Main.storyboard +++ b/GetDibs/Base.lproj/Main.storyboard @@ -2,6 +2,7 @@ + @@ -16,16 +17,49 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + + @@ -35,6 +69,12 @@ + + + + + + diff --git a/GetDibs/EquipmentCell.swift b/GetDibs/EquipmentCell.swift index fe59c8e..5625a9c 100644 --- a/GetDibs/EquipmentCell.swift +++ b/GetDibs/EquipmentCell.swift @@ -7,7 +7,33 @@ // import UIKit +import CoreBluetooth + +protocol EquipmentCellDelegate +{ + func equipmentCellSwitchTapped(peripheral : BLEPeripheral) +} class EquipmentCell: UITableViewCell { + var delegate : EquipmentCellDelegate! + + var peripheral : BLEPeripheral! = nil + { + didSet + { + nameLabel.text = peripheral.deviceName; + codeLabel.text = "\(peripheral.deviceID)"; + onOffSwitch.on = peripheral.isOn; + } + } + + @IBAction func onOffTapped(sender: AnyObject) { + onOffSwitch.setOn(peripheral.isOn, animated: false) + self.delegate.equipmentCellSwitchTapped(peripheral) + } + + @IBOutlet weak var onOffSwitch: UISwitch! + @IBOutlet weak var codeLabel: UILabel! + @IBOutlet weak var nameLabel: UILabel! } diff --git a/GetDibs/Extensions.swift b/GetDibs/Extensions.swift new file mode 100644 index 0000000..c0e3bbb --- /dev/null +++ b/GetDibs/Extensions.swift @@ -0,0 +1,38 @@ +extension Int { + func hexString() -> String { + return String(format:"%02x", self) + } +} + +extension NSData { + func hexString() -> String { + var string = String() + for i in UnsafeBufferPointer(start: UnsafeMutablePointer(bytes), count: length) { + string += Int(i).hexString() + } + return string + } + + func MD5() -> NSData { +// let result = NSMutableData(length: Int(CC_MD5_DIGEST_LENGTH))! + let result = NSMutableData(length: Int(10))! + CC_MD5(bytes, CC_LONG(length), UnsafeMutablePointer(result.mutableBytes)) + return NSData(data: result) + } + + func SHA1() -> NSData { + let result = NSMutableData(length: Int(CC_SHA1_DIGEST_LENGTH))! + CC_SHA1(bytes, CC_LONG(length), UnsafeMutablePointer(result.mutableBytes)) + return NSData(data: result) + } +} + +extension String { + func MD5() -> String { + return (self as NSString).dataUsingEncoding(NSUTF8StringEncoding)!.MD5().hexString() + } + + func SHA1() -> String { + return (self as NSString).dataUsingEncoding(NSUTF8StringEncoding)!.SHA1().hexString() + } +} \ No newline at end of file diff --git a/GetDibs/ViewController.swift b/GetDibs/ViewController.swift index 7de2dea..397522e 100644 --- a/GetDibs/ViewController.swift +++ b/GetDibs/ViewController.swift @@ -7,22 +7,113 @@ // import UIKit +import Parse -class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { +class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, BLEDeviceDelegate, PFLogInViewControllerDelegate, EquipmentCellDelegate { @IBOutlet weak var tableView: UITableView! + var equipment : BLEDevice! = nil; + var authorizedMachines : [String:String] = [:] + + func connectionStateDidUpdate() { + tableView.reloadData() + } + + func equipmentCellSwitchTapped(peripheral: BLEPeripheral) { + if peripheral.isOn + { + peripheral.isOn = false; + self.equipment.send("O", toPeripheral: peripheral); + self.tableView.reloadData() + } + else + { + let confirm = UIAlertController(title: "Please Confirm", message: "Do you want to turn \(peripheral.deviceName) on?", preferredStyle: UIAlertControllerStyle.Alert) + let ok = UIAlertAction(title: "YES", style: UIAlertActionStyle.Destructive, handler: { (action) -> Void in + self.equipment.send("X", toPeripheral: peripheral); + peripheral.isOn = true; + self.tableView.reloadData(); + }) + let cancel = UIAlertAction(title: "NO", style: UIAlertActionStyle.Default, handler: { (action) -> Void in + () + }) + confirm.addAction(cancel) + confirm.addAction(ok) + presentViewController(confirm, animated: true, completion: nil) + } + } + //MARK: + //MARK: Tableview delegates and datasource + //MARK: func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { var cell = tableView.dequeueReusableCellWithIdentifier("equipmentCell") as! EquipmentCell + cell.delegate = self + let item = equipment.peripheralsArray[indexPath.row] + cell.peripheral = item + cell.onOffSwitch.enabled = false; + if authorizedMachines["\(item.deviceID)"] != nil + { + cell.onOffSwitch.enabled = true; + } return cell } func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return 0; + if equipment == nil + { + return 0; + } + return equipment.peripheralsArray.count; + } + + func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { + tableView.deselectRowAtIndexPath(indexPath, animated: true) +// equipment.toggleConnection(equipment.peripheralsArray[indexPath.row]) + } + + //MARK: + //MARK: Parse cloud work + //MARK: + + func queryAuthorizedEquipment() + { + AuthorizedEquipment.getAuthorizedMachines({ (machines, error) -> Void in + for machine in machines! + { + let m = machine as! AuthorizedEquipment + self.authorizedMachines["<\(m.machineID)>"] = "" + } + self.equipment = BLEDevice.sharedInstance; + self.equipment.delegate = self; + self.equipment.begin(); + }) + } + + //MARK: + //MARK: Viewcontroller lifecycle + //MARK: + + override func viewWillAppear(animated: Bool) { + + super.viewWillAppear(animated) + + if PFUser.currentUser() == nil + { + let login = PFLogInViewController() + login.delegate = self; + self.authorizedMachines.removeAll(keepCapacity: true) + presentViewController(login, animated: true, completion: { () -> Void in + self.queryAuthorizedEquipment() + }) + } + else + { + queryAuthorizedEquipment() + } } override func viewDidLoad() { super.viewDidLoad() - // Do any additional setup after loading the view, typically from a nib. } override func didReceiveMemoryWarning() { diff --git a/ParseUI.framework/Headers/PFCollectionViewCell.h b/ParseUI.framework/Headers/PFCollectionViewCell.h new file mode 100644 index 0000000..71b3642 --- /dev/null +++ b/ParseUI.framework/Headers/PFCollectionViewCell.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2014, Parse, LLC. All rights reserved. + * + * You are hereby granted a non-exclusive, worldwide, royalty-free license to use, + * copy, modify, and distribute this software in source code or binary form for use + * in connection with the web services and APIs provided by Parse. + * + * As with any software that integrates with the Parse platform, your use of + * this software is subject to the Parse Terms of Service + * [https://www.parse.com/about/terms]. This copyright notice shall be + * included in all copies or substantial portions of the software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#import + +#import + +PFUI_ASSUME_NONNULL_BEGIN + +@class PFImageView; +@class PFObject; + +/*! + The `PFCollectionViewCell` class represents a collection view cell which can + download and display remote images stored on Parse as well as has a default simple text label. + */ +@interface PFCollectionViewCell : UICollectionViewCell + +/*! + @abstract A simple lazy-loaded label for the collection view cell. + */ +@property (nonatomic, strong, readonly) UILabel *textLabel; + +/*! + @abstract The lazy-loaded imageView of the collection view cell. + + @see PFImageView + */ +@property (nonatomic, strong, readonly) PFImageView *imageView; + +/*! + @abstract This method should update all the relevant information inside a subclass of `PFCollectionViewCell`. + + @discussion This method is automatically called by whenever the cell + should display new information. By default this method does nothing. + + @param object An instance of `PFObject` to update from. + */ +- (void)updateFromObject:(PFUI_NULLABLE PFObject *)object; + +@end + +PFUI_ASSUME_NONNULL_END diff --git a/ParseUI.framework/Headers/PFImageView.h b/ParseUI.framework/Headers/PFImageView.h new file mode 100644 index 0000000..368b3d6 --- /dev/null +++ b/ParseUI.framework/Headers/PFImageView.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2014, Parse, LLC. All rights reserved. + * + * You are hereby granted a non-exclusive, worldwide, royalty-free license to use, + * copy, modify, and distribute this software in source code or binary form for use + * in connection with the web services and APIs provided by Parse. + * + * As with any software that integrates with the Parse platform, your use of + * this software is subject to the Parse Terms of Service + * [https://www.parse.com/about/terms]. This copyright notice shall be + * included in all copies or substantial portions of the software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#import + +#import + +PFUI_ASSUME_NONNULL_BEGIN + +typedef void(^PFImageViewImageResultBlock)(UIImage *PFUI_NULLABLE_S image, NSError *PFUI_NULLABLE_S error); + +@class BFTask; +@class PFFile; + +/*! + An image view that downloads and displays remote image stored on Parse's server. + */ +@interface PFImageView : UIImageView + +/*! + @abstract The remote file on Parse's server that stores the image. + + @warning Note that the download does not start until is called. + */ +@property (PFUI_NULLABLE_PROPERTY nonatomic, strong) PFFile *file; + +/*! + @abstract Initiate downloading of the remote image. + + @discussion Once the download completes, the remote image will be displayed. + + @returns The task, that encapsulates the work being done. + */ +- (BFTask *)loadInBackground; + +/*! + @abstract Initiate downloading of the remote image. + + @discussion Once the download completes, the remote image will be displayed. + + @param completion the completion block. + */ +- (void)loadInBackground:(PFUI_NULLABLE PFImageViewImageResultBlock)completion; + +/*! + @abstract Initiate downloading of the remote image. + + @discussion Once the download completes, the remote image will be displayed. + + @param completion the completion block. + @param progressBlock called with the download progress as the image is being downloaded. + Will be called with a value of 100 before the completion block is called. + */ +- (void)loadInBackground:(PFUI_NULLABLE PFImageViewImageResultBlock)completion + progressBlock:(PFUI_NULLABLE void (^)(int percentDone))progressBlock; + +@end + +PFUI_ASSUME_NONNULL_END diff --git a/ParseUI.framework/Headers/PFLogInView.h b/ParseUI.framework/Headers/PFLogInView.h new file mode 100644 index 0000000..ee71b02 --- /dev/null +++ b/ParseUI.framework/Headers/PFLogInView.h @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2014, Parse, LLC. All rights reserved. + * + * You are hereby granted a non-exclusive, worldwide, royalty-free license to use, + * copy, modify, and distribute this software in source code or binary form for use + * in connection with the web services and APIs provided by Parse. + * + * As with any software that integrates with the Parse platform, your use of + * this software is subject to the Parse Terms of Service + * [https://www.parse.com/about/terms]. This copyright notice shall be + * included in all copies or substantial portions of the software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#import + +#import + +PFUI_ASSUME_NONNULL_BEGIN + +/*! + `PFLogInFields` bitmask specifies the log in elements which are enabled in the view. + + @see PFLogInViewController + @see PFLogInView + */ +typedef NS_OPTIONS(NSInteger, PFLogInFields) { + /*! No fields. */ + PFLogInFieldsNone = 0, + /*! Username and password fields. */ + PFLogInFieldsUsernameAndPassword = 1 << 0, + /*! Forgot password button. */ + PFLogInFieldsPasswordForgotten = 1 << 1, + /*! Login button. */ + PFLogInFieldsLogInButton = 1 << 2, + /*! Button to login with Facebook. */ + PFLogInFieldsFacebook = 1 << 3, + /*! Button to login with Twitter. */ + PFLogInFieldsTwitter = 1 << 4, + /*! Signup Button. */ + PFLogInFieldsSignUpButton = 1 << 5, + /*! Dismiss Button. */ + PFLogInFieldsDismissButton = 1 << 6, + + /*! Default value. Combines Username, Password, Login, Signup, Forgot Password and Dismiss buttons. */ + PFLogInFieldsDefault = (PFLogInFieldsUsernameAndPassword | + PFLogInFieldsLogInButton | + PFLogInFieldsSignUpButton | + PFLogInFieldsPasswordForgotten | + PFLogInFieldsDismissButton) +}; + +@class PFTextField; + +/*! + The `PFLogInView` class provides a standard log in interface for authenticating a . + */ +@interface PFLogInView : UIScrollView + +///-------------------------------------- +/// @name Creating Log In View +///-------------------------------------- + +/*! + @abstract Initializes the view with the specified log in elements. + + @param fields A bitmask specifying the log in elements which are enabled in the view + + @returns An initialized `PFLogInView` object or `nil` if the object couldn't be created. + + @see PFLogInFields + */ +- (instancetype)initWithFields:(PFLogInFields)fields; + +/*! + @abstract The view controller that will present this view. + + @discussion Used to lay out elements correctly when the presenting view controller has translucent elements. + */ +@property (PFUI_NULLABLE_PROPERTY nonatomic, weak) UIViewController *presentingViewController; + +///-------------------------------------- +/// @name Customizing the Logo +///-------------------------------------- + +/// The logo. By default, it is the Parse logo. +@property (PFUI_NULLABLE_PROPERTY nonatomic, strong) UIView *logo; + +///-------------------------------------- +/// @name Configure Username Behaviour +///-------------------------------------- + +/*! + @abstract If email should be used to log in, instead of username + + @discussion By default, this is set to `NO`. + */ +@property (nonatomic, assign) BOOL emailAsUsername; + +///-------------------------------------- +/// @name Log In Elements +///-------------------------------------- + +/*! + @abstract The bitmask which specifies the enabled log in elements in the view. + */ +@property (nonatomic, assign, readonly) PFLogInFields fields; + +/*! + @abstract The username text field. It is `nil` if the element is not enabled. + */ +@property (PFUI_NULLABLE_PROPERTY nonatomic, strong, readonly) PFTextField *usernameField; + +/*! + @abstract The password text field. It is `nil` if the element is not enabled. + */ +@property (PFUI_NULLABLE_PROPERTY nonatomic, strong, readonly) PFTextField *passwordField; + +/*! + @abstract The password forgotten button. It is `nil` if the element is not enabled. + */ +@property (PFUI_NULLABLE_PROPERTY nonatomic, strong, readonly) UIButton *passwordForgottenButton; + +/*! + @abstract The log in button. It is `nil` if the element is not enabled. + */ +@property (PFUI_NULLABLE_PROPERTY nonatomic, strong, readonly) UIButton *logInButton; + +/*! + @abstract The Facebook button. It is `nil` if the element is not enabled. + */ +@property (PFUI_NULLABLE_PROPERTY nonatomic, strong, readonly) UIButton *facebookButton; + +/*! + @abstract The Twitter button. It is `nil` if the element is not enabled. + */ +@property (PFUI_NULLABLE_PROPERTY nonatomic, strong, readonly) UIButton *twitterButton; + +/*! + @abstract The sign up button. It is `nil` if the element is not enabled. + */ +@property (PFUI_NULLABLE_PROPERTY nonatomic, strong, readonly) UIButton *signUpButton; + +/*! + @abstract It is `nil` if the element is not enabled. + */ +@property (PFUI_NULLABLE_PROPERTY nonatomic, strong, readonly) UIButton *dismissButton; + +/*! + @abstract The facebook/twitter login label. + + @deprecated This property is deprecated and will always be nil. + */ +@property (PFUI_NULLABLE_PROPERTY nonatomic, strong, readonly) UILabel *externalLogInLabel __attribute__(PARSE_UI_DEPRECATED("This property is deprecated and will always be nil.")); + +/*! + @abstract The sign up label. + + @deprecated This property is deprecated and will always be nil. + */ +@property (PFUI_NULLABLE_PROPERTY nonatomic, strong, readonly) UILabel *signUpLabel __attribute__(PARSE_UI_DEPRECATED("This property is deprecated and will always be nil.")); + +@end + +PFUI_ASSUME_NONNULL_END diff --git a/ParseUI.framework/Headers/PFLogInViewController.h b/ParseUI.framework/Headers/PFLogInViewController.h new file mode 100644 index 0000000..9df9112 --- /dev/null +++ b/ParseUI.framework/Headers/PFLogInViewController.h @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2014, Parse, LLC. All rights reserved. + * + * You are hereby granted a non-exclusive, worldwide, royalty-free license to use, + * copy, modify, and distribute this software in source code or binary form for use + * in connection with the web services and APIs provided by Parse. + * + * As with any software that integrates with the Parse platform, your use of + * this software is subject to the Parse Terms of Service + * [https://www.parse.com/about/terms]. This copyright notice shall be + * included in all copies or substantial portions of the software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#import + +#import +#import + +PFUI_ASSUME_NONNULL_BEGIN + +@class PFSignUpViewController; +@class PFUser; +@protocol PFLogInViewControllerDelegate; + +/*! + The `PFLogInViewController` class presents and manages a standard authentication interface for logging in a . + */ +@interface PFLogInViewController : UIViewController + +///-------------------------------------- +/// @name Configuring Log In Elements +///-------------------------------------- + +/*! + @abstract A bitmask specifying the log in elements which are enabled in the view. + + @see PFLogInFields + */ +@property (nonatomic, assign) PFLogInFields fields; + + +/*! + @abstract The log in view. It contains all the enabled log in elements. + + @see PFLogInView + */ +@property (PFUI_NULLABLE_PROPERTY nonatomic, strong, readonly) PFLogInView *logInView; + +///-------------------------------------- +/// @name Configuring Log In Behaviors +///-------------------------------------- + +/*! + @abstract The delegate that responds to the control events of `PFLogInViewController`. + + @see PFLogInViewControllerDelegate + */ +@property (PFUI_NULLABLE_PROPERTY nonatomic, weak) id delegate; + +/*! + @abstract The facebook permissions that Facebook log in requests for. + + @discussion If unspecified, the default is basic facebook permissions. + */ +@property (PFUI_NULLABLE_PROPERTY nonatomic, copy) NSArray *facebookPermissions; + +/*! + @abstract The sign up controller if sign up is enabled. + + @discussion Use this to configure the sign up view, and the transition animation to the sign up view. + The default is a sign up view with a username, a password, a dismiss button and a sign up button. + */ +@property (PFUI_NULLABLE_PROPERTY nonatomic, strong) PFSignUpViewController *signUpController; + +/*! + @abstract Whether to prompt for the email as username on the login view. + + @discussion If set to `YES`, we'll prompt for the email in the username field. + This property value propagates to the attached . + By default, this is set to `NO`. + */ +@property (nonatomic, assign) BOOL emailAsUsername; + +@end + +///-------------------------------------- +/// @name Notifications +///-------------------------------------- + +/*! + @abstract The notification is posted immediately after the log in succeeds. + */ +extern NSString *const PFLogInSuccessNotification; + +/*! + @abstract The notification is posted immediately after the log in fails. + @discussion If the delegate prevents the log in from starting, the notification is not sent. + */ +extern NSString *const PFLogInFailureNotification; + +/*! + @abstract The notification is posted immediately after the log in is cancelled. + */ +extern NSString *const PFLogInCancelNotification; + +///-------------------------------------- +/// @name PFLogInViewControllerDelegate +///-------------------------------------- + +/*! + The `PFLogInViewControllerDelegate` protocol defines methods a delegate of a should implement. + All methods of this protocol are optional. + */ +@protocol PFLogInViewControllerDelegate + +@optional + +///-------------------------------------- +/// @name Customizing Behavior +///-------------------------------------- + +/*! + @abstract Sent to the delegate to determine whether the log in request should be submitted to the server. + + @param logInController The login view controller that is requesting the data. + @param username the username the user tries to log in with. + @param password the password the user tries to log in with. + + @returns A `BOOL` indicating whether the log in should proceed. + */ +- (BOOL)logInViewController:(PFLogInViewController *)logInController +shouldBeginLogInWithUsername:(NSString *)username + password:(NSString *)password; + +///-------------------------------------- +/// @name Responding to Actions +///-------------------------------------- + +/*! + @abstract Sent to the delegate when a is logged in. + + @param logInController The login view controller where login finished. + @param user object that is a result of the login. + */ +- (void)logInViewController:(PFLogInViewController *)logInController didLogInUser:(PFUser *)user; + +/*! + @abstract Sent to the delegate when the log in attempt fails. + + @discussion If you implement this method, PFLoginViewController will not automatically show its default + login failure alert view. Instead, you should show your custom alert view in your implementation. + + @param logInController The login view controller where login failed. + @param error `NSError` object representing the error that occured. + */ +- (void)logInViewController:(PFLogInViewController *)logInController + didFailToLogInWithError:(PFUI_NULLABLE NSError *)error; + +/*! + @abstract Sent to the delegate when the log in screen is cancelled. + + @param logInController The login view controller where login was cancelled. + */ +- (void)logInViewControllerDidCancelLogIn:(PFLogInViewController *)logInController; + +@end + +PFUI_ASSUME_NONNULL_END diff --git a/ParseUI.framework/Headers/PFProductTableViewController.h b/ParseUI.framework/Headers/PFProductTableViewController.h new file mode 100644 index 0000000..fa5ce55 --- /dev/null +++ b/ParseUI.framework/Headers/PFProductTableViewController.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, Parse, LLC. All rights reserved. + * + * You are hereby granted a non-exclusive, worldwide, royalty-free license to use, + * copy, modify, and distribute this software in source code or binary form for use + * in connection with the web services and APIs provided by Parse. + * + * As with any software that integrates with the Parse platform, your use of + * this software is subject to the Parse Terms of Service + * [https://www.parse.com/about/terms]. This copyright notice shall be + * included in all copies or substantial portions of the software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#import + +#import +#import + +PFUI_ASSUME_NONNULL_BEGIN + +/*! + `PFProductTableViewController` displays in-app purchase products stored on Parse. + In addition to setting up in-app purchases in iTunes Connect, the app developer needs + to register product information on Parse, in the Product class. + */ +@interface PFProductTableViewController : PFQueryTableViewController + +/*! + @abstract Initializes a product table view controller. + + @param style The UITableViewStyle for the table + + @returns An initialized `PFProductTableViewController` object or `nil` if the object couldn't be created. + */ +- (instancetype)initWithStyle:(UITableViewStyle)style NS_DESIGNATED_INITIALIZER; + +@end + +PFUI_ASSUME_NONNULL_END diff --git a/ParseUI.framework/Headers/PFPurchaseTableViewCell.h b/ParseUI.framework/Headers/PFPurchaseTableViewCell.h new file mode 100644 index 0000000..eb80487 --- /dev/null +++ b/ParseUI.framework/Headers/PFPurchaseTableViewCell.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2014, Parse, LLC. All rights reserved. + * + * You are hereby granted a non-exclusive, worldwide, royalty-free license to use, + * copy, modify, and distribute this software in source code or binary form for use + * in connection with the web services and APIs provided by Parse. + * + * As with any software that integrates with the Parse platform, your use of + * this software is subject to the Parse Terms of Service + * [https://www.parse.com/about/terms]. This copyright notice shall be + * included in all copies or substantial portions of the software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#import + +#import +#import + +PFUI_ASSUME_NONNULL_BEGIN + +/*! + An enum that represents states of the PFPurchaseTableViewCell. + @see PFPurchaseTableViewCell + */ +typedef NS_ENUM(uint8_t, PFPurchaseTableViewCellState) { + /*! Normal state of the cell. */ + PFPurchaseTableViewCellStateNormal = 0, + /*! Downloading state of the cell. */ + PFPurchaseTableViewCellStateDownloading, + /*! State of the cell, when the product was downloaded. */ + PFPurchaseTableViewCellStateDownloaded +}; + +/*! + `PFPurchaseTableViewCell` is a subclass that is used to show + products in a . + + @see PFProductTableViewController + */ +@interface PFPurchaseTableViewCell : PFTableViewCell + +/*! + @abstract State of the cell. + @see PFPurchaseTableViewCellState + */ +@property (nonatomic, assign) PFPurchaseTableViewCellState state; + +/*! + @abstract Label where price of the product is displayed. + */ +@property (PFUI_NULLABLE_PROPERTY nonatomic, strong, readonly) UILabel *priceLabel; + +/*! + @abstract Progress view that is shown, when the product is downloading. + */ +@property (PFUI_NULLABLE_PROPERTY nonatomic, strong, readonly) UIProgressView *progressView; + +@end + +PFUI_ASSUME_NONNULL_END diff --git a/ParseUI.framework/Headers/PFQueryCollectionViewController.h b/ParseUI.framework/Headers/PFQueryCollectionViewController.h new file mode 100644 index 0000000..e658269 --- /dev/null +++ b/ParseUI.framework/Headers/PFQueryCollectionViewController.h @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2014, Parse, LLC. All rights reserved. + * + * You are hereby granted a non-exclusive, worldwide, royalty-free license to use, + * copy, modify, and distribute this software in source code or binary form for use + * in connection with the web services and APIs provided by Parse. + * + * As with any software that integrates with the Parse platform, your use of + * this software is subject to the Parse Terms of Service + * [https://www.parse.com/about/terms]. This copyright notice shall be + * included in all copies or substantial portions of the software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#import + +#import + +PFUI_ASSUME_NONNULL_BEGIN + +@class BFTask; +@class PFCollectionViewCell; +@class PFObject; +@class PFQuery; + +/*! + This class allows you to think about a one-to-one mapping between a and a `UICollectionViewCell`, + rather than having to juggle index paths. + + You also get the following features out of the box: + + - Pagination with a cell that can be tapped to load the next page. + - Pull-to-refresh collection view header. + - Automatic downloading and displaying of remote images in cells. + - Loading screen, shown before any data is loaded. + - Automatic loading and management of the objects array. + - Various methods that can be overridden to customize behavior at major events in the data cycle. + + @see PFCollectionViewCell + */ +@interface PFQueryCollectionViewController : UICollectionViewController + +/*! + @abstract The class name of the this collection will use as a datasource. + */ +@property (PFUI_NULLABLE_PROPERTY nonatomic, copy) IBInspectable NSString *parseClassName; + +/*! + @abstract Whether the collection should use the default loading view. Default - `YES`. + */ +@property (nonatomic, assign) IBInspectable BOOL loadingViewEnabled; + +/*! + @abstract Whether the collection should use the built-in pull-to-refresh feature. Defualt - `YES`. + */ +@property (nonatomic, assign) IBInspectable BOOL pullToRefreshEnabled; + +/*! + @abstract Whether the collection should use the built-in pagination feature. Default - `YES`. + */ +@property (nonatomic, assign) IBInspectable BOOL paginationEnabled; + +/*! + @abstract The number of objects to show per page. Default - `25`. + */ +@property (nonatomic, assign) IBInspectable NSUInteger objectsPerPage; + +/*! + @abstract Whether the collection is actively loading new data from the server. + */ +@property (nonatomic, assign, getter=isLoading) BOOL loading; + +///-------------------------------------- +/// @name Creating a PFQueryCollectionViewController +///-------------------------------------- + +/*! + @abstract Initializes a view controller with a `UICollectionViewFlowLayout` and a class name + of that will be associated with this collection. + + @param className The class name of the instances of that this table will display. + + @returns An initialized `PFQueryCollectionViewController` object or `nil` if the object couldn't be created. + */ +- (instancetype)initWithClassName:(PFUI_NULLABLE NSString *)className; + +/*! + @abstract Initializes a view controller with a class name of that will be associated with this collection. + + @param layout Layout for collection view to use. + @param className The class name of the instances of that this table will display. + + @returns An initialized `PFQueryCollectionViewController` object or `nil` if the object couldn't be created. + */ +- (instancetype)initWithCollectionViewLayout:(UICollectionViewLayout *)layout + className:(PFUI_NULLABLE NSString *)className NS_DESIGNATED_INITIALIZER; + +///-------------------------------------- +/// @name Responding to Events +///-------------------------------------- + +/*! + Called when objects will be loaded from Parse. If you override this method, you must + call [super objectsWillLoad] in your implementation. + */ +- (void)objectsWillLoad NS_REQUIRES_SUPER; + +/*! + Called when objects have loaded from Parse. If you override this method, you must + call [super objectsDidLoad:] in your implementation. + @param error The Parse error from running the PFQuery, if there was any. + */ +- (void)objectsDidLoad:(PFUI_NULLABLE NSError *)error NS_REQUIRES_SUPER; + +///-------------------------------------- +/// @name Accessing Results +///-------------------------------------- + +/*! + @abstract The array of instances of that is used as a data source. + */ +@property (nonatomic, copy, readonly) NSArray *objects; + +/*! + @abstract Returns an object at a particular indexPath. + + @discussion The default impementation returns the object at `indexPath.item`. + If you want to return objects in a different indexPath order, like for sections, override this method. + + @param indexPath An instance of `NSIndexPath`. + + @returns The object at the specified indexPath. + */ +- (PFUI_NULLABLE PFObject *)objectAtIndexPath:(PFUI_NULLABLE NSIndexPath *)indexPath; + +/*! + @abstract Removes an object at the specified index path, animated. + */ +- (void)removeObjectAtIndexPath:(PFUI_NULLABLE NSIndexPath *)indexPath; + +/*! + @abstract Removes all objects at the specified index paths, animated. + */ +- (void)removeObjectsAtIndexPaths:(PFUI_NULLABLE NSArray *)indexes; + +///-------------------------------------- +/// @name Loading Data +///-------------------------------------- + +/*! + @abstract Clears the collection view and loads the first page of objects. + + @returns An awaitable task that completes when the reload succeeds + */ +- (BFTask *)loadObjects; + +/*! + @abstract Loads the objects of the at the specified page and appends it to the + objects already loaded and refreshes the collection. + + @param page The page of objects to load. + @param clear Whether to clear the collection view after receiving the objects. + + @returns An awaitable task that completes when the reload succeeds + */ +- (BFTask *)loadObjects:(NSInteger)page clear:(BOOL)clear; + +/*! + @abstract Loads the next page of objects, appends to table, and refreshes. + */ +- (void)loadNextPage; + +/*! + @abstract Clears the collection view of all objects. + */ +- (void)clear; + +///-------------------------------------- +/// @name Querying +///-------------------------------------- + +/*! + @abstract Override to construct your own custom to get the objects. + + @returns An instance of that method will use to the objects for this collection. + */ +- (PFQuery *)queryForCollection; + +///-------------------------------------- +/// @name Data Source Methods +///-------------------------------------- + +/*! + @abstract Override this method to customize each cell given a that is loaded. + + @warning The cell should inherit from which is a subclass of `UICollectionViewCell`. + + @param collectionView The collection view object associated with this controller. + @param indexPath The indexPath of the cell. + @param object The that is associated with the cell. + + @returns The cell that represents this object. + */ +- (PFUI_NULLABLE PFCollectionViewCell *)collectionView:(UICollectionView *)collectionView + cellForItemAtIndexPath:(NSIndexPath *)indexPath + object:(PFUI_NULLABLE PFObject *)object; + +/*! + @discussion Override this method to customize the view that allows the user to load the + next page when pagination is turned on. + + @param collectionView The collection view object associated with this controller. + + @returns The view that allows the user to paginate. + */ +- (PFUI_NULLABLE UICollectionReusableView *)collectionViewReusableViewForNextPageAction:(UICollectionView *)collectionView; + +@end + +PFUI_ASSUME_NONNULL_END diff --git a/ParseUI.framework/Headers/PFQueryTableViewController.h b/ParseUI.framework/Headers/PFQueryTableViewController.h new file mode 100644 index 0000000..4f73344 --- /dev/null +++ b/ParseUI.framework/Headers/PFQueryTableViewController.h @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2014, Parse, LLC. All rights reserved. + * + * You are hereby granted a non-exclusive, worldwide, royalty-free license to use, + * copy, modify, and distribute this software in source code or binary form for use + * in connection with the web services and APIs provided by Parse. + * + * As with any software that integrates with the Parse platform, your use of + * this software is subject to the Parse Terms of Service + * [https://www.parse.com/about/terms]. This copyright notice shall be + * included in all copies or substantial portions of the software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#import + +#import + +PFUI_ASSUME_NONNULL_BEGIN + +@class BFTask; +@class PFObject; +@class PFQuery; +@class PFTableViewCell; + +/*! + This class allows you to think about a one-to-one mapping between a and a `UITableViewCell`, + rather than having to juggle index paths. + + You also get the following features out of the box: + + - Pagination with a cell that can be tapped to load the next page. + - Pull-to-refresh table view header. + - Automatic downloading and displaying of remote images in cells. + - Loading screen, shown before any data is loaded. + - Automatic loading and management of the objects array. + - Various methods that can be overridden to customize behavior at major events in the data cycle. + */ +@interface PFQueryTableViewController : UITableViewController + +///-------------------------------------- +/// @name Creating a PFQueryTableViewController +///-------------------------------------- + +/*! + @abstract Initializes with a class name of the that will be associated with this table. + + @param style The UITableViewStyle for the table + @param className The class name of the instances of that this table will display. + + @returns An initialized `PFQueryTableViewController` object or `nil` if the object couldn't be created. + */ +- (instancetype)initWithStyle:(UITableViewStyle)style + className:(PFUI_NULLABLE NSString *)className NS_DESIGNATED_INITIALIZER; + +/*! + @abstract Initializes with a class name of the PFObjects that will be associated with this table. + + @param className The class name of the instances of that this table will display. + + @returns An initialized `PFQueryTableViewController` object or `nil` if the object couldn't be created. + */ +- (instancetype)initWithClassName:(PFUI_NULLABLE NSString *)className; + +///-------------------------------------- +/// @name Configuring Behavior +///-------------------------------------- + +/*! + @abstract The class name of the this table will use as a datasource. + */ +@property (PFUI_NULLABLE_PROPERTY nonatomic, copy) IBInspectable NSString *parseClassName; + +/*! + @abstract The key to use to display for the cell text label. + + @discussion This won't apply if you override + */ +@property (PFUI_NULLABLE_PROPERTY nonatomic, copy) IBInspectable NSString *textKey; + +/*! + @abstract The key to use to display for the cell image view. + + @discussion This won't apply if you override + */ +@property (PFUI_NULLABLE_PROPERTY nonatomic, copy) IBInspectable NSString *imageKey; + +/*! + @abstract The image to use as a placeholder for the cell images. + + @discussion This won't apply if you override + */ +@property (PFUI_NULLABLE_PROPERTY nonatomic, strong) IBInspectable UIImage *placeholderImage; + +/*! + @abstract Whether the table should use the default loading view. Default - `YES`. + */ +@property (nonatomic, assign) IBInspectable BOOL loadingViewEnabled; + +/*! + @abstract Whether the table should use the built-in pull-to-refresh feature. Defualt - `YES`. + */ +@property (nonatomic, assign) IBInspectable BOOL pullToRefreshEnabled; + +/*! + @abstract Whether the table should use the built-in pagination feature. Default - `YES`. + */ +@property (nonatomic, assign) IBInspectable BOOL paginationEnabled; + +/*! + @abstract The number of objects to show per page. Default - `25`. + */ +@property (nonatomic, assign) IBInspectable NSUInteger objectsPerPage; + +/*! + @abstract Whether the table is actively loading new data from the server. + */ +@property (nonatomic, assign, getter=isLoading) BOOL loading; + +///-------------------------------------- +/// @name Responding to Events +///-------------------------------------- + +/*! + Called when objects will loaded from Parse. If you override this method, you must + call [super objectsWillLoad] in your implementation. + */ +- (void)objectsWillLoad; + +/*! + Called when objects have loaded from Parse. If you override this method, you must + call [super objectsDidLoad:] in your implementation. + @param error The Parse error from running the PFQuery, if there was any. + */ +- (void)objectsDidLoad:(PFUI_NULLABLE NSError *)error; + +///-------------------------------------- +/// @name Accessing Results +///-------------------------------------- + +/*! + @abstract The array of instances of that is used as a data source. + */ +@property (PFUI_NULLABLE_PROPERTY nonatomic, copy, readonly) NSArray *objects; + +/*! + @abstract Returns an object at a particular indexPath. + + @discussion The default impementation returns the object at `indexPath.row`. + If you want to return objects in a different indexPath order, like for sections, override this method. + + @param indexPath The indexPath. + + @returns The object at the specified index + */ +- (PFUI_NULLABLE PFObject *)objectAtIndexPath:(PFUI_NULLABLE NSIndexPath *)indexPath; + +/*! + @abstract Removes an object at the specified index path, animated. + */ +- (void)removeObjectAtIndexPath:(PFUI_NULLABLE NSIndexPath *)indexPath; + +/*! + @abstract Removes an object at the specified index path, with or without animation. + */ +- (void)removeObjectAtIndexPath:(PFUI_NULLABLE NSIndexPath *)indexPath animated:(BOOL)animated; + +/*! + @abstract Removes all objects at the specified index paths, animated. + */ +- (void)removeObjectsAtIndexPaths:(PFUI_NULLABLE NSArray *)indexes; + +/*! + @abstract Removes all objects at the specified index paths, with or without animation. + */ +- (void)removeObjectsAtIndexPaths:(PFUI_NULLABLE NSArray *)indexes animated:(BOOL)animated; + +/*! + @abstract Clears the table of all objects. + */ +- (void)clear; + +/*! + @abstract Clears the table and loads the first page of objects. + + @returns An awaitable task that completes when the reload succeeds + */ +- (BFTask *)loadObjects; + +/*! + @abstract Loads the objects of the className at the specified page and appends it to the + objects already loaded and refreshes the table. + + @param page The page of objects to load. + @param clear Whether to clear the table after receiving the objects + + @returns An awaitable task that completes when the reload succeeds + */ +- (BFTask *)loadObjects:(NSInteger)page clear:(BOOL)clear; + +/*! + @abstract Loads the next page of objects, appends to table, and refreshes. + */ +- (void)loadNextPage; + +///-------------------------------------- +/// @name Querying +///-------------------------------------- + +/*! + Override to construct your own custom PFQuery to get the objects. + @result PFQuery that loadObjects will use to the objects for this table. + */ +- (PFQuery *)queryForTable; + +///-------------------------------------- +/// @name Data Source Methods +///-------------------------------------- + +/*! + @abstract Override this method to customize each cell given a PFObject that is loaded. + + @discussion If you don't override this method, it will use a default style cell and display either + the first data key from the object, or it will display the key as specified with `textKey`, `imageKey`. + + @warning The cell should inherit from which is a subclass of `UITableViewCell`. + + @param tableView The table view object associated with this controller. + @param indexPath The indexPath of the cell. + @param object The PFObject that is associated with the cell. + + @returns The cell that represents this object. + */ +- (PFUI_NULLABLE PFTableViewCell *)tableView:(UITableView *)tableView + cellForRowAtIndexPath:(NSIndexPath *)indexPath + object:(PFUI_NULLABLE PFObject *)object; + +/*! + @discussion Override this method to customize the cell that allows the user to load the + next page when pagination is turned on. + + @param tableView The table view object associated with this controller. + @param indexPath The indexPath of the cell. + + @returns The cell that allows the user to paginate. + */ +- (PFUI_NULLABLE PFTableViewCell *)tableView:(UITableView *)tableView + cellForNextPageAtIndexPath:(NSIndexPath *)indexPath; + +@end + +PFUI_ASSUME_NONNULL_END diff --git a/ParseUI.framework/Headers/PFSignUpView.h b/ParseUI.framework/Headers/PFSignUpView.h new file mode 100644 index 0000000..d6a8795 --- /dev/null +++ b/ParseUI.framework/Headers/PFSignUpView.h @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2014, Parse, LLC. All rights reserved. + * + * You are hereby granted a non-exclusive, worldwide, royalty-free license to use, + * copy, modify, and distribute this software in source code or binary form for use + * in connection with the web services and APIs provided by Parse. + * + * As with any software that integrates with the Parse platform, your use of + * this software is subject to the Parse Terms of Service + * [https://www.parse.com/about/terms]. This copyright notice shall be + * included in all copies or substantial portions of the software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#import + +#import + +PFUI_ASSUME_NONNULL_BEGIN + +/*! + `PFSignUpFields` bitmask specifies the sign up elements which are enabled in the view. + + @see PFSignUpViewController + @see PFSignUpView + */ +typedef NS_OPTIONS(NSInteger, PFSignUpFields) { + /*! Username and password fields. */ + PFSignUpFieldsUsernameAndPassword = 0, + /*! Email field. */ + PFSignUpFieldsEmail = 1 << 0, + /*! This field can be used for something else. */ + PFSignUpFieldsAdditional = 1 << 1, + /*! Sign Up Button */ + PFSignUpFieldsSignUpButton = 1 << 2, + /*! Dismiss Button */ + PFSignUpFieldsDismissButton = 1 << 3, + /*! Default value. Combines Username, Password, Email, Sign Up and Dismiss Buttons. */ + PFSignUpFieldsDefault = (PFSignUpFieldsUsernameAndPassword | + PFSignUpFieldsEmail | + PFSignUpFieldsSignUpButton | + PFSignUpFieldsDismissButton) +}; + +@class PFTextField; + +/*! + The `PFSignUpView` class provides a standard sign up interface for authenticating a . + */ +@interface PFSignUpView : UIScrollView + +///-------------------------------------- +/// @name Creating SignUp View +///-------------------------------------- + +/*! + @abstract Initializes the view with the specified sign up elements. + + @param fields A bitmask specifying the sign up elements which are enabled in the view + + @returns An initialized `PFSignUpView` object or `nil` if the object couldn't be created. + + @see PFSignUpFields + */ +- (instancetype)initWithFields:(PFSignUpFields)fields; + +/*! + @abstract The view controller that will present this view. + + @discussion Used to lay out elements correctly when the presenting view controller has translucent elements. + */ +@property (PFUI_NULLABLE_PROPERTY nonatomic, weak) UIViewController *presentingViewController; + +///-------------------------------------- +/// @name Customizing the Logo +///-------------------------------------- + +/*! + @abstract The logo. By default, it is the Parse logo. + */ +@property (PFUI_NULLABLE_PROPERTY nonatomic, strong) UIView *logo; + +///-------------------------------------- +/// @name Configure Username Behaviour +///-------------------------------------- + +/*! + @abstract If email should be used to log in, instead of username + + @discussion By default, this is set to `NO`. + */ +@property (nonatomic, assign) BOOL emailAsUsername; + +///-------------------------------------- +/// @name Sign Up Elements +///-------------------------------------- + +/*! + @abstract The bitmask which specifies the enabled sign up elements in the view + */ +@property (nonatomic, assign, readonly) PFSignUpFields fields; + +/*! + @abstract The username text field. + */ +@property (PFUI_NULLABLE_PROPERTY nonatomic, strong, readonly) PFTextField *usernameField; + +/*! + @abstract The password text field. + */ +@property (PFUI_NULLABLE_PROPERTY nonatomic, strong, readonly) PFTextField *passwordField; + +/*! + @abstract The email text field. It is `nil` if the element is not enabled. + */ +@property (PFUI_NULLABLE_PROPERTY nonatomic, strong, readonly) PFTextField *emailField; + +/*! + @abstract The additional text field. It is `nil` if the element is not enabled. + + @discussion This field is intended to be customized. + */ +@property (PFUI_NULLABLE_PROPERTY nonatomic, strong, readonly) PFTextField *additionalField; + +/*! + @abstract The sign up button. It is `nil` if the element is not enabled. + */ +@property (PFUI_NULLABLE_PROPERTY nonatomic, strong, readonly) UIButton *signUpButton; + +/*! + @abstract The dismiss button. It is `nil` if the element is not enabled. + */ +@property (PFUI_NULLABLE_PROPERTY nonatomic, strong, readonly) UIButton *dismissButton; + +@end + +PFUI_ASSUME_NONNULL_END diff --git a/ParseUI.framework/Headers/PFSignUpViewController.h b/ParseUI.framework/Headers/PFSignUpViewController.h new file mode 100644 index 0000000..88b2332 --- /dev/null +++ b/ParseUI.framework/Headers/PFSignUpViewController.h @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2014, Parse, LLC. All rights reserved. + * + * You are hereby granted a non-exclusive, worldwide, royalty-free license to use, + * copy, modify, and distribute this software in source code or binary form for use + * in connection with the web services and APIs provided by Parse. + * + * As with any software that integrates with the Parse platform, your use of + * this software is subject to the Parse Terms of Service + * [https://www.parse.com/about/terms]. This copyright notice shall be + * included in all copies or substantial portions of the software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#import + +#import +#import + +@class PFUser; +@protocol PFSignUpViewControllerDelegate; + +PFUI_ASSUME_NONNULL_BEGIN + +/*! + The `PFSignUpViewController` class that presents and manages + a standard authentication interface for signing up a . + */ +@interface PFSignUpViewController : UIViewController + +///-------------------------------------- +/// @name Configuring Sign Up Elements +///-------------------------------------- + +/*! + @abstract A bitmask specifying the log in elements which are enabled in the view. + + @see PFSignUpFields + */ +@property (nonatomic, assign) PFSignUpFields fields; + +/*! + @abstract The sign up view. It contains all the enabled log in elements. + + @see PFSignUpView + */ +@property (PFUI_NULLABLE_PROPERTY nonatomic, strong, readonly) PFSignUpView *signUpView; + +///-------------------------------------- +/// @name Configuring Sign Up Behaviors +///-------------------------------------- + +/*! + @abstract The delegate that responds to the control events of `PFSignUpViewController`. + + @see PFSignUpViewControllerDelegate + */ +@property (PFUI_NULLABLE_PROPERTY nonatomic, weak) id delegate; + +/*! + @abstract Minimum required password length for user signups, defaults to `0`. + */ +@property (nonatomic, assign) NSUInteger minPasswordLength; + +/*! + @abstract Whether to use the email as username on the attached . + + @discussion If set to `YES`, we'll hide the email field, prompt for the email in + the username field, and save the email into both username and email + fields on the new object. By default, this is set to `NO`. + */ +@property (nonatomic, assign) BOOL emailAsUsername; + +@end + +///-------------------------------------- +/// @name Notifications +///-------------------------------------- + +/*! + @abstract The notification is posted immediately after the sign up succeeds. + */ +extern NSString *const PFSignUpSuccessNotification; + +/*! + @abstract The notification is posted immediately after the sign up fails. + + @discussion If the delegate prevents the sign up to start, the notification is not sent. + */ +extern NSString *const PFSignUpFailureNotification; + +/*! + @abstract The notification is posted immediately after the user cancels sign up. + */ +extern NSString *const PFSignUpCancelNotification; + +///-------------------------------------- +/// @name PFSignUpViewControllerDelegate +///-------------------------------------- + +/*! + The `PFLogInViewControllerDelegate` protocol defines methods a delegate of a should implement. + All methods of this protocol are optional. + */ +@protocol PFSignUpViewControllerDelegate + +@optional + +///-------------------------------------- +/// @name Customizing Behavior +///-------------------------------------- + +/*! + @abstract Sent to the delegate to determine whether the sign up request should be submitted to the server. + + @param signUpController The signup view controller that is requesting the data. + @param info An `NSDictionary` instance which contains all sign up information that the user entered. + + @returns A `BOOL` indicating whether the sign up should proceed. + */ +- (BOOL)signUpViewController:(PFSignUpViewController *)signUpController shouldBeginSignUp:(NSDictionary *)info; + +///-------------------------------------- +/// @name Responding to Actions +///-------------------------------------- + +/*! + @abstract Sent to the delegate when a is signed up. + + @param signUpController The signup view controller where signup finished. + @param user object that is a result of the sign up. + */ +- (void)signUpViewController:(PFSignUpViewController *)signUpController didSignUpUser:(PFUser *)user; + +/*! + @abstract Sent to the delegate when the sign up attempt fails. + + @param signUpController The signup view controller where signup failed. + @param error `NSError` object representing the error that occured. + */ +- (void)signUpViewController:(PFSignUpViewController *)signUpController + didFailToSignUpWithError:(PFUI_NULLABLE NSError *)error; + +/*! + @abstract Sent to the delegate when the sign up screen is cancelled. + + @param signUpController The signup view controller where signup was cancelled. + */ +- (void)signUpViewControllerDidCancelSignUp:(PFSignUpViewController *)signUpController; + +@end + +PFUI_ASSUME_NONNULL_END diff --git a/ParseUI.framework/Headers/PFTableViewCell.h b/ParseUI.framework/Headers/PFTableViewCell.h new file mode 100644 index 0000000..9238d99 --- /dev/null +++ b/ParseUI.framework/Headers/PFTableViewCell.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2014, Parse, LLC. All rights reserved. + * + * You are hereby granted a non-exclusive, worldwide, royalty-free license to use, + * copy, modify, and distribute this software in source code or binary form for use + * in connection with the web services and APIs provided by Parse. + * + * As with any software that integrates with the Parse platform, your use of + * this software is subject to the Parse Terms of Service + * [https://www.parse.com/about/terms]. This copyright notice shall be + * included in all copies or substantial portions of the software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#import + +#import +#import + +PFUI_ASSUME_NONNULL_BEGIN + +/*! + The `PFTableViewCell` class represents a table view cell which can download and display remote images stored on Parse. + + When used in a - downloading and displaying of the remote images + are automatically managed by the . + */ +@interface PFTableViewCell : UITableViewCell + +/*! + @abstract The imageView of the table view cell. + + @see PFImageView + */ +@property (PFUI_NULLABLE_PROPERTY nonatomic, strong, readonly) PFImageView *imageView; + +@end + +PFUI_ASSUME_NONNULL_END diff --git a/ParseUI.framework/Headers/PFTextField.h b/ParseUI.framework/Headers/PFTextField.h new file mode 100644 index 0000000..5bfb168 --- /dev/null +++ b/ParseUI.framework/Headers/PFTextField.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2014, Parse, LLC. All rights reserved. + * + * You are hereby granted a non-exclusive, worldwide, royalty-free license to use, + * copy, modify, and distribute this software in source code or binary form for use + * in connection with the web services and APIs provided by Parse. + * + * As with any software that integrates with the Parse platform, your use of + * this software is subject to the Parse Terms of Service + * [https://www.parse.com/about/terms]. This copyright notice shall be + * included in all copies or substantial portions of the software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#import + +#import + +PFUI_ASSUME_NONNULL_BEGIN + +/*! + `PFTextFieldSeparatorStyle` bitmask specifies the style of the separators, + that should be used for a given `PFTextField`. + + @see PFTextField + */ +typedef NS_OPTIONS(uint8_t, PFTextFieldSeparatorStyle){ + /*! No separators are visible. */ + PFTextFieldSeparatorStyleNone = 0, + /*! Separator on top of the text field. */ + PFTextFieldSeparatorStyleTop = 1 << 0, + /*! Separator at the bottom of the text field. */ + PFTextFieldSeparatorStyleBottom = 1 << 1 +}; + +/*! + `PFTextField` class serves as a stylable subclass of `UITextField`. + It includes styles that are specific to `ParseUI` framework and allows advanced customization. + */ +@interface PFTextField : UITextField + +/*! + @abstract Separator style bitmask that should be applied to this textfield. + + @discussion Default: + + @see PFTextFieldSeparatorStyle + */ +@property (nonatomic, assign) PFTextFieldSeparatorStyle separatorStyle; + +/*! + @abstract Color that should be used for the separators, if they are visible. + + @discussion Default: `227,227,227,1.0`. + */ +@property (PFUI_NULLABLE_PROPERTY nonatomic, strong) UIColor *separatorColor UI_APPEARANCE_SELECTOR; + +/*! + This method is a convenience initializer that sets both `frame` and `separatorStyle` for an instance of `PFTextField.` + + @param frame The frame rectangle for the view, measured in points. + @param separatorStyle Initial separator style to use. + + @return An initialized instance of `PFTextField` or `nil` if it couldn't be created. + */ +- (instancetype)initWithFrame:(CGRect)frame separatorStyle:(PFTextFieldSeparatorStyle)separatorStyle; + +@end + +PFUI_ASSUME_NONNULL_END diff --git a/ParseUI.framework/Headers/ParseUI.h b/ParseUI.framework/Headers/ParseUI.h new file mode 100644 index 0000000..788a4b0 --- /dev/null +++ b/ParseUI.framework/Headers/ParseUI.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2014, Parse, LLC. All rights reserved. + * + * You are hereby granted a non-exclusive, worldwide, royalty-free license to use, + * copy, modify, and distribute this software in source code or binary form for use + * in connection with the web services and APIs provided by Parse. + * + * As with any software that integrates with the Parse platform, your use of + * this software is subject to the Parse Terms of Service + * [https://www.parse.com/about/terms]. This copyright notice shall be + * included in all copies or substantial portions of the software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import diff --git a/ParseUI.framework/Headers/ParseUIConstants.h b/ParseUI.framework/Headers/ParseUIConstants.h new file mode 100644 index 0000000..19cfa1d --- /dev/null +++ b/ParseUI.framework/Headers/ParseUIConstants.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2014, Parse, LLC. All rights reserved. + * + * You are hereby granted a non-exclusive, worldwide, royalty-free license to use, + * copy, modify, and distribute this software in source code or binary form for use + * in connection with the web services and APIs provided by Parse. + * + * As with any software that integrates with the Parse platform, your use of + * this software is subject to the Parse Terms of Service + * [https://www.parse.com/about/terms]. This copyright notice shall be + * included in all copies or substantial portions of the software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#import +#import + +#ifndef ParseUI_ParseUIConstants_h +#define ParseUI_ParseUIConstants_h + +///-------------------------------------- +/// @name Deprecated Macros +///-------------------------------------- + +#ifndef PARSE_UI_DEPRECATED +# ifdef __deprecated_msg +# define PARSE_UI_DEPRECATED(_MSG) (deprecated(_MSG)) +# else +# ifdef __deprecated +# define PARSE_UI_DEPRECATED(_MSG) (deprecated) +# else +# define PARSE_UI_DEPRECATED(_MSG) +# endif +# endif +#endif + +///-------------------------------------- +/// @name Nullability Support +///-------------------------------------- + +#if __has_feature(nullability) +# define PFUI_NULLABLE nullable +# define PFUI_NULLABLE_S __nullable +# define PFUI_NULL_UNSPECIFIED null_unspecified +# define PFUI_NULLABLE_PROPERTY nullable, +#else +# define PFUI_NULLABLE +# define PFUI_NULLABLE_S +# define PFUI_NULL_UNSPECIFIED +# define PFUI_NULLABLE_PROPERTY +#endif + +#if __has_feature(assume_nonnull) +# ifdef NS_ASSUME_NONNULL_BEGIN +# define PFUI_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN +# else +# define PFUI_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin") +# endif +# ifdef NS_ASSUME_NONNULL_END +# define PFUI_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END +# else +# define PFUI_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end") +# endif +#else +# define PFUI_ASSUME_NONNULL_BEGIN +# define PFUI_ASSUME_NONNULL_END +#endif + +#endif diff --git a/ParseUI.framework/Info.plist b/ParseUI.framework/Info.plist new file mode 100644 index 0000000..293765f Binary files /dev/null and b/ParseUI.framework/Info.plist differ diff --git a/ParseUI.framework/Modules/module.modulemap b/ParseUI.framework/Modules/module.modulemap new file mode 100644 index 0000000..8bcc6b9 --- /dev/null +++ b/ParseUI.framework/Modules/module.modulemap @@ -0,0 +1,6 @@ +framework module ParseUI { + umbrella header "ParseUI.h" + + export * + module * { export * } +} diff --git a/ParseUI.framework/ParseUI b/ParseUI.framework/ParseUI new file mode 100644 index 0000000..56b7cc2 Binary files /dev/null and b/ParseUI.framework/ParseUI differ