Skip to Content

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)

/wp-content/uploads/2015/07/image1_739713.png

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!.textString(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, UIPickerViewDataSourceScannerViewControllerDelegate {

    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.


/wp-content/uploads/2015/07/image100_739721.jpg







To report this post you need to login first.

1 Comment

You must be Logged on to comment or reply to a post.

Leave a Reply