In this article:

Resuming Table Data Loading to Database

Resuming Table Data Loading without Loading to Database

Resuming Resource Downloading in Uniform Request to Resource

Resuming Resource Downloading

The mobile application allows for setting up parameters of resuming resource downloading with saving of downloading status:

If resource downloading has failed or mobile platform server connection is lost, the mobile application keeps requesting resource.

Resuming Table Data Loading to Database

To get table data with loading to database, create the HHFWTableStreamRetry application, which uses framework methods:

Method name Brief description
initWithCredentials (_: host: environment: project: device:) The method initializes the framework.
setDownloadPath(_:) The method sets path to the folder in the mobile application directory, which will store download resumption files.
auth (_: password:) The method authenticates the user by login and password.
openBase (_: key:) The method opens connection with database at the specified path.
resources (_: password: handler:) The method gets schemes of available resources and automatically creates corresponding tables in the database.
useDownload(_:) The method enables or disables resuming resource downloading.
tableStream (_: withCache: transactionID: tableCallParams: handler:) The method loads table data to local database.
getTablesName (_: resourceName: requestParams: tableName:) The method returns table name in local database.
query (_: query:) The method sends SQL query to local database.

Auxiliary methods:

Method name Brief description
getURL (for:) The method returns URL for the file with the specified name in the Documents folder.
Type of returned data: URL.
getRecords (from:) The method returns value of the "records" key from JSON result of SQL query to local database.
Type of returned data: [[String: Any]]?
getTableNames (from:) The method returns the array of values for "name" keys from results of the getRecords method
Type of returned data: [String].
parseServerJSONResponse (json:) The method returns the result of converting JSON string into a dictionary.
Type of returned data: [String: Any]?
getResponseStatus (from:) The method returns value for the "status" key from JSON result of the query.
Type of returned data: String?
getTableNamesInDatabase (_: forResource: originalTableName:) The method returns the array of table names that satisfy the specified parameters: database location in application directory, resource name and searched table name.
Type of returned data: [String].

To set the number of repetitionsens and interval between them, use the retryCount and retryIntervalSec properties of instance of the TableCallParams class that is sent as a parameter to the table method.

The HHFWTableStreamRetry application includes one screen, the UITextView text view, and UIButton buttons:

NOTE. When the application is initialized, authentication is executed, the buttons are not available. If the authentication is executed successfully, the buttons are available, and the text box displays the text "Authentication and resources load success".

To execute the example:

  1. Click the Perform TableStream button.

Clicking the button requests table data for the specified resource. Query execution result is automatically written to local database.

  1. Click the Perform SELECT button.

Clicking the button executes the SQL query SELECT * FROM table_name to local database.

Application code:

import UIKit
 
class ViewController: UIViewController {
 
    // Determine output data
    @IBOutlet weak var resultTextView: UITextView!
    @IBOutlet weak var tableStreamButton: UIButton!
    @IBOutlet weak var queryButton: UIButton!
 
    // Redetermine method
    override func viewDidLoad() {
        super.viewDidLoad()
        self.deactivateButtons()
        self.initializeFramework()
        self.auth {
            let databaseName = "database.sqlite"
            if self.openDatabase(databaseName) {
                self.loadResourcesScheme(databaseName) {
                    self.activateButtons()
                    self.resultTextView.text = "Authentication and load resources success"
                }
            }
        }
    }
 
    // Set method that will be executed on button click
    @IBAction func tableStreamPressed(_ sender: UIButton) {
        let databaseName = "database.sqlite"
        self.loadTable(databaseName) { (jsonResult) in
            self.resultTextView.text = String(format: "%@", jsonResult)
        }
    }
 
    @IBAction func selectFromTablePressed(_ sender: Any?) {
        let databaseName = "database.sqlite"
        self.performSelect(databaseName, completion: { (jsonResult) in
            self.resultTextView.text = jsonResult
        })
    }
 
