Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
nabheetscn
Active Contributor
PS: Demo app at the end. I have not used the Fiori iOS assistant out of my own curiosity to understand the things. You can refer to this wonderful blog Translation via Assistant or API Hub integration via Assistant by jitendrakumar.kansal to quickly get a look and feel. For knowing the new features in the SDK refer this blog What’s new in SAP Cloud Platform SDK for iOS 2.0

My own Rants


So in this blog we have created things from scratch to get a better understanding of Swift as well as how does SAP Fiori iOS SDK integrates with it.  One of the most basic thing is to spend at least 2-3 weeks in understanding what Swift is, and how it works. Without a basic understanding of the underlying concept, i believe things will get tough in some complex situation.There are so many important concepts like delegate, protocol, dictionaries, mutable arrays etc. which needs to be understood clearly. So in a nut shell like we always do read, understand and share as much as you can.

What we are trying to make?


We will be making a simple translation app to start the momentum in this blog, which will take input and translate it to the chosen language via SAP cloud translation API.


Technical Details



  • FUISimplePropertyFomCell - Input field for text

  • FUIListPickerFormCell - Dropdown

  • FUIButtonFormCell - Button

  • SAPURL Session - Technique to communicate with Rest API's

  • SAP API Hub – Translation - Our API


I would specifically like to thank steve.guo for his  blog series and robin.vanhethof for his blog series which I have referred to get my head around the iOS development.

So, coming to the technical details we are using a navigation controller with a table view by default. Inside table view controller we are adding our Fiori based form elements, please refer this blog to know how to add navigation controller steps in detail.
 // Add cell to the view.
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(FUISimplePropertyFormCell.self, forCellReuseIdentifier: FUISimplePropertyFormCell.reuseIdentifier)
tableView.register(FUIListPickerFormCell.self, forCellReuseIdentifier: FUIListPickerFormCell.reuseIdentifier)
tableView.register(FUISimplePropertyFormCell.self, forCellReuseIdentifier: FUISimplePropertyFormCell.reuseIdentifier)
tableView.register(FUIButtonFormCell.self, forCellReuseIdentifier: FUIButtonFormCell.reuseIdentifier)
}

Add the cell attributes etc.
//Provide Cell Details and values
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let row = indexPath.row
switch row{
case 0:
// source text
let cell = tableView.dequeueReusableCell(withIdentifier:FUISimplePropertyFormCell.reuseIdentifier, for: indexPath) as! FUISimplePropertyFormCell
cell.keyName = "Input Text "
cell.value = self.translationModel.inputData
cell.onChangeHandler = {
self.str = $0
}
return cell
case 1:
// target language
let cell = tableView.dequeueReusableCell(withIdentifier:FUIListPickerFormCell.reuseIdentifier, for: indexPath) as! FUIListPickerFormCell
cell.keyName = "Target Language"
cell.valueOptions = TranslationModel.langList
cell.allowsMultipleSelection = false
cell.allowsEmptySelection = false
cell.isEditable = true
if(cell.value.count == 0){
cell.value.append(self.translationModel.targetLang)
}
else{
cell.value[0] = self.translationModel.targetLang
}
cell.onChangeHandler = {
self.translationModel.targetLang = $0[0]
}
return cell
case 2:
// Translated Text
let cell = tableView.dequeueReusableCell(withIdentifier:FUISimplePropertyFormCell.reuseIdentifier, for: indexPath) as! FUISimplePropertyFormCell
cell.keyName = "Translation"
cell.value = self.translationModel.outputData
cell.onChangeHandler = {
self.str = $0
}
return cell

case 3:
// Button
let cell = tableView.dequeueReusableCell(withIdentifier:FUIButtonFormCell.reuseIdentifier, for: indexPath) as! FUIButtonFormCell
cell.button.setTitle("Translate", for: [])
cell.button.tintColor = UIColor.black
//Button Actions
cell.button.addTarget(self, action: #selector(TableViewController.getTranslation(_:)), for: .touchUpInside)
return cell
default:
let cell = tableView.dequeueReusableCell(withIdentifier:FUISimplePropertyFormCell.reuseIdentifier, for: indexPath) as! FUISimplePropertyFormCell
return cell
}
}

