This guide covers the different aspects of Booking in the MapsIndoors iOS SDK. The concept of Booking in MapsIndoors implies that specific Locations in your MapsIndoors dataset is treated as Bookable resources. Typical bookable resources could be meeting rooms and workspaces.
A MapsIndoors dataset can only have bookable resources if an integration with a Booking provider exists. Current examples of Booking providers are Google Calendar and Microsoft Office 365. These providers and more can be added and integrated to your MapsIndoors project by request.
The central service in the SDK managing Bookings is the Booking Service.
MPMapsIndoors.shared.bookingService
The Booking Service can help with the following tasks:
By default, the MPBookingService performs anonymous Bookings using a service account known to MapsIndoors. However, it is also possible to list, perform and cancel Bookings on behalf of a user.
To determine whether or not a Location is bookable can be looked up using the MPMapsIndoors.shared.bookingService. bookableLocationsUsing(query: MPBookableQuery) method. Below is an example of querying for bookable Locations:
The above example creates a query for Locations that are bookable for a timespan between now and 1 hour ahead.
It is also possible to check a location statically using MPLocation.isBookable, but please note that this information is not a dynamic property reflecting the current bookable state from the Booking Service. If MPLocation.isBookable is true it means that the Location has a potentially bookable resource known by the integrated Booking provider, but still it might be booked for a specific time.
It is possible execute a booking creation request using the MPMapsIndoors.shared.bookingService.performBooking(MPBooking) method which takes a booking object as input. If the booking is successfully performed, the booking will return in the block with an assigned bookingId.
In this tutorial we will create a Booking experience using the Booking Service in MapsIndoors. You will learn how to list bookable Locations, list Bookings for a Location and perform new Bookings using the Booking Service, MPBookingService.
Please note that a MapsIndoors dataset can only have bookable resources if an integration with a booking provider exists. Current examples of booking providers are Google Calendar and Microsoft Office 365. These providers, and more, can be added and integrated to your MapsIndoors project by request. It is a prerequisite for this tutorial that the API key used refers to a dataset containing bookable Locations.
In tableView(_:didSelectRowAt:), get the relevant MPLocation for the indexPath. Initialise a BookingsController which we will implement next. Assign the selected Location to a bookableLocation property on BookingsController and push the controller to the navigation stack.
Create a new controller, BookingsController inheriting again from UITableViewController. This controller will list the Bookings for a locations within a timespan, as well as give access to creating new and editing bookings.
classBookingsController:UITableViewController {
Create a public property bookableLocation that will hold the Location we want to book.
var bookableLocation : MPLocation?
Create a private property bookings that can hold the Location's bookings.
privatevar bookings = [MPBooking]()
In your viewDidLoad() method, initialise a UIBarButtonItem with the title Booktargeting newBooking which we will create later. Add the button to the navigationItem.
Also in your viewDidLoad() method, initialise a MPBookingsQuerywith the MPLocation stored in bookableLocation and a timespan, in this example 24 hours starting one hour ago.
let bookingsQuery =MPBookingsQuery()bookingsQuery.location = bookableLocationbookingsQuery.startTime =Date().advanced(by:-60*60)bookingsQuery.endTime = bookingsQuery.startTime?.advanced(by:24*60*60)
Lastly in your viewDidLoad() method, call bookingsUsing(query: bookingsQuery)with the bookingsQuery we just created. Store the returned Bookings in our bookings property.
Create a method editBooking(booking:). In this mehod, initialise a BookingController which we will implement next. Assign the selected booking to the BookingController and push the controller to the navigation stack.
Create an Objective-C exposed method newBooking() which will be use by our UIBarButtonItem created in viewDidLoad(). In the newBooking() mehod, initialise a new MPBooking instance and provide some default values for the Booking. Call the newly created editBooking(booking:) with the Booking instance.
We need a third controller to display, edit and perform an actual Booking.
We will create an enum model to keep track on the different parts of the MPBooking model displayed through the view controller.
enumBookingRow:Int{case title =0case description =1case start =2case end =3case id =4case count =5}
Create BookingController inheriting once again from UITableViewController.
classBookingController:UITableViewController {
Create a public property booking that will hold our Booking.
var booking =MPBooking()
Create a method updateButtons() that will either place a book button if there is no bookingId on the Booking, which means it was created locally, or place a cancel button if a bookingId exist for the Booking, which means it was selected from a list of Bookings fetched from the MPBookingService.
In your viewDidLoad() method, just call the updateButtons() method.
overridefuncviewDidLoad() {updateButtons()}
Create an Objective-C exposed method book() which will be use by our UIBarButtonItem inserted in viewDidLoad(). In the book() mehod, call perform(booking) on the MPBookingService instance with our Booking object as input. If all goes well and we have a Booking returned in the block, we assign this new Booking to our booking propery and refresh our views. If not, we assume that we have an error, and show this in an alert controller.
Create another Objective-C exposed method cancel() which will be use by our UIBarButtonItem inserted in viewDidLoad(). In the cancel() mehod, call cancel(booking) on the MPBookingService instance with our Booking object as input. If all goes well and we have a Booking returned in the block, we assign this new Booking to our booking propery and refresh our views. If not, we assume that we have an error, and show this in an alert controller.
In tableView(:cellForRowAt indexPath:), create a UITableViewCell and create a switch control structure by initialising a BookingRow enum value from indexPath.row. Based on the cases, populate the textLabel with title, bookingDescription, startTime, endTime and bookingId from your MPBooking instance.
In tableView(_:cellForRowAt:), create a switch control structure again by initialising a BookingRow enum value from indexPath.row. Based on the cases, either initialise and present FieldEditController or DatePickerController which we will implement next.
overridefunctableView(_tableView: UITableView, didSelectRowAtindexPath: IndexPath) {weakvar wself = selfswitch BookingRow.init(rawValue: indexPath.row) {case .title:let fieldEditVC =FieldEditController() fieldEditVC.title ="Edit Title" fieldEditVC.beginEdit(initialValue: booking.title) { (value) in wself?.booking.title = value wself?.tableView.reloadData() }present(fieldEditVC, animated:true, completion:nil)case .description:let fieldEditVC =FieldEditController() fieldEditVC.title ="Edit Description" fieldEditVC.beginEdit(initialValue: booking.bookingDescription) { (value) in wself?.booking.bookingDescription = value wself?.tableView.reloadData() }present(fieldEditVC, animated:true, completion:nil)case .start:let dateEditVC =DatePickerController() dateEditVC.title ="Edit Start Date" dateEditVC.beginEdit(initialValue: booking.startTime) { (value) in wself?.booking.startTime = value wself?.tableView.reloadData() }present(dateEditVC, animated:true, completion:nil)case .end:let dateEditVC =DatePickerController() dateEditVC.title ="Edit End Date" dateEditVC.beginEdit(initialValue: booking.endTime) { (value) in wself?.booking.endTime = value wself?.tableView.reloadData() }present(dateEditVC, animated:true, completion:nil)default: () }}
Creating UI for editing text and dates is outside the scope of this tutorial. But since we need it for creating the actual Booking, you are advised to just insert the following 3 controllers into your code.
First a controller EditController for arranging the presented editing view skeleton.
This concludes the tutorial about Booking in the MapsIndoors iOS SDK. Depending on your dataset you should not be far from a working Booking experience where you can list Bookable Locations, list Bookings and create new Bookings.