    // Initialize framework
    private func initializeFramework() {
        let apiVersion: String = "v1"
        let host: String = "http://testmasterfmp.fsight.cloud/"
        let environment: String = "DocumentationExampleEnv"
        let project: String = "DocumentationExampleProj"
        let device: String = (UIDevice.current.identifierForVendor?.uuidString)!
        HHFWController.sharedInstance().initWithCredentials(
            apiVersion,
            host: host,
            environment: environment,
            project: project,
            device: device
        )
        let fileFolderPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).paths[0].appendingPathComponent("FilesForDownload", isDirectory: true).path
        HHFWController.sharedInstance().setDownloadPath(fileFolderPath)
    }
 
    // Authenticate
    private func auth(completion: @escaping ()->()) {
        let username: String = "test"
        let password: String = "test123"
        HHFWController.sharedInstance().auth(username, password: password){ (jsonResult) in
            if let jsonDict = jsonResult as? NSDictionary,
                let status = jsonDict["status"] as? String, status == "ok" {
                print("Auth success")
                completion()
            } else {
                print("Auth error")
            }
        }
    }
 
    // Open or create a database
    private func openDatabase(_ databaseName: String) -> Bool {
        let fullDatabaseURL = self.getURL(for: databaseName)
        return HHFWController.sharedInstance().openBase(fullDatabaseURL.path, key: "")
    }
 
    // Load resources scheme
    private func loadResourcesScheme(_ databaseName: String, completion: @escaping ()->()) {
        HHFWController.sharedInstance().resources(databaseName, password: "") { (jsonResult) in
            if let jsonDict = jsonResult as? NSDictionary,
                let status = jsonDict["status"] as? String, status == "ok" {
                print("Load resources success")
                completion()
            } else {
                print("Load resources error")
            }
        }
    }
 
    // Perform the TableStream request
    private func loadTable(_ databaseName: String, completion: @escaping (NSDictionary)->()) {
        let resourceName = "FRUITS"
        let requestCallParams = RequestCallParams(defaultDb: ())
        let fullDatabaseURL = self.getURL(for: databaseName)
        requestCallParams?.dataBasePath = fullDatabaseURL.path
        requestCallParams?.retryCount = 10
        requestCallParams?.retryIntervalSec = 1
        HHFWController.sharedInstance().useDownload(true)
        HHFWController.sharedInstance().tableStream(resourceName, withCache: true, transactionID: nil, tableCallParams: requestCallParams) { (jsonResult) in
            if let jsonDict = jsonResult as? NSDictionary,
                let status = jsonDict["status"] as? String, status == "ok" {
                print("Load table success")
                completion(jsonDict)
            } else {
                print("Load table error")
            }
        }
        HHFWController.sharedInstance().useDownload(false)
    }
 
    // Perform the SELECT * FROM table request
    private func performSelect(_ databaseName: String, completion: (String?) -> ()) {
        let resourceName = "FRUITS"
        let tableName = "output_table"
        if let databaseTableName = self.getTableNamesInDatabase(databaseName, forResource: resourceName, originalTableName: tableName).first {
            let query = "SELECT * FROM `\(databaseTableName)`"
            let jsonResult = HHFWController.sharedInstance().query("/Documents/\(databaseName)", query: query)
            completion(jsonResult)
        }
    }
 
    // Get table names in local database
    private func getTableNamesInDatabase(_ databaseName: String, forResource resourceName: String, originalTableName tableName: String) -> [String] {
        let tableNames = HHFWController.sharedInstance().getTablesName("/Documents/\(databaseName)", resourceName: resourceName, requestParams: "", tableName: tableName)
        return self.getTableNames(from: tableNames)
    }
 
    // Set methods to display application user interface elements
    private func deactivateButtons() {
        self.tableStreamButton.isEnabled = false
        self.queryButton.isEnabled = false
    }
 
    private func activateButtons() {
        self.tableStreamButton.isEnabled = true
        self.queryButton.isEnabled = true
    }
 
    // Call auxiliary classes
    private func getURL(for fileName: String) -> URL {
        let paths: [URL] = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
        let fileURL: URL = paths[0].appendingPathComponent(fileName)
        return fileURL
    }
 
    private func getRecords(from json: String?) -> [[String: Any]]? {
        var resultRecords: [[String: Any]]? = nil
        if let jsonString = json {
            let jsonDict = parseServerJSONResponse(json: jsonString)
            if self.getResponseStatus(from: jsonDict) == "ok" {
                if let result = jsonDict?["result"] as? [String: Any],
                    let database = result["database"] as? [String:Any],
                    let records = database["records"] as? [[String: Any]] {
                    resultRecords = records
                }
            }
        }
        return resultRecords
    }
 
    private func getTableNames(from json: String?) -> [String] {
        var resultTableNames: [String] = []
        if let records = getRecords(from: json) {
            for record in records {
                if let tableName = record["name"] as? String {
                    resultTableNames.append(tableName)
                }
            }
        }
        return resultTableNames
    }
 
    private func parseServerJSONResponse(json: String) -> [String: Any]? {
        guard let responseData = json.data(using: .utf8) else { return nil }
        return try? JSONSerialization.jsonObject(with: responseData, options: []) as! [String: Any]
    }
 
    func getResponseStatus(from json: [String: Any]?) -> String? {
        return json?["status"] as? String
    }
}

