Higher order functions in swift

As far as I understood, higher order functions are functions that takes another function/closure as argument and/or returns it.

Higher order functions are simply functions that operate on other functions by either taking a function as an argument, or returning a function. Swift’s Array type has a few methods that are higher order functions: sorted, map, filter, and reduce. These methods use closures to allow us to pass in functionality that can then determine how we want the method to sort, map, filter, or reduce an array of objects.
If you look around the internets the most commonly mentioned higher order functions in Swift are generally mapfilter, reduce and sort (or sorted). But there are so many more to play with!

Just take a look at Array – you will also find containsdropfirstflatMapforEachpartition  and split.

Map

Use map to loop over a collection and apply the same operation to each element in the collection.

Map on array:

Let’s assume we need to multiply each item by 10 in an array called numberArray

          let numberArray = [2,3,4,5,6,7,8]
          let emptyArray:[Int] = []
          //MARK:-Traditional Way
         for number in numberArray{
                    emptyArray.append(number*10)
         }
        //MARK:-
Higher Order Functions that is map

There are few form’s: long-form vs shorthand closure syntax preference.
        //1) Way
        emptyArray = []

        emptyArray = numberArray.map ( { (value:Int) -> Int in
               return value*10
})
        //2) Way
        emptyArray = []
        emptyArray = numberArray.map( { (value:Int) in
               return value*10
        })
//3) Way
        emptyArray = []
        emptyArray = numberArray.map {value in value*10}
//4) Way
        emptyArray = []
        emptyArray = numberArray.map {$0 * 10}

The map function has a single argument which is a closure (a function) that it calls as it loops over the collection. This closure takes the element from the collection as an argument and returns a result. The map function returns these results in an array.

Map on Dictionary:

        let reviews = [“likes”:50, “comments”:52]

Here, for the above dictionary, as we iterate over the collection our closure has arguments that are a String and a Int from the types of the key and value that make up each element of the dictionary. The return type can be an array of values (i.e., 50), values array with discounts or even an array of tuples. It’s all upto you.

         let reviewsCount = reviews.map { (key, value) in
                 return value
         }
         print(reviewsCount)
         //[50, 52]

Map on Custom Object:

    struct Person{
       let name:String
       let id:Int
           init(name:String, id:Int){
           self.name = name
           self.id = id
       }
    }
    let personDict = ["Palash":1,"Rahul":2,"Govind":3]
    let persons = personDict.map{ name, id in Person(name: name, id: id)}
    print(persons.first?.name)
    //Palash

Array count  Traditional Way Exe. time    Using Hight Order Function map Exe. time
   6930         0.0645290017127991                         0.00439298152923584

Filter

Use filter to loop over a collection and return an Array containing only those elements that match an include condition.

Filter on array:

Consider the following code to filter even numbers from an array of integers.Now, like map , there is a simple method to do the filtering stuff for collection types.The swift autocomplete shows the following if we try to use filter method for an Int array.
The filter method has a single argument that specifies the include condition. This is a closure that takes as an argument the element from the collection and must return a Bool indicating if the item should be included in the result. I have given the shorthand closure syntax example below.,

         //MARK:-Traditional Way
         emptyArray = []
         for no in numberArray{
             if no % 2 == 0{
                 emptyArray.append(no)
             }
         }

         //MARK:-Higher Order Functions
         emptyArray = []
         emptyArray = numberArray.filter{$0 % 2 == 0}

Filter on dictionary:

 The filter functions will call a closure called isIncluded by passing each key-value pair and do the condition check (here, it accepts a String and Doubleas arguments). Finally, based on the bool value returned, the filter function will decide whether or not to add the key-value pair in the returned array.
Filter function on dictionary returns an array of Tuples .

          let reviewsFilter = reviews.filter { (key, value) in
                  return value > 50
}
          print(reviewsFilter)

         //52

This can be further simplified as:

         let reviewsFilter1 = reviews.filter { $1 > 50}

       Note: $0 is the key, $1 is the value

Array count  Traditional Way Exe. time    Using Hight Order Function map Exe. time
 3300           0.000292956829071045                    0.00520197877883911