Once user clicks the translate button we call the SAP Cloud API for translation on button click. The implementation of this decoding the response was quite a challenge, explained below in challenges.
	// Action for getting translation
@objc func getTranslation(_ sender:UIButton!){
var index = IndexPath(row: 0, section: 0)
var cell = self.tableView.cellForRow(at: index)
// Read current input
self.translationModel.inputData = cell?.value(forKey: "value") as! String
//adding request headers
//API Key for API Sandbox
let headers = [
"Content-Type": "application/json",
"Accept": "application/json;charset=UTF-8",
"APIKey": "a4hcjXcHKxMeCZg0Af9y7GA5YUbqv6os"]
let parameters = [
"sourceLanguage": "en",
"targetLanguages": [TranslationModel.langList[self.translationModel.targetLang]],
"units": [["value": self.translationModel.inputData]]]
as [String : Any]
var postData: NSData? = nil
do {
postData = try JSONSerialization.data(withJSONObject: parameters, options: JSONSerialization.WritingOptions(rawValue:0)) as NSData
}
catch {
print(error)
}
//API endpoint for API sandbox
let request = NSMutableURLRequest(url: NSURL(string: "https://sandbox.api.sap.com/ml/translation/translate")! as URL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10)
//setting request method
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData! as Data
let urlSession = SAPURLSession()
//sending request
let dataTask = urlSession.dataTask(with: request as URLRequest, completionHandler: {
(data, response, error) -> Void in
// Response Handling in Challenges part
})
dataTask.resume()
}

Demo


A basic iOS app running translation is up.


Challenges



  • First big challenge is the sample code in SAP API Hub for Swift does not work with my version of Xcode and Swift. I being a beginner in Swift it was tough to actually resolve the errors but was worth it. It will be great if we can have version dependent Swift sample code in the API hub.

  • Secondly Sample code for iOS Fiori is available only on an Ipad app☹ and we have lack of examples online otherwise. I can understand we have just started this SDK and improving day by day but availability of SAP Mentor App on Iphone will be a plus.

  • Third biggest challenge for me was how to Parse the response from API. This actually led me to understand in detail about concept of dictionaries (nothing by key, value pair), mutable array (an array which can be changed after initial value assignment) and non-mutable one(non-changeable after initialization).Good use of casting was needed to get the translated text. The challenge comes you can see the whole response but don’t know how to traverse it.


 do {
guard let responseObject = try JSONSerialization.jsonObject(with: data!, options:JSONSerialization.ReadingOptions.mutableContainers)as? NSDictionary else {
print("error trying to convert data to JSON")
return
}
let root = responseObject["units"] as? NSMutableArray
let contentDictionary : NSDictionary = root![0] as! NSDictionary
let translationArray = contentDictionary["translations"] as? NSMutableArray
let decoded : NSDictionary = translationArray![0] as! NSDictionary
self.translationModel.outputData = decoded["value"] as! String



  • Fourth biggest challenge for me was how to update the value which was returned by SAP Translation API. In my experience while working with Angular & Ionic the moment you update the model the changes are reflected. But in Swift world as far as my understanding till now is, I have to trigger it manually using the below mentioned code. Although 3 lines but took me good amount of time.


DispatchQueue.main.async {
self.tableView.reloadData()
}

What is next?



  • More blogs to share the Swift Learning experience while using different controls and trying to mix different things:)

  • Might be a series on Swift for ABAPer's is needed does not matter who writes it, important is to share the knowledge


Feel free to provide your feedback open to all ears. I have also uploaded the code on Github it might help people who are starting the journey

 

 
2 Comments
Labels in this area