Iphone App in Swift Xcode 6.3 for SAP Plant Stock
In my first blog on mobile development about a year back
SAP and Xamarin for C# Mobile Cross Platform Development Tutorial
I had described in detail about mobile application architecture. All my earlier applications were developed in C# using Xamarin. When Swift was released I wanted to explore this and write a iphone app with based on Swift and Xcode 6.3. This blog
describes the SAP Plant Stock application that I developed using SWIFT. The ABAP side REST service has been developed as described in my earlier blog.
When I started my application I wanted to provide all the functionality that I had provided with a similar app that I had developed for Andorid and Iphone using Xamarin(C#) but develop this in SWIFT and Xcode 6.3
Xamarin Native IPhone and Apple Watch for Plant Stock – Part1
I Created a new Single View Application using Xcode – Deleted the created View Controller – Added a new Table View Controller – Embedding this in Navigation View Controller (Edit Menu- Embed in Navigation View Controller)
Create Swift Classes one based on Table View Controller and other UI View Controller and assoicate these classes with storyboard. Create a Segue way from the barbutton to the second View Controller which will allow the user to enter the selection – For the Material I have textFiled for the Plant and Location I populate two pickers from the data I get from SAP REST call.
To Make REST all to SAP I Created a protocol as follows
protocol SapRestProtocol {
func didRecieveResponse(results: NSArray)
}
as I wanted to get the master data for Plants and locations at the start I changed the appdelegate file to implement the above protocol to read
class AppDelegate: UIResponder, UIApplicationDelegate, SapRestProtocol {
{
// Override point for customization after application launch.
checkandFetch()
return true
}
}
func checkandFetch()
{
/
var sapapi: SapRest? = SapRest()
sapapi!.delegate = self
sapapi!.GetSapMasterData(“XXXXX”, RestTag: “/MADATA/MADATA”)
}
func didRecieveResponse(results: NSArray) {
if results.count>0 {
//populate the location and plant arrays which have to populated in the respective pickers
}}
in the SapRest Class I have code as follows
class SapRest: NSObject {
var data: NSMutableData = NSMutableData()
var delegate: SapRestProtocol?
func GetSapMasterData(stringPost: String, RestTag:String) {
let path = “”
let SapClient = “”
let userName = “
let passWord = ““
let loginString = NSString(format: “%@:%@”, userName, passWord)
let loginData: NSData = loginString.dataUsingEncoding(NSUTF8StringEncoding)!
let base64LoginString = loginData.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.allZeros)
let urlPath = path + RestTag + SapClient;
if let url = NSURL(string: urlPath) {
var request: NSMutableURLRequest = NSMutableURLRequest(URL: url)
request.HTTPMethod = “POST”
request.setValue(“Basic \(base64LoginString)”, forHTTPHeaderField: “Authorization”)
var postData:NSData = stringPost.dataUsingEncoding(NSUTF8StringEncoding)!
var postLength: NSString = String(postData.length)
request.HTTPBody = postData
request.setValue(postLength as String, forHTTPHeaderField: “Content-Length”)
request.setValue(“application/x-www-form-urlencoded”, forHTTPHeaderField: “Content-Type”)
request.setValue(“application/json”, forHTTPHeaderField: “Accept”)
if let connection = NSURLConnection(request: request,delegate: self,startImmediately: false) {
connection.start()
}
}
}
//}
We now have the Plants and Locations in two arrays of strings so that when the user clicks on the Button – we will populate the pickers and transfer to the selection screen.
For the TableView Controller I have code – we have to implement the functions to implement the required functions
class StockListController: UITableViewController {
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
@IBAction func unwindToStockList(segue: UIStoryboardSegue)
{
if segue.identifier == “UnWindList” {
if let svc = segue.sourceViewController as? SelectViewController {
in_rec = svc.indata
if in_rec.MATNR != “” {
getData()
self.tableView.reloadData()
}
}
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier(“StockCell”, forIndexPath: indexPath) as? StockCell
if cell == nil {
cell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: “StockCell”) as? StockCell
}
var celldata = items[indexPath.row];
// Configure the cell…
cell!.txtPlant!.text = celldata.WERKS
cell!.txtLocation!.text = celldata.LGORT
cell!.txtBatch!.text = celldata.CHARG
cell!.txtStock!.text = String(format: “%d”,celldata.LABST)
return cell!
}
Notice the UnWind usage – this comes into action when the user selects the parameters and cliks on Get Button – it is at at that time GetData will call SAP and get the stock records based on the Selection Parameters
Now let us look the code where the user is allowed to enter the selection criteria and then click on Get – For the material the user can scan for barcode
import UIKit
import AVFoundation
class SelectViewController: UIViewController, UITextFieldDelegate, UIPickerViewDelegate, UIPickerViewDataSource, ScannerViewControllerDelegate {
var scannerVC: ScannerViewController!
…
you have to implement the following delegate and datasource methods
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return false
}
func SetDataForPicker( PLANTS:[String], LOCATIONS:[String])->() {
self.plants = PLANTS
self.locations = LOCATIONS
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier != “UnWindList” {
scannerVC = segue.destinationViewController as! ScannerViewController
scannerVC.delegate = self
}
}
override func viewWillAppear(animated: Bool) {
self.pickerPlant.reloadAllComponents()
self.pickerLocation.reloadAllComponents()
selPlant = “ALL”
selLocation = “”
}
@IBAction func btnScan(sender: AnyObject) {
}
//—fired when the barcode is captured—
@IBOutlet weak var pickerPlant: UIPickerView!
@IBOutlet weak var pickerLocation: UIPickerView!
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func btnGetStock(sender: AnyObject) {
if selPlant == “ALL” || selPlant == “All” {
selPlant = “”
}
if selLocation == “ALL” || selLocation == “All” {
selLocation = “”
}
if txtMaterial.text.isEmpty {
let alert = UIAlertController(title: “No Material”,
message: “Please Enter Material and Click Get Button”,
preferredStyle: .Alert)
// Display the alert
self.presentViewController(alert,
animated: true,
completion: nil)
return
}
// if let parentc = self.parentViewController as? StockListController {
indata.MATNR = txtMaterial.text
indata.WERKS = selPlant
indata.LGORT = selLocation
indata.CHARG = selbatch
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
}
We have to implement the required delegates – The picker data is populated when you click on the tool bar button –
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
if segue.identifier == “ToSelect” {
let vc = segue.destinationViewController as! SelectViewController
var appdeg = UIApplication.sharedApplication().delegate as! AppDelegate
vc.SetDataForPicker(appdeg.plants, LOCATIONS: appdeg.locations)
}
else if segue.identifier == “StockDetail” {
let vc = segue.destinationViewController as! StockDetailViewController
if let currpath = tableView.indexPathForSelectedRow(){
vc.datarec = items[currpath.row]
}
}
}
In addition I have one more view controller that displays the detailview when you click on TableLine -(segue.identifier == “StockDetail”) – Just as I was finishing I upgraded my Iphone to 8.4 – and then I had to upgrade to Xcode 6.4 so that I can test this app on my phone. I have used the same Architecture as my mobile applications – There is lot material on SWIFT/XCODE so I wanted to emphasize on the SAP interfacing part.
Can you please send the link for this project