Reduce

Combines all items in a collection to create a single value.

The most versatile function reviewed here is reduce. Reducing a sequence means transforming many items into a single item. For example, an array of integers could be reduced to the sum of every integer in the array. In this case, a sequence of integers is reduced to a single integer.

        //MARK:-Traditional Way
        var sum = 0
        for no in numberArray{
sum += no
        }

The two parameters in reduce function are a starting value and a function respectively. The function takes a running total and an element of the array as parameters, and returns a new running total.

        //MARK:-Higher Order Functions
        //1 Way 
        var  sum = numberArray.reduce(0, {$0 + $1})
        //2 Way 
        var sum = numberArray.reduce(0,+)

In above scenario, instead of the closure, we could also pass basic operator functions like +, -, *, / . So we can say reduce is used to combine all items in a collection to create a single new value.

Reduce on dictionary

        let totalReviews = reviews.reduce(0) { (result, tupleOfKeyAndValue) in
                   return result + tupleOfKeyAndValue.value
}

Flatmap

When implemented on sequences : Flattens a collection of collections.

There are two versions of this function: one that supports mapping optional values and another that supports mapping a sequence of sequences, such as [[Int]] (i.e. an array of array of integers)

let tempArray = _flatMap([“Hi”,” “,“there”,” “, nil,“😁!!!!”]) { $0 }
print(tempArray)

//Hi there 😁!!!!

This function is like a mixture of map and filter. It creates a sequence of mapped values, but a mapped value is not added to the output sequence when the closure returns nil. In that sense, returning nil is similar to returning false from a closure passed to the filter function.

 

Happy Coding… 🙂📱😁
I will show the usage of remaining higher order function in my next post.

How to Integrate Pardot with WordPress via Contact Form 7

When you want to submit your form to third-party CRM like (pardot, Salesforce, MailChimp etc.) or if you want to
change action URL of the form please following steps.

To get this to work you need to have following things.

1.   WordPress website
2.  Contact Form7 Plugin – WordPress Plugin
3.  Forms: 3rd Party Integration – WordPress Plugin
4.  Pardot and the ability to create form handler


1. Create a Form using Contact Form7 which you want to submit on third-party CRM.
2. Create a Form Handler on pardot for the fields which you have used in contact form7 form.
3. Go to WordPress admin panel -> Contact -> 3rd party Services

i.  Now click on ‘[+]3rd-Party Service: Pardot‘ and give some service name.
ii. Next, you have to add 3rd party action URL into ‘Submission URL

Imp Note:  Action URL into ‘Submission URL’ must be HTTPS. This plugin does not support HTTP URL.
select the form from ‘Attach to Forms’ options

iii. Now you have to map your contact form fields with pardot form fields. Enter all contact form fields into
‘Form submission Field’ column and all pardot fields into ‘3rd-Party Field’ column.

Imp Note:  Values of ‘Form submission Field’ and ‘3rd-Party Field‘ must be identical. Small space or difference will break your submission.

iv. Next setup redirect URL into Contact Form7 settings.
v.  Now copy contact Form7 shortcode and paste it into any page.That’s it.

How to check user exist or not in pardot prospect using api-php

The Pardot API should be accessed via POST for all operations . For the most part the API does not use the standard HTTP response codes to convey the outcome of the request, rather it always returns 2 response codes and sends back its own set of status codes that need to be handled.

Steps for the check user in prospect :

Step 1 : Login to pardot by api :

$url = “https://pi.pardot.com/api/login/version/3?email=useremail@email.com&password=pardot_password&user_key=********************************”;

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$response = curl_exec($ch);

$xml = simplexml_load_string($response);
$json = json_encode($xml);
$array = json_decode($json,TRUE);

$api_key = $array[‘api_key’];

Above API will return access token in response(api_key).

Step 2 : Check user :

$url = “https://pi.pardot.com/api/prospect/version/4/do/read/email/search_user_by_email?user_key=********************************&api_key=$api_key”

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$response = curl_exec($ch);

 