Resuming Table Data Loading without Loading to Database

To get table data without loading to database, create the HHFWTableRetry application, which uses framework methods:

Method name Brief description
initWithCredentials (_: host: environment: project: device:) The method initializes the framework.
auth (_: password:) The method authenticates the user by login and password.
table (_: transactionID: tableCallParams: handler:) The method returns resource table data without loading to database.

To set the number of repetitions and interval between them, use the retryCount and retryIntervalSec properties of instance of the TableCallParams class that is sent as a parameter to the table method.

The HHFWTableRetry application includes one screen, the UITextView text view, and the UIButton button:

NOTE. When the application is initialized, authentication is executed, the button is not available. If the authentication is executed successfully, the button is available, and the text box displays the text "Authentication success".

To execute the example, click the Request Table button. Clicking the button initializes a request to resource. A mobile platform server returns corresponding table data without loading to database.

Application code:

import UIKit
 
class ViewController: UIViewController {
 
    // Determine output data
    @IBOutlet weak var resultTextView: UITextView!
    @IBOutlet weak var tableRequestButton: UIButton!
 
    // Redetermine method
    override func viewDidLoad() {
        super.viewDidLoad()
        self.deactivateButtons()
        self.initializeFramework()
        self.auth {
            self.activateButtons()
            self.resultTextView.text = "Authentication success"
        }
    }
 
    // Set method that will be executed on button click
    @IBAction func tableRequestPressed(_ sender: UIButton) {
        self.tableRequest { (jsonResult) in
            self.resultTextView.text = String(format: "%@", jsonResult)
        }
    }
 
    // Initialize framework
    private func initializeFramework() {
        let apiVersion: String = "v1"
        let host: String = "http://testmasterfmp.fsight.cloud/"
        let environment: String = "DocumentationExampleEnv"
        let project: String = "DocumentationExampleProj"
        let device: String = (UIDevice.current.identifierForVendor?.uuidString)!
        HHFWController.sharedInstance().initWithCredentials(
            apiVersion,
            host: host,
            environment: environment,
            project: project,
            device: device
        )
    }
 
    // Authenticate
    private func auth(completion: @escaping ()->()) {
        let username: String = "test"
        let password: String = "test123"
        HHFWController.sharedInstance().auth(username, password: password){ (jsonResult) in
            if let jsonDict = jsonResult as? NSDictionary,
                let status = jsonDict["status"] as? String, status == "ok" {
                print("Auth success")
                completion()
            } else {
                print("Auth error")
            }
        }
    }
 
