- iOS Example
If you are getting started with Swift and iOS development you should be able to use this guide, although this guide is recommended for those familiar with iOS development and the Swift language. This is a simplified guide to integrate the XYO Core Swift SDK.
For the source code refer to this link
- Swift with Xcode and Cocoapods
Click here for an introduction to integrate a new Xcode project with CocoaPods
Versions used in this sample
- XCode
10.3
- Swift
5.0.1
It is important to set up this project with CocoaPods so you can use dependencies to build the app
When creating the configuration for the emulator, we recommend using a mid-range device definition for a wider range of coverage for iOS devices. (Such as a iPhone XR) feel free to use whatever example iOS device you would like.
This Sample App Example is best for mobile devices since bound witnessing is optimal on mobile. Integration into your application should be based on a mobile app architecture.
For the podfile, we will go ahead and use the latest sdk-core-swift
target 'MyApp' do
pod 'sdk-core-swift', '3.0'
end
Then run a pod install
from your terminal
Once the pod installation is complete we open the workspace
open MyApp.xcworkspace
You should now see your Xcode workspace
All of our work will be in the ViewController.swift
file
For this integration guide we will do our work in the view controller.
Go here for the source code of the complete project
We want to start by importing our core_swift
and objectmodel
SDKs
import sdk_core_swift
import sdk_objectmodel_swift
We should see the following in our ViewController.swift
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
}
In order for us to do a bound witness we need some objects and interfaces
class ViewController: UIViewController {
private let hasher = XyoSha256()
private let store = XyoInMemoryStorage()
private lazy var state = XyoStorageOriginStateRepository(storage: store)
private lazy var blocks = XyoStorageProviderOriginBlockRepository(storageProvider: store, hasher: hasher)
private lazy var conf = XyoRepositoryConfiguration(originState: state, originBlock: blocks)
private lazy var node = XyoOriginChainCreator(hasher: hasher, repositoryConfiguration: conf)
}
Let us add an extension to our ViewController
to get the node listener that we'll need to display the hash representation of our bound witness
extension ViewController : XyoNodeListener {
// the library will bring some of these functions in, but we won't need most of them
func onBoundWitnessStart() {}
func onBoundWitnessEndFailure() {}
func onBoundWitnessDiscovered(boundWitness: XyoBoundWitness) {}
// this is where we bring in and display our bound witness
func onBoundWitnessEndSuccess(boundWitness: XyoBoundWitness) {
let hash = (try? boundWitness.getHash(hasher: hasher))?.getBuffer().toByteArray().toHexString()
}
}
Before we can actually display the hash we need to set up the UI
Let's create the bound witness text to display, we will use the UILabel
view class
private lazy var doBoundWitness: UILabel = {
let text = UILabel()
text.textColor = UIColor.black
text.font = UIFont.systemFont(ofSize: 20, weight: .black)
text.numberOfLines = 0
return text
}()
We can now set the text in our listener which will be the hash
func onBoundWitnessEndSuccess(boundWitness: XyoBoundWitness) {
let hash = (try? boundWitness.getHash(hasher: hasher))?.getBuffer().toByteArray().toHexString()
doBoundWitness.text = hash
}
In order for us to call the listener and get our hash, we need to create a button, we will use the UIButton
class
private lazy var doBoundWitnessButton: UIButton = {
let button = UIButton(type: UIButton.ButtonType.roundedRect)
button.setTitle("Create Origin", for: UIControl.State.normal)
return button
}()
Add logic to the button
private func layoutButton () {
view.addSubview(doBoundWitnessButton)
doBoundWitnessButton.translatesAutoresizingMaskIntoConstraints = false
doBoundWitnessButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
doBoundWitnessButton.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
let click = UITapGestureRecognizer(target: self, action: #selector(onButtonClick(_:)))
doBoundWitnessButton.addGestureRecognizer(click)
}
Add interactivity to the button
@objc func onButtonClick (_ sender: UITapGestureRecognizer) {
// error check without crashing
try? node.selfSignOriginChain()
}
Now we have a button to activate the listener and display a bound witness hash on our primary view.
Before setting up the entire layout, let's create a title
private lazy var appTitle: UILabel = {
let text = UILabel()
text.textColor = UIColor.purple
text.font = UIFont.systemFont(ofSize: 20, weight: .black)
text.numberOfLines = 0
return text
}()
We should create a layout where we can have our viewDidLoad()
function call for what text and interactivity we want on this simple app
private func layout() {
// bring in a title
appTitle.text = "Sample XYO App"
view.addSubView(appTitle)
view.addSubView(doBoundWitness)
appTitle.translatesAutoresizingMaskIntoConstraints = false
appTitle.topAnchor.constraint(equalTo: view.topAnchor, constant: 150).isActive = true
appTitle.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
doBoundWitness.translatesAutoresizingMaskIntoConstraints = false
doBoundWitness.bottomAnchor.constraint(equalTo: doBoundWitnessButton.topAnchor, constant: -80).isActive = true
}
Now we can include the layouts in our primary view
override func viewDidLoad() {
super.viewDidLoad()
node.addListener(key: "main", listener: self)
layout()
layoutButton()
}
Once you update the viewDidLoad()
, your code should currently look like this
import UIKit
import sdk_core_swift
import sdk_objectmodel_swift
class ViewController: UIViewController {
private let locationManager = CLLocationManager()
private let hasher = XyoSha256()
private let store = XyoInMemoryStorage()
private lazy var state = XyoStorageOriginStateRepository(storage: store)
private lazy var blocks = XyoStorageProviderOriginBlockRepository(storageProvider: store, hasher: hasher)
private lazy var conf = XyoRepositoryConfiguration(originState: state, originBlock: blocks)
private lazy var node = XyoOriginChainCreator(hasher: hasher, repositoryConfiguration: conf)
private lazy var doBoundWitnessButton: UIButton = {
let button = UIButton(type: UIButton.ButtonType.roundedRect)
button.setTitle("Create Origin", for: UIControl.State.normal)
return button
}()
private lazy var doBoundWitness: UILabel = {
let text = UILabel()
text.textColor = UIColor.black
text.font = UIFont.systemFont(ofSize: 20, weight: .black)
text.numberOfLines = 0
return text
}()
private lazy var appTitle: UILabel = {
let text = UILabel()
text.textColor = UIColor.purple
text.font = UIFont.systemFont(ofSize: 20, weight: .black)
text.numberOfLines = 0
return text
}()
override func viewDidLoad() {
super.viewDidLoad()
node.addListener(key: "main", listener: self)
layout()
layoutButton()
}
private func layout () {
appTitle.text = "Sample XYO App"
view.addSubview(appTitle)
view.addSubview(doBoundWitness)
appTitle.translatesAutoresizingMaskIntoConstraints = false
appTitle.topAnchor.constraint(equalTo: view.topAnchor, constant: 150).isActive = true
appTitle.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
doBoundWitness.translatesAutoresizingMaskIntoConstraints = false
doBoundWitness.bottomAnchor.constraint(equalTo: doBoundWitnessButton.topAnchor, constant: -80).isActive = true
doBoundWitness.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
doBoundWitness.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -80).isActive = true
}
private func layoutButton () {
view.addSubview(doBoundWitnessButton)
doBoundWitnessButton.translatesAutoresizingMaskIntoConstraints = false
doBoundWitnessButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
doBoundWitnessButton.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
let click = UITapGestureRecognizer(target: self, action: #selector(onButtonClick(_:)))
doBoundWitnessButton.addGestureRecognizer(click)
}
@objc func onButtonClick (_ sender: UITapGestureRecognizer) {
try? node.selfSignOriginChain()
}
}
extension ViewController : XyoNodeListener {
// not needed
func onBoundWitnessStart() {}
func onBoundWitnessEndFailure() {}
func onBoundWitnessDiscovered(boundWitness: XyoBoundWitness) {}
func onBoundWitnessEndSuccess(boundWitness: XyoBoundWitness) {
let hash = (try? boundWitness.getHash(hasher: hasher))?.getBuffer().toByteArray().toHexString()
doBoundWitness.text = hash
}
}
}
Go ahead and save the project and run the build by clicking on the play button on the top left hand side of the Xcode IDE
You should now see the Create Origin
button and when you tap it you should see a response on the screen with the hash value of the newly created bound witness chain. You can tap again for another bound witness chain.
Let's keep going. We want to add a heuristic and see what heuristic we are adding. We'll add a GPS location to our bound witness chain.
Let's start by briging in the Swift location manager in the first line of the ViewController
class.
private let locationManager = CLLocationManager()
We should create a new text field to be ready for the location information that we want the user to see. That way the user knows what the heuristic we are adding to the origin chain.
private lazy var doLocation: UILabel = {
let text = UILabel()
text.textColor = UIColor.red
text.font = UIFont.systemFont(ofSize: 13, weight: .black)
return text
}()
We should add permissions.
In viewDidLoad()
locationManager.requestWhenInUseAuthorization()
Now we can add an extension to add the location heuristic. You can look at the primary readme guide for an example of the getHeuristic
method.
Now let's create a new extension for the getter
extension ViewController : XyoHeuristicGetter {
func getHeuristic() -> XyoObjectStructure? {
guard let lat: Double = locationManager.location?.coordinate.latitude else {
return nil
}
guard let lng: Double = locationManager.location?.coordinate.longitude else {
return nil
}
doLocation.text = "\(lat), \(lng)"
let encodedLat = XyoObjectStructure.newInstance(schema: XyoSchemas.LAT, bytes: XyoBuffer(data: anyToBytes(lat)))
let encodedLng = XyoObjectStructure.newInstance(schema: XyoSchemas.LNG, bytes: XyoBuffer(data: anyToBytes(lng)))
return XyoIterableStructure.createUntypedIterableObject(schema: XyoSchemas.GPS, values: [encodedLat, encodedLng])
}
func anyToBytes<T>(_ value: T) -> [UInt8] {
var value = value
return withUnsafeBytes(of: &value) { Array($0) }.reversed()
}
}
Once we get the user's permission, we get the last known location if there is one, then we encode the location coordinates before we create a new XyoObjectStructure
for the heuristic to be compatible with our origin chain object.
We also add a doLocation.text
to print out the non-encoded location coordinates so that the user can see a human readable version of the location that is added to the origin chain.
Once we have the resolver set, we can plug it into the addHeuristic
method to the view loader
viewDidLoad()
override fun onCreate(savedInstanceState: Bundle?) {
...
node.addHeuristic(key: "gps", getter: self)
}
We then should enable updating location
locationManager.startUpdatingLocation()
The viewDidLoad()
should look like this when we are done
override func viewDidLoad() {
super.viewDidLoad()
locationManager.requestWhenInUseAuthorization()
node.addListener(key: "main", listener: self)
node.addHeuristic(key: "gps", getter: self)
locationManager.startUpdatingLocation()
layoutButton()
layout()
}
Now we can add our doLocation
view to our Layout
private func layout () {
...
view.addSubview(doLocation)
doLocation.translatesAutoresizingMaskIntoConstraints = false
doLocation.bottomAnchor.constraint(equalTo: doBoundWitnessButton.topAnchor, constant: 100).isActive = true
doLocation.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
}
Now rebuild and run the app.
When you tap or click (in a simulator) the create origin
button, you should see the GPS coordinate appear right before the hash.
You have now created an origin chain and added the gps heuristic to the origin chain.
Made with 🔥and ❄️ by XY - The Persistent Company