If user exist then it will return [{“stat” : “ok”] otherwise it will return [{“stat”:”fail”}]

 

In the same way we can check user in pardot account also;

Repeat the above step for check user in account, there are only single change in second api.Replace prospect with account.

https://pi.pardot.com/api/acount/version/4/do/read/email/search_user_by_email?user_key=********************************&api_key=api_key

Virtual Assistant

A virtual assistant is a software agent that can perform tasks or services for an individual. Sometimes the term “chatbot” is used to refer to virtual assistants generally or specifically those accessed by online chat (or in some cases online chat programs that are for entertainment and not useful purposes).

As of 2017, the capabilities and usage of virtual assistants is expanding rapidly, with new products entering the market. An online poll in May 2017 found the most widely used in the US were Apple’s Siri (34%), Google Assistant (19%), Amazon Alexa (6%), and Microsoft Cortana(4%). Facebook’s M is expected to be available to hundreds of millions on Facebook Messenger in 2017.

 

Cortana

Cortana is an operating system-oriented voice assistant available on Windows 10 devices, as well as the Xbox One console. Cortana is closely connected to productivity, but can also help answer more general questions by pulling information from Bing.

The Cortana VA has seen a lot of recent growth, expanding her use throughout Windows 10 and related services. Combined with newer offerings like Surface Studio, its clear Microsoft favors Cortana as an OS-based service to control Windows 10 while one is working.

While user can store specific bits of information with Cortana, Microsoft’s virtual assistant is constantly analyzing user’s interactions to learn more about him/her. This info is stored in something Microsoft calls the “Notebook,” which includes the places user likes to go, people he/she care about, user’s preferred quiet hours, and things he/she might be interested in, among other things. User can even edit it if he like.

Cortana can user’s emails, track user’s location, watch user’s browsing history, check user’s contact list, keep an eye on user’s calendar, and put all this data together to suggest useful info, if user allow it to. Cortana is designed to recognize context, so it should be able to understand follow-up requests, and you can phrase things in different ways and still expect a useful answer. User can also type his/her questions or requests, if you prefer to not speak out loud.

The latest changes from the Windows 10 Creators Update allow Cortana to help in the setup process for new computers, and include a new full screen mode for Cortana that serves as both a screensaver and voice-assistant focused mode when user is away from the computer—or is too far away to type. Cortana can also handle music and reminder commands more effectively, spanning multiple music apps and controlling volume as user desire.

 

Siri

Siri has been an integral part of iOS since the launch of iOS 5 in 2011. It started with the basics such as weather and messaging, but has expanded greatly since then to support more third-party integration with MacOS.

While Siri’s jokes are legendary, the virtual assistant is getting more capable every day. Now, user can ask it to call people, send messages, schedule meetings, launch apps and games, play music, answer questions, set reminders, and provide weather forecasts.

Siri can also integrate with third-party apps and understand follow-up queries. That’s a big change in strategy for Apple, which typically maintains a tight grip on which third-party companies get access to its native functions.

Siri is probably the most familiar of all the voice assistants. It also lags behind the other VAs when it comes to text input, which isn’t supported for most Siri functions. Apple appears to be using Siri for voice controls and Spotlight for similar text-based queries.

The latest news for Siri includes voice compatibility for WhatsApp, expanded payment options for Lyft and Uber, and the ability to look up international cricket scores. These are minor tweaks compared to the changes other VAs are going through, but they also point to Siri’s continued stability—particularly for long-term iOS users who already know the voice assistant well.

 

Google Assistant

Google Assistant (which has incorporated functions from the older Google Now, as Now is being phased out) is different from Cortana and Siri. It has less personality, but more functionality. While it is an integral part of Android, Google Assistant also lives in an iOS app, and can be accessed through the Chrome browser as needed.

Like Cortana and Siri, you can ask Assistant for directions to the closest Chinese restaurant, or what the weather looks like for the next 10 days. If you let it, Google’s software will utilize your search history and customize its responses based on what it knows about your queries.

Google’s integration with its search engine makes Google Assistant one of the most useful virtual assistants out of the box. It already has a treasure trove of data on what you’ve done on the web. It also reacts to questions in a similar way to the Google browser, which makes it great for general information and trivia.

 

Alexa

It is Amazon’s voice assistant and it isn’t focused on mobile or computer purposes, but rather for the standalone Amazon Echo speaker and a limited number of Amazon Fire devices, with a greater concentration on whole-house management and services rather than computer-oriented tasks.

Obviously, this limits Alexa compared to the alternatives. However, there are some advantages to the Amazon approach. Like Assistant, Alexa is highly conversational, and its ability to parse meaning is frequently excellent, whether you’re asking about the weather or listening to the latest news summaries from around the web. Alexa is meant to be used out in the open, away from the computer, while you’re working elsewhere but still need information, entertainment, or purchases.

The customization and management options for Alexa also impress. While other voice assistants hide many of their capabilities away from users, Alexa brings them all out in the form of “skills” and connections. The Alexa app allows you to add various mini-apps in the form of skills, and adjust current services and settings using these skills. It’s a great system, especially for those who like to tinker, but it does require learning a new approach to VA management.

Amazon is also doing a lot of work to bring Alexa into more mobile situations: The Alexa app, for example, brings many of its capabilities to your phone so you can organize lists while driving or control smart home features away from an Echo.

 

 

Bixby

Not to be outdone in the voice assistant game, Samsung has also created a mobile device assistant called Bixby, which now has full voice command compatibility (if you’ve picked up a Galaxy S8, you’ve probably encountered it). In general, Bixby shares a lot in common with Cortana. The VA lingers on the Galaxy phone, ready to access information and manage your data, schedule, events, and more. It doesn’t venture out into the Internet of Things much, but it does have an impressive amount of control over everything you do on your Samsung device.

You can divide Bixby into three basic different categories of abilities—Voice, Home, and Vision. They all work together, but use different Bixby abilities:

Voice includes both questions—”What’s the weather today?”—and commands. Start by saying “Hey Bixby” and you can get general information or facts. However, like Cortana, Bixby also excels at operating software, so you can also use it to control the Galaxy menus, change settings, set reminders, take pictures, edit video, and much, much more. If you’ve ever wanted to operate your smartphone hands free, there’s a lot to explore here. Some functionality goes even deeper – you can ask Bixby to read out your latest emails, or tell it to post your photo to Instagram, and Bixby will do so.

Home is the app face of Bixby, a screen that provides information based on what you have asked Bixby about in the past, as well as the different services that Bixby can control with the right compatibility—Including Facebook, CNN, and Spotify. In the future this area may include smart home capabilities (Samsung says it’s on the way), but for now it’s relegated to basic online services.

Vision is the most unique part of Bixby, as it can analyze what image the camera is picking up and give you a report on it. When this works (say, looking at a recognizable logo) Bixby can help you instantly compare online prices to in-store prices, or give you more information about local landmarks. If this feature takes off, other voice assistants may start getting jealous.

 

 

A/B Testing in Marketing Cloud

 A/B Testing Marketing Cloud

 Why A/B Testing :-

We use standard A/B testing to determine which version of your email(Or a subject line)receives the highest click-through rate or highest unique open rate. On the basis of that, we sends the best performing version to the remaining subscribers or Data Extentions.

  • You can test the following elements:
  • Test Type            Description
  1. Subject Line:                     Create two different subject lines and track which email send                                                                                             performs better. Each subject line has a 256 character limit.
  2. Email:                                Select two different emails and track which email send performs                                                                                       better.
  3. Content area:                    Select an email that contains at least two different content areas and                                                                               track which content area performs better.
  4. From Name:                     Create two different from names and track which email send                                                                                             performs better. You can select an existing from name in your account,                                                                           or manually enter a from name to use. To add additional from name                                                                               Select two different dates and/or times to send and track which time                                                                               options to your account, create an additional user.
  5. Send Time:                        performs better.
  6. Preheaders:                     Create two different preheaders and track which preheader performs                                                                  better.

 

  • IF Tie Happens :

If your A/B Test results in a tie, the system declares Condition A the winner. You can edit the winner criteria to see if one condition performed better than the other using a different winner criteria.

For example, if you ran your test by the highest open rate and your test results in a tie, you can edit the winner criteria to use highest click-through rate.

Or, if you ran your test by the highest open rate and Condition B had a significantly higher click-through rate than Condition A had an open rate, you can edit the winner criteria in order to send Condition B.  You will be able to make this change only if you scheduled the remainder to send at a later time.

  • WE Can Save the Winning Subject Line :

When running a subject line A/B test, you have the option to have the winning subject line save back to the original email. You configure this in the Winner stage of the test creation process.

Different Processes of A/B testing and Useful links.

Following link contain steps to create those processes.

  1. Configure A/B Test

https://help.marketingcloud.com/en/documentation/exacttarget/ab_testing/configure_an_ab_test/

  1. Duplicate A/B Test

https://help.marketingcloud.com/en/documentation/exacttarget/ab_testing/how_to_duplicate_modify_or_cancel_existing_ab_tests/

  1. Edit A/B Test

https://help.marketingcloud.com/en/documentation/exacttarget/ab_testing/edit_a_ab_test/

  1. Track A/B Test

https://help.marketingcloud.com/en/documentation/exacttarget/ab_testing/tracking_ab_email_testing/

  1. Cancel A/B Test

https://help.marketingcloud.com/en/documentation/exacttarget/ab_testing/cancel_ab_tests/

Platform Cache varient 2 – Org Cache

Continuing with Platform Cache….

2. Org Cache : The second variant of Platform Cache is the Org Cache. Org Cache does the same thing of storing the data in session, but the data stored is accessible through out the org, irrespective of  user, which is not the case with Session Cache.
If user1 is storing a  value1 in org cache, it is accessible by user2 also.

We can have different partitions to store values. We use the Cache.Org and Cache.OrgPartition classes to manage values in the org cache. To manage values in any partition, use the methods in the Cache.Org class. If we are managing cache values in one partition, use the Cache.OrgPartition methods instead.

This example stores a DateTime cache value with the key orderDate. Next, the snippet checks if the orderDate key is in the cache, and if so, retrieves the value from the cache.

// Add a value to the cache//
DateTime dt = DateTime.parse(’06/16/2015 11:46 AM’);  Cache.Org.put(‘ns1.partition1.orderDate’, dt);
if (Cache.Org.contains(‘ns1.partition1.orderDate’)) {
       DateTime cachedDt = (DateTime)Cache.Org.get(‘ns1.partition1.orderDate’);

}

To refer to the default partition and the namespace of the invoking class, omit the namespace.partition prefix and specify the key name.

Cache.Org.put(‘orderDate’, dt);
if (Cache.Org.contains(‘orderDate’)) {
DateTime cachedDt = (DateTime)Cache.Org.get(‘orderDate’);
}

The local prefix refers to the namespace of the current org where the code is running. The local prefix refers to the namespace of the current org where the code is running, regardless of whether the org has a namespace defined. If the org has a namespace defined as ns1, the following two statements are equivalent.

Cache.Org.put(‘local.myPartition.orderDate’, dt);
Cache.Org.put(‘ns1.myPartition.orderDate’, dt);

This is all about the Org Cache in apex.  There is another interesting thing about Platform Cache!

We can access cached values stored in the session or org cache from a Visualforce page with global variables.We can use either the $Cache.Session or $Cache.Org global variable. Include the global variable’s fully qualified key name with the namespace and partition name.

This output text component retrieves a session cache value using the global variable’s namespace, partition, and key.

<apex:outputText value=”{!$Cache.Session.myNamespace.myPartition.key1}”/>

This example is similar but uses the $Cache.Org global variable to retrieve a value from the org cache.

<apex:outputTextvalue=”{!$Cache.Org.myNamespace.myPartition.key1}”/>

Now the Platform Cache concept seems more useful! We can directly use it in Vf page!!

Salesforce is Awesome!

Use Glide Cache efficiently in Glide Android

The issue is that currently if I call Glide.load() multiple times with the same URL. however, each time with an image views the image gets downloaded again.

It happens because the width and height are mixed into the cache key so if you load the same image into multiple different views with different sizes, the image will be fetched once per image by default.

You can change this by calling  .diskCacheStrategy() with  DiskCacheStrategy.SOURCE on remote image loads. Doing so will use only the original URL as the cache key and so you will get a cache hit if you try to load the same URL with multiple sizes.

e.g:

Glide
    .with( context )
    .load( URL )
    .diskCacheStrategy( DiskCacheStrategy.SOURCE )
    .into( imageViewInternet );

For more details click here

Bundles in Steelbrick CPQ

Steelbrick CPQ allows users to define bundles to be added to Quote. This proves very helpful as it saves time of adding every product individually.

For achieving this there are two objects in CPQ.

The first is Features. Features is basically definition of the bundle. Features can be added from related lists of Products. The product that has a feature becomes the master. So whenever the Master is added, the feature can be added.

Feature is just the name of the bundle, but actual contents of the bundle are stored in Options object.

Options can be added from related list of the Features record. Options are references to the products to be included in the bundle.

Apart from just adding the products in the Bundles, various configurations can be added like predefining the quantity and whether the Quantity can be edited while adding the products in the Quote or it has to be fixed, whether the Product is mandatory or not, whether the product has to be selected by default in the bundle etc.

Bundle proves to be one of the most useful feature of the CPQ.

Alternative for xib in swift3 iOS

Hi all,

Lets see the simplest and best way to replace or avoid use of xib by using UIView on storyboard.

 

  1.  Go on storyboard ,select Viewcontroller Drag UIView and drop it between FirstResponder and exit button on that.
  2.  Add IBOutlet of that UIView on ViewController.swift file.
  3.  set the center, width, height for that UIView
  4.  Refer Following code :

 

——– IBOutlet ——–

@IBOutlet var View_alternativeForXib: UIView!

var view_BGDimmer = UIView()

    

——– Set the center , width, height for that UIView as well as add transperent Background view ———

 

       View_alternativeForXib.center = (UIApplication.shared.keyWindow?.center)!

          view_BGDimmer.frame = (UIApplication.shared.keyWindow?.frame)!

         View_alternativeForXib.frame.size.width = (UIApplication.shared.keyWindow?.frame.width)! – 40

         View_alternativeForXib.frame.origin.x = (UIApplication.shared.keyWindow?.frame.origin.x)! + 20

          view_BGDimmer.backgroundColor =  colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)

          view_BGDimmer.alpha = 0.3

          UIApplication.shared.keyWindow?.addSubview(view_BGDimmer)

          UIApplication.shared.keyWindow?.insertSubview(self.View_alternativeForXib, aboveSubview: self.view_BGDimmer)

          UIView.animate(withDuration: 0.1, animations: {

          }) { (completed) in

          }

 

