NOTE: This version of the SDK is under development.
This repo contains the HCHotelsPriceFreeze framework which can be added to your iOS project via CocoaPods or manually.
- Install CocoaPods on your Mac
- Open Terminal
- In Terminal navigate to your Xcode project root directory, where your
.xcodeproj
file lives, and type:pod init
- Open the newly created Podfile
- In the Podfile below the line
use_frameworks!
add:pod 'HCHotelsPriceFreezeSDK'
- Save your Podfile
- In Terminal in your Xcode project root directory type:
pod install
for Intel machines, orarch -x86_64 pod install
for Apple Silicon machines - Close any open Xcode windows and open up the newly created
.xcworkspace
file - Where you'd like to use the SDK in the Xcode project type
import HCHotelsPriceFreeze
at the top of your Swift file.
If you're having issues installing CocoaPods, or for a more detailed walkthrough of installing CocoaPods, check out this Stack Overflow post.
- Download this repo
- Unzip the zip file
- Drag the HCHotelsPriceFreeze.xcframework into your Xcode project
- Open Terminal
- In Terminal navigate to your Xcode project root directory
- In Terminal run
pod update HCHotelsPriceFreezeSDK
NOTE: This version of the SDK is under development.
Below is a summary of usage, see each class and method for additional documentation.
Access the SDK using an ObservedObject
and call configure()
before making requests.
import HCHotelsPriceFreeze
import SwiftUI
struct ContentView: View {
@ObservedObject var sdk = HCHotelsPriceFreezeSDK.shared
init() {
sdk.configure(with: "your_hopper_token",
environmentType: .staging)
}
var body: some View {
HCPriceFreezeButtonWrapper(roomDetails: roomDetails,
purchaseCallback: { } )
{ offer, onClick in
Button("Freeze Price") { } // This is your SwiftUI Button
}
}
}
Let's say you have a SwiftUI Button that represents your Price Freeze button:
// Within your SwiftUI View
Button("Price Freeze") { } // This is your SwiftUI Button
You can wrap your button with HCPriceFreezeButtonWrapper
:
// Within your SwiftUI View
HCPriceFreezeButtonWrapper(roomDetails: roomDetails,
purchaseCallback: {})
{ offer, onClick in
Button("Price Freeze") { } // This is your SwiftUI Button
}
The PriceFreezeButtonWrapper
will handle fetching, caching, expiring, managing offer state, and will provide you with the current HCPriceFreezeOffer
to render how you wish.
The HCPriceFreezeOffer
will be in one of a few possible states:
- loading
- available
- unavailable
- error
You can use this status to decide how/if to render your button, for example if you only want to render it when there is an available offer:
// Within your SwiftUI View
HCPriceFreezeButtonWrapper(roomDetails: roomDetails,
purchaseCallback: {})
{ offer, onClick in
if offer.state == .available {
Button("Price Freeze") { } // This is your SwiftUI Button
}
}
The wrapper will always and first provide the currently known HCPriceFreezeOffer
state, and then again anytime the offer state changes.
If an offer for this room has not yet been calculated, the HCPriceFreezeOffer
will have a loading HCPriceFreezeOfferState
. As soon as an HCPriceFreezeOffer
is calculated the wrapper will provide the updated HCPriceFreezeOffer
, for example an offer in the available HCPriceFreezeOfferState
.
If the offer has already been determined, you will have access to the calculated HCPriceFreezeOffer
.
To calculate offers for rooms ahead of time, use the following method:
sdk.cacheOffers(for: rooms) // Where `rooms` is an array of `HCRoomDetails` to preload
This will start calculating the offers in the background so the PriceFreezeButtonWrapper
will have a result immediately or sooner.
To observe the offer state for a given room ahead of time, use the following method:
sdk.subscribeTo(roomDetails: roomDetails) { // Where `roomroomDetails` is of `HCRoomDetails` which you would like to observe
newState in
switch newState {
case .loading:
print("Offer for room is being calculated")
case .available:
print("Offer for room is now available")
case .unavailable:
print("No offer is available for room")
case .error(let error):
print("Error encountered for room Error: \(error)")
}
}
To cancel the subscription to all the subscribed rooms using above method, use the following method:
sdk.cancelAllSubscriptions()
To start the purchase flow for an offer, invoke the onClick
function provided:
// Within your SwiftUI View
HCPriceFreezeButtonWrapper(roomDetails: roomDetails,
purchaseCallback: {})
{ offer, onClick in
if offer.state == .available {
Button("Price Freeze") { onClick() } // This is your SwiftUI Button
}
}
This will trigger the purchase flow to be launched for the user.
The HCPriceFreezeButtonWrapper
accepts a purchaseCallback
which allows you to take action depending on the outcome of the purchase flow.
HCPriceFreezeButtonWrapper(roomDetails: roomDetails,
purchaseCallback: { purchaseResult in
switch purchaseResult {
case .purchased(let offer): // The user purchased the PF
print("Price Freeze Purchased!")
print("Offer ID: \(offer.id)")
print("Offer Conditions: \(offer.conditions)")
print("Offer frozenPrice: \(offer.conditions.frozenPrice)")
print("Offer cap: \(offer.conditions.cap)")
case .cancelled(let offer, let whileLoading): // The user exited the purchase flow without purchasing
print("Price Freeze purchase flow cancelled")
print("while it was loading: \(whileLoading)")
print("Offer ID: \(offer.id)")
default: // Other purchaseResult outcomes
print("Error/Invalid purchaseResult: \(purchaseResult)")
}
}
)
{ offer, onClick in
if offer.state == .available {
Button("Price Freeze") { } // This is your SwiftUI Button
}
}
- Xcode 14 has a known issue when running code that utilizes
WKWebView
s. You may notice an Xcode warning, displayed as a purple exclamation point, when interacting with the price freeze purchase microsite. The warning will stateSecurity: This method should not be called on the main thread as it may lead to UI unresponsiveness
. (Apple's Developer Technical Support addressed the issue)[https://developer.apple.com/forums/thread/714467?answerId=734799022#734799022] and outlined steps to confirm the warning can be ignored, as we can here.
- Added
AccommodationType
as a new optional parameter forRoom
- Set session lifetime to 4 hours
- Open all microsite links in-app
- Change internal management of Price Freeze Offers to address fetching errors and loading errors
- Change
isRefundable
field onHCRoom
to required
- Added version number to internal logging
- E2E tests added
- Fixed bug that prevented hotel image from displaying on microsite
- Fixed bug that fired internal analytics event early
- Initial functional draft
- Session management added
- Changed offer storage logic
- Logging added
- Debouncing added
- Initial implementation stub, a mockup of the SDK's interface