    // Perform the Table request
    private func tableRequest(completion: @escaping (NSDictionary)->()) {
        let resourceName = "FRUITS"
        let tableCallParams = TableCallParams(defaultProperty: ())
        tableCallParams?.retryCount = 10
        tableCallParams?.retryIntervalSec = 1
        HHFWController.sharedInstance().table(resourceName, transactionID: nil, tableCallParams: tableCallParams) { (jsonResult) in
            if let jsonDict = jsonResult as? NSDictionary,
                let status = jsonDict["status"] as? String, status == "ok" {
                print("Table request success")
                completion(jsonDict)
            } else {
                print("Table request error")
            }
        }
    }
 
    // Set methods to display application user interface elements
    private func deactivateButtons() {
        self.tableRequestButton.isEnabled = false
    }
 
    private func activateButtons() {
        self.tableRequestButton.isEnabled = true
    }
}

Resuming Resource Downloading in Uniform Request to Resource

To execute a uniform request to resource without loading to database, create the HHFWRequestRetry application, which uses framework methods:

Method name Brief description
initWithCredentials (_: host: environment: project: device:) The method initializes the framework.
auth (_: password:) The method authenticates the user by login and password.
request (_: requestCallParams: handler:) The method sends a uniform request to resource without loading to database.

To set the number of repetitions and interval between them, use the retryCount and retryIntervalSec properties of instance of the RequestCallParams class that is sent as a parameter to the request method.

The HHFWRequestRetry application includes one screen, the UITextView text view and the UIButton button:

NOTE. When the application is initialized, authentication is executed, the button is not available. If the authentication is executed successfully, the button is available, and the text box displays the text "Authentication success".

To execute the example, click the Perform Request button. Clicking the button initializes a request to resource. A mobile platform server returns corresponding data.

Application code:

import UIKit
 
class ViewController: UIViewController {
 
    // Determine output data
    @IBOutlet weak var resultTextView: UITextView!
    @IBOutlet weak var requestButton: UIButton!
 
    // Redetermine method
    override func viewDidLoad() {
        super.viewDidLoad()
        self.deactivateButtons()
        self.initializeFramework()
        self.auth {
            self.activateButton()
            self.resultTextView.text = "Authentication success"
        }
    }
 
    // Set method that will be executed on button click
    @IBAction func requestPressed(_ sender: UIButton) {
        self.performRequest { (jsonDict) in
            self.resultTextView.text = String(format: "%@", jsonDict)
        }
    }
 
    // Initialize framework
    private func initializeFramework() {
        let apiVersion: String = "v1"
        let host: String = "http://testmasterfmp.fsight.cloud/"
        let environment: String = "DocumentationExampleEnv"
        let project: String = "DocumentationExampleProj"
        let device: String = (UIDevice.current.identifierForVendor?.uuidString)!
        HHFWController.sharedInstance().initWithCredentials(
            apiVersion,
            host: host,
            environment: environment,
            project: project,
            device: device
        )
    }
 
    // Authenticate
    private func auth(completion: @escaping ()->()) {
        let username: String = "test"
        let password: String = "test123"
        HHFWController.sharedInstance().auth(username, password: password){ (jsonResult) in
            if let jsonDict = jsonResult as? NSDictionary,
                let status = jsonDict["status"] as? String, status == "ok" {
                print("Auth success")
                completion()
            } else {
                print("Auth error")
            }
        }
    }
 
    // Perform the Request request
    private func performRequest(completion: @escaping (NSDictionary)->()) {
        let resourceName = "FRUITS"
        let requestCallParams = RequestCallParams(defaultProperty: ())
        requestCallParams?.retryCount = 10
        requestCallParams?.retryIntervalSec = 1
        HHFWController.sharedInstance().request(resourceName, requestCallParams: requestCallParams) { (jsonResult) in
            if let jsonDict = jsonResult as? NSDictionary,
                let status = jsonDict["status"] as? String, status == "ok" {
                print("Request success")
                completion(jsonDict)
            } else {
                print("Request error")
            }
        }
    }
 
    // Set methods to display application user interface elements
    private func deactivateButtons() {
        self.requestButton.isEnabled = false
    }
 
    private func activateButton() {
        self.requestButton.isEnabled = true
    }
}

See also:

Examples of iOS Framework Use | Examples of Working with Resources