——-  To dismiss view ——

   func dimissPopUp() {

        UIView.animate(withDuration: 0.2, animations: {

            self.view_BGDimmer.alpha = 0.0

            self.View_alternativeForXib.removeFromSuperview()

            self.view.layoutIfNeeded()

        }) { (completed) in

            self.view_BGDimmer.removeFromSuperview()

        }

    }

 

 

Thanks,

 

 

Save and Load from KeyChain | Swift 4

import Cocoa

import Security

// see https://stackoverflow.com/a/37539998/1694526

// Arguments for the keychain queries

let kSecClassValue = NSString(format: kSecClass)

let kSecAttrAccountValue = NSString(format: kSecAttrAccount)

let kSecValueDataValue = NSString(format: kSecValueData)

let kSecClassGenericPasswordValue = NSString(format: kSecClassGenericPassword)

let kSecAttrServiceValue = NSString(format: kSecAttrService)

let kSecMatchLimitValue = NSString(format: kSecMatchLimit)

let kSecReturnDataValue = NSString(format: kSecReturnData)

let kSecMatchLimitOneValue = NSString(format: kSecMatchLimitOne)

public class KeychainService: NSObject {

    class func updatePassword(service: String, account:String, data: String) {

        if let dataFromString: Data = data.data(using: String.Encoding.utf8, allowLossyConversion: false) {

            // Instantiate a new default keychain query

            let keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPasswordValue, service, account, kCFBooleanTrue, kSecMatchLimitOneValue], forKeys: [kSecClassValue, kSecAttrServiceValue, kSecAttrAccountValue, kSecReturnDataValue, kSecMatchLimitValue])

