1

Can anyone suggest me how to make a rest api call for Mac OS Application using Swift 4 And Cocoa. I tried lots of ways but unable to make the api call.

Here is the code:

func callAPI(){

    let AuthorizationToken = "Basic mykey="
    var request = URLRequest(url: URL(string: "http://myipaddress/api/Batch")!)
    request.httpMethod = "GET"
    request.addValue("application/json", forHTTPHeaderField: "Content-Type")
    request.setValue(AuthorizationToken, forHTTPHeaderField: "Authorization")
    let session = URLSession.shared
    let task = session.dataTask(with: request, completionHandler: { data, response, error -> Void in
        //print(response!)
        do {
            let json = try JSONSerialization.jsonObject(with: data!)
            print(json)
            self.ApiValue.stringValue = "Success"
        } catch {
            print("error")
            self.ApiValue.stringValue = "Error"
        }
    })

    task.resume()

}

See the info.plist

Bishnu Das
  • 161
  • 2
  • 14
  • @Moritz , "Thread 6: Fatal error: Unexpectedly found nil while unwrapping an Optional value" I am getting this exception. – Bishnu Das Oct 04 '18 at 05:53
  • If `data` is `nil` then `error` is not `nil`. Handle the error and print it. And in the `catch` clause print also the `error` instance rather than a meaningless literal string. – vadian Oct 04 '18 at 07:37

4 Answers4

3

in Xcode 11 .1 +

Set Capabilities - Under App Sandbox - Check both Incoming Connects and Outgoing Connections:

You can try this code to check in your viewDidLoad:

override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        let session = URLSession.shared
        let url = URL(string: "https://pokeapi.co/api/v2/")!

        let task = session.dataTask(with: url) { data, response, error in

            if error != nil || data == nil {
                print("Client error!")
                return
            }


            do {
                let json = try JSONSerialization.jsonObject(with: data!, options: [])
                print(json)
            } catch {
                print("JSON error: \(error.localizedDescription)")
            }
        }

        task.resume()
    }
Di Nerd Apps
  • 770
  • 8
  • 15
0

data from server side is nil, that's why you get error like

Unexpectedly found nil while unwrapping an Optional value

It's not a good idea to use force unwrapping for Optional value

I've tested your code and see issue:

Transport security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file.

You can fix it with adding this code into plist:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
    <key>NSExceptionDomains</key>
    <dict>
        <key>example.com</key>
        <dict>
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <true/>
            <key>NSIncludesSubdomains</key>
            <true/>
        </dict>
    </dict>
</dict>

More info you can find here

I've tested code with updating of plist file and got this json from server side without any errors:

{
        batchID = BA000000015;
        code = 2015;
        coordinatorName = "<null>";
        createdBy = Suc19320182015;
        createdByID = LU000000011;
        createdOn = "2018-08-14T06:37:43";
        endDate = "2018-08-14T00:00:00";
        name = SSDG;
        schoolID = BS00001;
        startDate = "2018-08-14T00:00:00";
        status = 1;
        updatedBy = Suc19320182015;
        updatedOn = "2018-08-14T06:37:51";
    }
Vadim Nikolaev
  • 2,132
  • 17
  • 34
0

Just as a temporary hack, just delete the NSExceptionDomains key and everything underneath it. Then re-test and see if it works.

Please keep in mind, this completely disables the ATS security and it's not recommended. Realistically, you should have a proper domain for your server and reference it with the correct domain in the NSExceptionDomains key (instead of the example.com).

Shawn
  • 406
  • 4
  • 12
  • Actually I have inserted my server IP address instead of that example.com , is it ok ? – Bishnu Das Oct 05 '18 at 08:53
  • I don't have any domain in my server instead of APIs – Bishnu Das Oct 05 '18 at 09:09
  • Did you try without a NSExceptionDomains key? Did it work? Then, you can try to enter an ip address but I'm not sure that will work. The documentation seems to imply an ip address wouldn't work but I haven't tried it. – Shawn Oct 06 '18 at 15:51
  • I tried without a NSExceptionDomains key, but still it was showing exception releted to domain. – Bishnu Das Oct 08 '18 at 05:05
0

I solved it. In new update of swift the NSAppTransportSecurity configuration is needed. I added following code to my info.plist file.

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
    <key>NSExceptionDomains</key>
    <dict>
        <key>yourdomain.com</key>
        <dict>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
            <false/>
        </dict>
    </dict>
</dict>

Then also have to allow the network incoming and outgoing connection in AppSandBox->Capabilities, then all set.

Bishnu Das
  • 161
  • 2
  • 14