You have been warned.
Double the Fun
As was pointed out in the last page, we are now receiving two streams of data from one call. Each is delivered to a different callback.
We have a problem, as we have a simple UI (an alert) that is displayed in each callback, but only the first alert is shown. This is because of the way that iOS presents alerts. We need to either display two separate, sequential alerts, or display one alert that has both pieces of data.
The second one is preferable, but the data is delivered in two parts, in two separate callbacks.
We’ll take care of this by storing the results of the first callback, then referring to it in the second.
As the note above says, we are cheating like crazy. We know that the formats callback comes first, will be allowed to complete before the second callback comes and that both callbacks are in the main thread.
So we’ll simply stash the results in the first callback, and present our “twofer” alert in the second callback.
Here’s what we’ll do:
import UIKit import BMLTiOSLib class ViewController : UIViewController, BMLTiOSLibDelegate { var _libraryInstance: BMLTiOSLib! = nil var _formatsResult: [BMLTiOSLibFormatNode] = [] override func viewDidLoad() { super.viewDidLoad() // This is a string that points to a VALID Root Server instance // (>=10.2.8.1 running HTTPS, and with most of its data fields unmodified from default). let rootServerURI = "https://tkddevel.com/bmltwork/bmlt/main_server/" // Create an instance of the class. This immediately begins a communication process with the Root Server, // and the callbacks will be the next course of action. self._libraryInstance = BMLTiOSLib(inRootServerURI: rootServerURI, inDelegate: self) } // These are the required callback functions for the BMLTiOSLibDelegate class. // This is called upon successful connection and querying of the Root Server (or unsuccessful) func bmltLibInstance(_ inLibInstance: BMLTiOSLib, serverIsValid: Bool) { let alertController = UIAlertController(title: (serverIsValid ? "EXCELLENT!" : "BOGUS!"), message: "We're in! Wanna find some meetings?", preferredStyle: .alert) let cancelAction = UIAlertAction(title: "NO", style: UIAlertActionStyle.cancel, handler: nil) alertController.addAction(cancelAction) let findAction = UIAlertAction(title: "YES", style: UIAlertActionStyle.default, handler: {(_:UIAlertAction) in self._libraryInstance.searchCriteria.performMeetingSearch()}) alertController.addAction(findAction) self.present(alertController, animated: true, completion: nil) } // This is called if the BMLTiOSLib suffers an error of some sort. func bmltLibInstance(_ inLibInstance: BMLTiOSLib, errorOccurred error: Error) { let alertController = UIAlertController(title: "ERROR!", message: "\(error)", preferredStyle: .alert) let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.cancel, handler: nil) alertController.addAction(okAction) self.present(alertController, animated: true, completion: nil) } // This is called with the results of a meeting search. func bmltLibInstance(_ inLibInstance: BMLTiOSLib, meetingSearchResults: [BMLTiOSLibMeetingNode]) { let alertController = UIAlertController(title: "w00t!", message: "\(meetingSearchResults.count) meetings, and \(self._formatsResult.count) formats were found!", preferredStyle: .alert) let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.cancel, handler: nil) alertController.addAction(okAction) self.present(alertController, animated: true, completion: nil) } // This is called with the results of a format search. func bmltLibInstance(_ inLibInstance: BMLTiOSLib, formatSearchResults: [BMLTiOSLibFormatNode], isAllUsedFormats: Bool) { self._formatsResult = formatSearchResults } }
Build and run the app. This is what you now get (remember that the numbers may come up differently for you, as we are constantly changing our database):
Here’s what changed:
We added a new property to the class:
var _formatsResult: [BMLTiOSLibFormatNode] = []
This is the temporary “bucket” we’ll use to stash the results of the format call.
We changed the format callback to simply stash the results with no alert:
func bmltLibInstance(_ inLibInstance: BMLTiOSLib, formatSearchResults: [BMLTiOSLibFormatNode], isAllUsedFormats: Bool) { self._formatsResult = formatSearchResults }
We added an access to the count of this result in the alert we display in the meeting results callback:
let alertController = UIAlertController(title: "w00t!", message: "\(meetingSearchResults.count) meetings, and \(self._formatsResult.count) formats were found!", preferredStyle: .alert)
Here’s the fourth (and final) installment of the demo app (Downloads a zip file with an Xcode project). We won’t go farther than this, as it should have given you a fairly good idea of how to deal with the BMLTiOSLib.
Onward and Upward
You should be able to take it from here. There’s plenty of documentation.
In particular, the BMLTiOSLib class has a great many properties that describe the state of the server, and the BMLTiOSLibSearchCriteria class is the “heart” of the search. The BMLTiOSLib instance “owns” an instance of BMLTiOSLibSearchCriteria that you access via the “.searchCriteria” property.
In order to do a search, you acquire the searchCriteria object, and set it up with the various criteria it provides. You then exercise its performMeetingSearch(_:) method, which will trigger the two callbacks (or just one, depending on the parameter you give to performMeetingSearch) we discussed.
Several of the search criteria can have a “three-state” condition, this is “not selected or deselected” (We call this “clear”), “selected” (This means we are specifically looking for meetings that MATCH this criteria) and “deselected” (This means we are specifically looking for meetings that DON’T MATCH the criteria).
You use this enum type to manage this state.
For administration, you log in, via the BMLTiOSLib adminLogin(loginID:,password:) method. The login will remain in effect for the lifetime of the BMLTiOSLib object, or until you call the BMLTiOSLib adminLogout() method.
While the instance is logged in, you can call the various admin methods:
- permissions(forServiceBody:)
- saveMeetingChanges(_:) (You make changes by altering an editable meeting node)
- rollbackMeeting(_:,toBeforeChange:)
- deleteMeeting(_:)
- restoreDeletedMeeting(_:)
- Other Topics
- An Illustration of the BMLT System
- BMLT Roles
- Is Your Server Set Up Correctly?
- Test Site Links
- The BMLT Satellite Base Class
- The BMLTiOSLib iOS Framework
- BMLTiOSLib Technical Overview
- Adding the BMLTiOSLib to Your Project
- Being A Responsible Delegate
- Our First Search
- Doubling Down on the Data
- Configuration Management And Release