            let status = SecItemUpdate(keychainQuery as CFDictionary, [kSecValueDataValue:dataFromString] as CFDictionary)

            if (status != errSecSuccess) {

                if let err = SecCopyErrorMessageString(status, nil) {

                    print(“Read failed: \(err)”)

                }

            }

        }

    }

    class func removePassword(service: String, account:String) {

        // Instantiate a new default keychain query

        let keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPasswordValue, service, account, kCFBooleanTrue, kSecMatchLimitOneValue], forKeys: [kSecClassValue, kSecAttrServiceValue, kSecAttrAccountValue, kSecReturnDataValue, kSecMatchLimitValue])

        // Delete any existing items

        let status = SecItemDelete(keychainQuery as CFDictionary)

        if (status != errSecSuccess) {

            if let err = SecCopyErrorMessageString(status, nil) {

                print(“Remove failed: \(err)”)

            }

        }

    }

    class func savePassword(service: String, account:String, data: String) {

        if let dataFromString = data.data(using: String.Encoding.utf8, allowLossyConversion: false) {

            // Instantiate a new default keychain query

            let keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPasswordValue, service, account, dataFromString], forKeys: [kSecClassValue, kSecAttrServiceValue, kSecAttrAccountValue, kSecValueDataValue])

            // Add the new keychain item

            let status = SecItemAdd(keychainQuery as CFDictionary, nil)

            if (status != errSecSuccess) {    // Always check the status

                if let err = SecCopyErrorMessageString(status, nil) {

                    print(“Write failed: \(err)”)

                }

            }

        }

    }

    class func loadPassword(service: String, account:String) -> String? {

        // Instantiate a new default keychain query

        // Tell the query to return a result

        // Limit our results to one item

        let keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPasswordValue, service, account, kCFBooleanTrue, kSecMatchLimitOneValue], forKeys: [kSecClassValue, kSecAttrServiceValue, kSecAttrAccountValue, kSecReturnDataValue, kSecMatchLimitValue])

        var dataTypeRef :AnyObject?

        // Search for the keychain items

        let status: OSStatus = SecItemCopyMatching(keychainQuery, &dataTypeRef)

        var contentsOfKeychain: String?

        if status == errSecSuccess {

            if let retrievedData = dataTypeRef as? Data {

                contentsOfKeychain = String(data: retrievedData, encoding: String.Encoding.utf8)

            }

        } else {

            print(“Nothing was retrieved from the keychain. Status code \(status)”)

        }

        return contentsOfKeychain

    }

}

You need to imagine the following wired up to a text input field and a label, then having four buttons wired up, one for each of the methods.

class ViewController: NSViewController {

    @IBOutlet weak var enterPassword: NSTextField!

    @IBOutlet weak var retrievedPassword: NSTextField!

    let service = “myService”

    let account = “myAccount”

    // will only work after

    @IBAction func updatePassword(_ sender: Any) {

        KeychainService.updatePassword(service: service, account: account, data: enterPassword.stringValue)

    }

    @IBAction func removePassword(_ sender: Any) {

        KeychainService.removePassword(service: service, account: account)

    }

    @IBAction func passwordSet(_ sender: Any) {

        let password = enterPassword.stringValue

        KeychainService.savePassword(service: service, account: account, data: password)

    }

    @IBAction func passwordGet(_ sender: Any) {

        if let str = KeychainService.loadPassword(service: service, account: account) {

            retrievedPassword.stringValue = str

        }

        else {retrievedPassword.stringValue = “Password does not exist” }

    }

}


Need more help?

Hi there, was your problem or query resolved? If not & need more assistance, please do reach out to us at info@nanostuffs.com, we'll be more than delighted to help. Nanostuffs has 7+ years of extensive Salesforce & iOS/Android experience.
Holler Box