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
.xcodeprojfile 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 installfor Intel machines, orarch -x86_64 pod installfor Apple Silicon machines - Close any open Xcode windows and open up the newly created
.xcworkspacefile - Where you'd like to use the SDK in the Xcode project type
import HCHotelsPriceFreezeat 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 ButtonYou 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 preloadThis 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
WKWebViews. 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
AccommodationTypeas 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
isRefundablefield onHCRoomto 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