Send SMS with Twilio in Swift - ios

I try to use Twilio as an service provider but they have no examples for Swift that I understand.
My task is to send SMS to a number using Twilio API with Swift.
I have a Twilio.com account - and that one is working. But how do I do this in Swift code in a easy manner.
Twilio does provide a library - but that is meant for C# not for Swift (and using a bridging header seems too complicated!)
Here is the C# example, I need a easy Swift example.
// Download the twilio-csharp library from twilio.com/docs/csharp/install
using System;
using Twilio;
class Example
{
static void Main(string[] args)
{
// Find your Account Sid and Auth Token at twilio.com/user/account
string AccountSid = "AC5ef8732a3c49700934481addd5ce1659";
string AuthToken = "{{ auth_token }}";
var twilio = new TwilioRestClient(AccountSid, AuthToken);
var message = twilio.SendMessage("+14158141829", "+15558675309", "Jenny please?! I love you <3", new string[] {"http://www.example.com/hearts.png"});
Console.WriteLine(message.Sid);
}
}

Twilio evangelist here.
To send a text message from Swift you can just make a request directly to Twilios REST API. That said, I would not recommend doing this from an iOS app (or any other client app) as it requires you to embed your Twilio account credentials in the app, which is dangerous. I would instead recommend sending the SMS from a server side application.
If you do want to send the message from your app, there are a couple of Swift libraries I know of that simplify making HTTP requests:
Alamofire - from Mattt Thompson, creator of AFNetworking - used in the example here: https://www.twilio.com/blog/2016/11/how-to-send-an-sms-from-ios-in-swift.html
SwiftRequest - from Ricky Robinett of Twilio
To make the request using SwiftRequest, it would look like this:
var swiftRequest = SwiftRequest();
var data = [
"To" : "+15555555555",
"From" : "+15555556666",
"Body" : "Hello World"
];
swiftRequest.post("https://api.twilio.com/2010-04-01/Accounts/[YOUR_ACCOUNT_SID]/Messages",
auth: ["username" : "[YOUR_ACCOUNT_SID]", "password" : "YOUR_AUTH_TOKEN"]
data: data,
callback: {err, response, body in
if err == nil {
println("Success: \(response)")
} else {
println("Error: \(err)")
}
});
Hope that helps.

recently I have gone through Twilio docs and few SO post.
you can send SMS with following code snip in Swift 2.0
func sendSMS()
{
let twilioSID = "your Sender ID here"
let twilioSecret = "your token id here"
//Note replace + = %2B , for To and From phone number
let fromNumber = "%2B14806794445"// actual number is +14803606445
let toNumber = "%2B919152346132"// actual number is +919152346132
let message = "Your verification code is 2212 for signup with <app name here> "
// Build the request
let request = NSMutableURLRequest(URL: NSURL(string:"https://\(twilioSID):\(twilioSecret)#api.twilio.com/2010-04-01/Accounts/\(twilioSID)/SMS/Messages")!)
request.HTTPMethod = "POST"
request.HTTPBody = "From=\(fromNumber)&To=\(toNumber)&Body=\(message)".dataUsingEncoding(NSUTF8StringEncoding)
// Build the completion block and send the request
NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: { (data, response, error) in
print("Finished")
if let data = data, responseDetails = NSString(data: data, encoding: NSUTF8StringEncoding) {
// Success
print("Response: \(responseDetails)")
} else {
// Failure
print("Error: \(error)")
}
}).resume()
}
if everything goes fine..You should receive message like this..

Here is the new Swift example for Passwordless authentication. For the complete tutorial, Click Here
let url = "http://localhost:8000"
var swiftRequest = SwiftRequest()
var params:[String:String] = [
"token" : token!.text
]
swiftRequest.post(url + "/user/auth/", data: params, callback: {err, response, body in
if( err == nil && response!.statusCode == 200) {
if((body as NSDictionary)["success"] as Int == 1) {
self.showAlert("User successfully authenticated!");
} else {
self.showAlert("That token isn't valid");
}
} else {
self.showAlert("We're sorry, something went wrong");
}
})

If You are using server side Swift with Perfect.org
See this Blog
http://perfecttwilio.blogspot.in

The answer by "Devin Rader" is perfect. For any other users like me, the following is the full converted code for SwiftRequest for swift 3.0. The original code is by Ricky Robinett.
Please let us know if any errors.
Thankx..
//
// SwiftRequest.swift
// SwiftRequestTest
//
// Created by Ricky Robinett on 6/20/14.
// Copyright (c) 2015 Ricky Robinett. All rights reserved.
//
// ***********************************************************
//
// Modification for Swift 3.0 by Sanjay Sampat on 21.Jun.2017
//
// ***********************************************************
import Foundation
public class SwiftRequest {
var session = URLSession.shared
public init() {
// we should probably be preparing something here...
}
// GET requests
public func get(url: String, auth: [String: String] = [String: String](), params: [String: String] = [String: String](), callback: ((_ err: NSError?, _ response: HTTPURLResponse?, _ body: AnyObject?)->())? = nil) {
let qs = dictToQueryString(data: params)
request(options: ["url" : url, "auth" : auth, "querystring": qs ], callback: callback )
}
// POST requests
public func post(url: String, data: [String: String] = [String: String](), auth: [String: String] = [String: String](), callback: ((_ err: NSError?, _ response: HTTPURLResponse?, _ body: AnyObject?)->())? = nil) {
let qs = dictToQueryString(data: data)
request(options: ["url": url, "method" : "POST", "body" : qs, "auth" : auth] , callback: callback)
}
// Actually make the request
func request(options: [String: Any], callback: ((_ err: NSError?, _ response: HTTPURLResponse?, _ body: AnyObject?)->())?) {
if( options["url"] == nil ) { return }
var urlString = options["url"] as! String
if( options["querystring"] != nil && (options["querystring"] as! String) != "" ) {
let qs = options["querystring"] as! String
urlString = "\(urlString)?\(qs)"
}
let url = NSURL(string:urlString)
let urlRequest = NSMutableURLRequest(url: url! as URL)
if( options["method"] != nil) {
urlRequest.httpMethod = options["method"] as! String
}
if( options["body"] != nil && options["body"] as! String != "" ) {
var postData = (options["body"] as! String).data(using: String.Encoding.ascii, allowLossyConversion: true)
urlRequest.httpBody = postData
urlRequest.setValue("\(postData!.count)", forHTTPHeaderField: "Content-length")
}
// is there a more efficient way to do this?
if( options["auth"] != nil && (options["auth"] as! [String: String]).count > 0) {
var auth = options["auth"] as! [String: String]
if( auth["username"] != nil && auth["password"] != nil ) {
let username = auth["username"]
let password = auth["password"]
var authorization = "\(username!):\(password!)"
if let data = authorization.data(using: String.Encoding.utf8) {
//authorization = "Basic " + data.base64EncodedString(options: [])
authorization = "Basic " + data.base64EncodedString()
}
urlRequest.setValue(authorization, forHTTPHeaderField: "Authorization")
}
}
let task = session.dataTask(with: urlRequest as URLRequest, completionHandler: {body, response, err in
let resp = response as! HTTPURLResponse?
if( err == nil) {
if let gotResponse = response {
if(gotResponse.mimeType == "text/html") {
let bodyStr = NSString(data: body!, encoding:String.Encoding.utf8.rawValue)
return callback!(err as NSError?, resp, bodyStr)
} else if(gotResponse.mimeType == "application/xml") {
let bodyStr = NSString(data: body!, encoding:String.Encoding.utf8.rawValue)
return callback!(err as NSError?, resp, bodyStr)
} else if(gotResponse.mimeType == "application/json") {
// ss pending
do {
let jsonAnyObject:AnyObject = try JSONSerialization.jsonObject(with: (body! as NSData) as Data, options: JSONSerialization.ReadingOptions.mutableContainers) as! [String: AnyObject] as AnyObject
return callback!(err as NSError?, resp, jsonAnyObject as AnyObject);
} catch _ {
}
}
}
}
return callback!(err as NSError?, resp, body as AnyObject)
})
task.resume()
}
func request(url: String, callback: ((_ err: NSError?, _ response: HTTPURLResponse?, _ body: AnyObject?)->())? = nil) {
request(options: ["url" : url ], callback: callback )
}
private func dictToQueryString(data: [String: String]) -> String {
var qs = ""
for (key, value) in data {
let encodedKey = encode(value: key)
let encodedValue = encode(value: value)
qs += "\(encodedKey)=\(encodedValue)&"
}
return qs
}
private func encode(value: String) -> String {
let queryCharacters = NSCharacterSet(charactersIn:" =\"#%/<>?#\\^`{}[]|&+").inverted
if let encodedValue:String = value.addingPercentEncoding(withAllowedCharacters: queryCharacters) {
return encodedValue
}
//let encodedValue:String = value.stringByAddingPercentEncodingWithAllowedCharacters(queryCharacters)!
return value
}
}
Sample code to use above class as mentioned by "Devin Rader"
let URL = "https://api.twilio.com/2010-04-01/Accounts/\(myUserIdForBulkSmsMessageSending)/Messages"
var swiftRequest = SwiftRequest();
var data = [
"To" : "+\(replaceNumberToSendSms)",
"From" : "+\(replaceNumberFromSendSms)",
"Body" : message,
"MediaUrl" : theUrlEncodedMessage
];
//print( "=========VV==========" )
//print( "URL: \(URL) " )
//print( "data: \(String(describing: data))" )
//print( "auth: \(myUserIdForBulkSmsMessageSending) \(myUserPasswordForBulkSmsMessageSending)")
//print( "=====================" )
swiftRequest.post(url: URL,
data: data,
auth: ["username" : myUserIdForBulkSmsMessageSending, "password" : myUserPasswordForBulkSmsMessageSending],
callback: {err, response, body in
if err == nil {
print("Success: \(String(describing: response))")
if let currentBody = body {
// SSTODO PENDING TO HANDLE SUCCESS OF TWILLO OR ERRORS HANDLING OF TWILLO.
//print( "=====================" )
//print( " currentBody: \(currentBody) " )
//print( " currentBodyString: \(String(describing: currentBody)) ")
//print( "=========^^==========" )
}
} else {
print("Error: \(String(describing: err))")
}
});

Swift 3 version:
func sendSMS()
{
print("Starting...")
let twilioSID = "ENRET YOUR SID"
let twilioSecret = "YOUR TOKEN"
//Note replace + = %2B , for To and From phone number
let fromNumber = "%29999999"// actual number is +9999999
let toNumber = "%29999999"// actual number is +9999999
let message = "Your verification code is 2212 for signup with"
// Build the request
let request = NSMutableURLRequest(url: URL(string:"https://\(twilioSID):\(twilioSecret)#api.twilio.com/2010-04-01/Accounts/\(twilioSID)/SMS/Messages")!)
request.httpMethod = "POST"
request.httpBody = "From=\(fromNumber)&To=\(toNumber)&Body=\(message)".data(using: .utf8)
// Build the completion block and send the request
URLSession.shared.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) in
print("Finished")
if let data = data, let responseDetails = NSString(data: data, encoding: String.Encoding.utf8.rawValue) {
// Success
print("Response: \(responseDetails)")
} else {
// Failure
print("Error: \(error)")
}
}).resume()
}

Related

WebService API Method in Swift 3 and Swift 4?

I am new to Swift iOS and i want to create a separate method in separate class(like NSObject) of web services so that i can use it in any ViewController and parse any type of JSON response using NSURLSession and Alamofire . Could someone help me.
class WebRequester: NSObject {
static let shared = WebRequester()
let session = URLSession.shared
func request(urlStr:String, parameter:String, token:String? = nil, callback:#escaping (_ result:NSDictionary?, error:Error?) -> Void) {
let url = URL(string: BaseURL + urlStr)
debugPrint("=====================")
debugPrint(url ?? "")
debugPrint(parameter)
debugPrint("=====================")
var request = URLRequest(url: url!)
request.httpMethod = "POST"
request.httpBody = parameter.data(using: String.Encoding.utf8)
print("Token :", (token ?? ""))
request.setValue(token, forHTTPHeaderField: "Authorization")
let task = session.dataTask(with: request) { (data, response, error) in
DispatchQueue.main.async {
if error == nil {
do {
let jsonObj = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.allowFragments)
if let dic = jsonObj as? NSDictionary {
callback(dic, error)
}
}
catch {
callback(nil, error)
}
}
else {
callback(nil, error)
}
}
}
task.resume()
}
}
You need to pass parameter as string
var params = "user_id=" + "12"
params += "&course_id=" + "1"
WebRequester.shared.request(urlStr: urlStr, parameter: params) { (result, error) in
DispatchQueue.main.async {
print(result)
}
}
you can also pass parameter as dictionary but need to convert in string using following Dictionary extension
request.httpBody = parameter.stringFromHttpParameters().data(using:
String.Encoding.utf8)
extension Dictionary {
func stringFromHttpParameters() -> String {
let parameterArray = self.map { (key, value) -> String in
let percentEscapedKey = (key as! String).addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
let percentEscapedValue = (value as AnyObject).addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
return "\(percentEscapedKey)=\(percentEscapedValue)"
}
return parameterArray.joined(separator: "&")
}
}
WebRequester
Http Request
multipart with single image
multipart with multiple image
You need to change response structure as per your api response
you need to set authorisation and api key as per your api
WebRequester
Here is a working code of Alamofire (swift 4)
Add this class in your project
import Foundation
import UIKit
import Alamofire
import SystemConfiguration
class APPWebService: NSObject {
class open func callPostApi(api:String, parameters:[String:AnyObject]?, complition:#escaping (AnyObject)->Void)
{
if self.IsInternetAvailable() == false {
self.showAlert(title: "Whoops :(", message: "No internet connection.")
return
}
let parameters = parameters
// Encode Data
let base64EncodedString = toBase64EncodedString(toJsonString(parameters: parameters!))
Alamofire.request(api, method: .post, parameters: ["jsondata":base64EncodedString])
.response { response in
do {
if response.error != nil{
print(response.error as Any, terminator: "")
}
if let jsonDict = try JSONSerialization.jsonObject(with: (response.data as Data?)!, options: []) as? [String: AnyObject]{
print(jsonDict as Any, terminator: "")
complition(jsonDict as AnyObject)
}else{
self.showAlert(title: "Whoops", message: "Something went wrong. Please, try after sometime.")
return
}
} catch _ {
print("Exception!")
}
}
}
// For check Internet Connection
class open func IsInternetAvailable () -> Bool {
var zeroAddress = sockaddr_in()
zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress))
zeroAddress.sin_family = sa_family_t(AF_INET)
let defaultRouteReachability = withUnsafePointer(to: &zeroAddress) {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {zeroSockAddress in
SCNetworkReachabilityCreateWithAddress(nil, zeroSockAddress)
}
}
var flags = SCNetworkReachabilityFlags()
if !SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) {
return false
}
let isReachable = flags.contains(.reachable)
let needsConnection = flags.contains(.connectionRequired)
return (isReachable && !needsConnection)
}
// Display Alert
class open func showAlert(title:String,message:String){
let alert = UIAlertView(title:title,message: "\n" + message,delegate: nil ,cancelButtonTitle: "Ok")
alert.show()
}
// For Convert to JSON String
class open func toJsonString(parameters:[String:AnyObject]) -> String
{
var jsonData: NSData?
do {
jsonData = try JSONSerialization.data(withJSONObject: parameters, options:JSONSerialization.WritingOptions(rawValue: 0)) as NSData?
} catch{
print(error.localizedDescription)
jsonData = nil
}
let jsonString = NSString(data: jsonData! as Data, encoding: String.Encoding.utf8.rawValue)! as String
return jsonString
}
// For Convert to Base64Encoded String
class open func toBase64EncodedString(_ jsonString : String) -> String
{
let utf8str = jsonString.data(using: .utf8)
let base64Encoded = utf8str?.base64EncodedString(options: [])
return base64Encoded!
}
}
Use Like this
func ServiceCall()
{
// Create parameter list
let parameters = [
"name":"Abc",
"address":"Xyz",
"contact":"1234567890"
]
// set webservice Url
let ReqURL = "your webservice url here"
APPWebService.callPostApi(api: ReqURL, parameters: parameters as [String : AnyObject]?) { (dict) -> Void in
print(dict) // Your response is here.
}
}

app creates Stripe customers but can't get ephemeral key due to "no such customer"

From my iOS app, I'm calling Firebase to 1) create a Stripe customer (and this works, I get a valid looking customer ID back) and 2) get the ephemeral key.
The second part is where things are failing. The error I get back looks like this:
message = "No such customer: \"cus_CFRA95y1cKuNH7\"";
param = customer;
requestId = "req_TKAARUJqcDqecK";
statusCode = 400;
type = "invalid_request_error";
Because I'm successfully creating and able to view customer IDs in the dashboard, I'm pretty convinced I have the correct test publishable key in my iOS app and the correct secret key in my Firebase .js file. I do have "viewing test data" set to "ON" in my Stripe dashboard.
If you eyeball the below code, do you see anything wrong here?
index.js
const functions = require('firebase-functions');
const stripe_key = "sk_test_y1otMY_SECRET_KEY"
var stripeFire = require("stripe-fire")(stripe_key);
// The Firebase Admin SDK to access the Firebase Realtime Database.
const admin = require('firebase-admin');
var stripe = require('stripe')(stripe_key);
admin.initializeApp(functions.config().firebase);
exports.newCustomer = functions.https.onRequest((req, res) => {
console.log("Creating new customer account...")
var body = req.body
stripe.customers.create(
{ email: body.email }
).then((customer) => {
console.log(customer)
// Send customerId -> Save this for later use
res.status(200).json(customer.id)
}).catch((err) => {
console.log('error while creating new customer account' + err)
res.status(400).send(JSON.stringify({ success: false, error: err }))
});
});
// Express
exports.StripeEphemeralKeys = functions.https.onRequest((req, res) => {
const stripe_version = req.body.api_version;
const customerId = req.body.customerId
if (!stripe_version) {
console.log('I did not see any api version')
res.status(400).end()
return;
}
stripe.ephemeralKeys.create(
{customer: customerId},
{stripe_version: stripe_version}
).then((key) => {
console.log("Ephemeral key: " + key)
res.status(200).json(key)
}).catch((err) => {
console.log('stripe version is ' + stripe_version + " and customer id is " + customerId + " for key: " + stripe_key + " and err is " + err.message )
res.status(500).json(err)
});
});
on the Swift side, in MyAPIClient.swift:
func createNewCustomer(withAPIVersion apiVersion : String, completion: #escaping STPJSONResponseCompletionBlock)
{
// using our Facebook account's e-mail for now...
let facebookDictionary = FacebookInfo.sharedInstance.graphDictionary
if let facebookemail = facebookDictionary["email"] as? String {
guard let key = Stripe.defaultPublishableKey() , !key.contains("#") else {
let error = NSError(domain: StripeDomain, code: 50, userInfo: [
NSLocalizedDescriptionKey: "Please set stripePublishableKey to your account's test publishable key in CheckoutViewController.swift"
])
completion(nil, error)
return
}
guard let baseURLString = self.baseURLString, let baseURL = URL(string: baseURLString) else {
print("something broken... what should I do?")
// how about some kind of error in the second parameter??
completion(nil, nil)
return
}
let path = "newCustomer"
let url = baseURL.appendingPathComponent(path)
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let parameters = ["email" : facebookemail]
do {
request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted)
} catch let error {
print("error while serialization parameters is \(error.localizedDescription)")
}
let task = self.session.dataTask(with: request) { (data, urlResponse, error) in
if let actualError = error {
print("error from createNewCustomer API is \(actualError)")
}
if let httpResponse = urlResponse as? HTTPURLResponse {
print("httpResponse is \(httpResponse.statusCode)")
if (httpResponse.statusCode == 200)
{
// eventually we'll want to get this into an actual complex JSON response / structure
if let actualData = data
{
if let customerIDString = String(data: actualData, encoding: .utf8) {
print("customer id string is \(customerIDString)")
let defaults = UserDefaults.standard
let originalcustomerid = defaults.string(forKey: "CustomerID")
if customerIDString != originalcustomerid
{
defaults.set(customerIDString, forKey: "CustomerID")
defaults.set(facebookemail, forKey: "CustomerEmail")
}
}
}
self.createCustomerKey(withAPIVersion: apiVersion, completion: completion)
}
} else {
assertionFailure("unexpected response")
}
}
task.resume()
}
}
func createCustomerKey(withAPIVersion apiVersion: String, completion: #escaping STPJSONResponseCompletionBlock)
{
// first, let's see if we have a valid customer ID for the facebook e-mail we're using
if weHaveCustomerIDSaved() == false
{
createNewCustomer(withAPIVersion: apiVersion, completion: completion)
return
}
guard let key = Stripe.defaultPublishableKey() , !key.contains("#") else {
let error = NSError(domain: StripeDomain, code: 50, userInfo: [
NSLocalizedDescriptionKey: "Please set stripePublishableKey to your account's test publishable key in CheckoutViewController.swift"
])
completion(nil, error)
return
}
guard let baseURLString = baseURLString, let baseURL = URL(string: baseURLString) else {
print("something broken... what should I do?")
// how about some kind of error in the second parameter??
completion(nil, nil)
return
}
let defaults = UserDefaults.standard
if let customerid = defaults.string(forKey: "CustomerID")
{
let path = "StripeEphemeralKeys"
let url = baseURL.appendingPathComponent(path)
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let parameters = ["api_version" : apiVersion, "customerId" : customerid]
do {
request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted)
} catch let error {
print("error while serialization parameters is \(error.localizedDescription)")
}
let task = self.session.dataTask(with: request) { (data, urlResponse, error) in
if let httpResponse = urlResponse as? HTTPURLResponse {
print("httpResponse is \(httpResponse.statusCode)")
} else {
assertionFailure("unexpected response")
}
if let actualError = error {
print("error from EphemeralKey API is \(actualError)")
}
DispatchQueue.main.async {
do {
if let actualData = data
{
if let json = try JSONSerialization.jsonObject(with: actualData) as? [AnyHashable : Any]
{
print("json is \(json)")
completion(json, nil)
}
}
} catch let error {
print("error from json \(error.localizedDescription)")
}
}
}
task.resume()
}
}
Here's my Firebase dashboard
And my Stripe customer tab, showing the customer account I created is really there...
Lastly, here's a log of a typical ephemeral key transaction:
Use cus_CFRA95y1cKuNH7, not \" cus_CFRA95y1cKuNH7 \"
You don't need the \" before and after your customerId. The customerId that Stripe needs should looks like cus_CFRA95y1cKuNH7 instead of you sending \"cus_CFRA95y1cKuNH7\". And that should work after all.
The error message should look like No such customer: cus_CFRA95y1cKuNH7; not "No such customer: \"cus_CFRA95y1cKuNH7\"";

POST body values are not recognized

I am calling a POST API but the post values are not getting recognised.
I am using alamofire for API handling
public func POSTRequest(postData : AnyObject?,APIName : String?,headers: HTTPHeaders?,success:#escaping (JSON) -> Void, failure:#escaping (String,String) -> Void)
{
let url = URL(string: APIName!)!
var urlRequest = URLRequest(url: url)
urlRequest.httpBody = postData as? Data
urlRequest.httpMethod = "POST"
urlRequest.allHTTPHeaderFields = headers
let manager = Alamofire.SessionManager.default
manager.session.configuration.timeoutIntervalForRequest = 30.0
manager.request(urlRequest).responseJSON { ( responseData) -> Void in
if responseData.result.isSuccess {
let statusCode = responseData.response?.statusCode
if(statusCode == 200){
let resJson = JSON(responseData.result.value!)
success(resJson)
}
else {
let resJson = JSON(responseData.result.value!)
let errorMsg = resJson["message"].stringValue
let errorTitle = resJson["title"].stringValue
failure(errorMsg,errorTitle)
}
}
if responseData.result.isFailure {
let error : Error = responseData.result.error!
failure(error.localizedDescription,"")
}
}
}
// MARK: Login
func userLogin(postData: AnyObject, completionHandler:#escaping (JSON) -> Void,failure:#escaping (String,String) -> Void)
{
let apiName = GlobalConstants.rootUrl + GlobalConstants.loginUrl
let httpHeaders: HTTPHeaders = getHeaders()
ApiRequestHandler.shared.POSTRequest(postData: postData, APIName: apiName, headers: httpHeaders, success: { (JSON) in
print("JSON \(JSON)")
completionHandler(JSON)
})
{ (Errormsg,ErrorTitle) in
print("Error \(Errormsg)")
failure(Errormsg,ErrorTitle)
}
}
I am creating the post data here
let postDataDct = NSMutableDictionary()
postDataDct.setValue(self.userNameTextField.text, forKey: "username")
postDataDct.setValue(self.phoneNumberTextField.text, forKey: "mobile")
guard let data = try? JSONSerialization.data(withJSONObject:
postDataDct , options: JSONSerialization.WritingOptions.prettyPrinted)
as NSData else {
return;
}
print(NSString(data: data as Data, encoding:
String.Encoding.utf8.rawValue)! as String)
header creation here
func getHeaders() -> HTTPHeaders {
let headers: HTTPHeaders = ["Content-Type": "application/json" ,"Authorization" : "Basic dGFuaXNocWdfgaFF%waXJvb3Q6dzBEMFlkSnR0"]
return headers
}
I am calling the login method here
ApiManager.shared.userLogin(postData: postDataDct as AnyObject, completionHandler: { (JSON) in
print(JSON)
})
{ (ErrorMsg, ErrorTitle) in
print(ErrorMsg)
}
Please help me to find the issue.
API is giving me error response, saying user name or password is empty.
For Posting Alamofire have its own Parameters Class Try to use that like this with make share using the exact keys as on server.
let parameter: Parameters = [
"Email": txtfld_email.text!,
"Password": txtfld_password.text!
]
Cross check your keys:
let postDataDct = NSMutableDictionary()
postDataDct.setValue(self.userNameTextField.text, forKey: "username")
postDataDct.setValue(self.phoneNumberTextField.text, forKey: "mobile")
You are making the request with username and mobile It seems like the keys will be username and password according to the response you are getting name or password is empty.
let postDataDct = NSMutableDictionary()
postDataDct.setValue(self.userNameTextField.text, forKey: "username")
postDataDct.setValue(self.phoneNumberTextField.text, forKey: "password")
Suggestion:
Don't use NSMutableDictionary in Swift, use its native Swift
counterpart, Dictionary

Send Nested JSON With POST Request iOS Swift 3

I want to send JSON to Server with POST request but i did not understand how i do this. I select friends from table view and show these friends in my Collection view. And the selected peoples shows in collection views and their email are sent in JSON to Create group. Here is my code written in Swift.
#IBAction func createGroupButton(_ sender: Any) {
let groupName = groupNameTextField.text
let adminEmail = UserDefaults.standard.value(forKey: "userEmail")
if groupName == "" {
alertMessage(msg: "Enter Group name")
}
else if base64String == nil {
alertMessage(msg: "Select Group Image")
}
else if emailArray.isEmpty {
alertMessage(msg: "Select atleast one person")
}
else {
if isNetAvailable {
var emailData: String?
print("email data \(emailArray)")
for i in emailArray {
emailData = "\"email\":\"\(i)\""
}
let postData = "\"name\":\"\(groupName!)\",\"adminemail\":\"\(adminEmail!)\",\"image\":\"\(base64String!)\",\"emailArray\":\"\(emailData!)\""
let postDat = "jsondata={\(postData)}"
print("Post Data \(postDat)")
let urlString = create_group
let url = URL(string: urlString)
var request = URLRequest(url: url!)
request.httpMethod = "POST"
request.httpBody = postDat.data(using: String.Encoding.utf8)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let session = URLSession.shared
let task = session.dataTask(with: request) { (data, response, error) in
if error != nil {
print("Something wrong with creating Group")
}
if data == nil {
print("Nil Data")
}
if response == nil {
print("Nil Response")
}
if response != nil {
let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
print("Response String is \(responseString)")
}
}
task.resume()
}
else {
alertMessage(msg: "Internet Not Available")
}
}
}
Here is my API
<?php
if($_SERVER["REQUEST_METHOD"] !="POST"){ exit; }
require_once 'dbcon.php';
if (!empty($_POST['jsondata']))
{
$configjson = $_POST['jsondata'];
$config = json_decode($configjson, true);
$groupname = $config['name'];
$adminemail = $config['adminemail'];
$image = $config['image'];
$queryemailcheck = "SELECT * FROM groups_name WHERE admin = '$adminemail' AND groupname = '$groupname'";
$selectquery = mysqli_query($connect, $queryemailcheck);
$totalemails= mysqli_num_rows($selectquery);
if($totalemails>0)
{
echo "Already exist";
}
else {
$queryinsert= "INSERT INTO groups_name(admin , groupname , pic ) VALUES('$adminemail' ,'$groupname' , '$image')";
if(mysqli_query($connect, $queryinsert)){
echo "Successfully Saved";
}else{
echo "Error: " ;
}
$members = $config['emailArray'];
foreach($members as $row ){
$email = $row['email'];
$queryinsert2= "INSERT INTO group_members(groupname , member , status ) VALUES('$groupname' ,'$email' , '0')";
if(mysqli_query($connect, $queryinsert2)){
echo "Successfully Saved";
}else{
echo "Error: " ;
}
}
}
}
else echo "post data is empty";
?>
You can use Alamofire library for handling your webservices. like
Alamofire.request(logoutUrl, method: .post, parameters: dict, encoding: JSONEncoding.default, headers:["Authorization":"Bearer \(accessToken)", "Accept":"application/json", "Content-Type":"application/json; charset=UTF-8"]).responseJSON { (response) in
let json:JSON = JSON(response.result.value)
let status = json["status"].stringValue
let statusCode = response.response?.statusCode
Create network handler class where you can hit webservices from all of your app.
func makeHttpPostRequest(uri:String, postBody:Dictionary<String, Any> ,Completion:#escaping (_ response: AnyObject, _ success: Bool) -> Void) {
let networkCheck = self.getNetworkStatus()
if networkCheck == false {
Completion("NO internet connection." as AnyObject,false)
return
}//end network check block
var urlRequest = self.makeHttpRequestWithUrl(url: uri)
urlRequest.httpMethod = "POST"
urlRequest.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
urlRequest.setValue("application/json", forHTTPHeaderField: "Accept")
//check and set authorization header
if (UserDefaults.standard.object(forKey: AppConstant.KAppAuthenticationToken) != nil) {
let authToken = UserDefaults.standard.object(forKey: AppConstant.KAppAuthenticationToken) as! String
urlRequest.setValue("Token token="+authToken, forHTTPHeaderField: "Authorization")
}
//let postData = [self.addDefultParameters(detailDict: postBody)]
let jsonData = try? JSONSerialization.data(withJSONObject: postBody)
urlRequest.httpBody = jsonData
//create connection
self.httpConnectionWithRequest(request: urlRequest, Completion: Completion)
}
func makeHttpRequestWithUrl(url: String) -> URLRequest {
let urlString = AppConstant.baseUrl+url
let networkUrlRequest = URLRequest.init(url: URL.init(string: urlString)!, cachePolicy: .reloadIgnoringCacheData, timeoutInterval: 50)
return networkUrlRequest
}
func httpConnectionWithRequest(request: URLRequest, Completion:#escaping (_ response: AnyObject, _ success: Bool) -> Void) {
let session = URLSession.shared
// make the request
let task = session.dataTask(with: request) {
(data, response, error) in
// check for any errors
guard error == nil else {
print("error is: " + String.init(format: "%#", error?.localizedDescription as! CVarArg))
Completion(error!.localizedDescription as String as AnyObject, false)
return
}
// make sure we got data
guard let responseData = data else {
print("Error: did not receive data")
Completion("didn't get response data" as String as AnyObject, false)
return
}
let responseString = String.init(data: responseData, encoding: .utf8)
// parse the result as JSON, since that's what the API provides
if let resp = response as? HTTPURLResponse{
if (UserDefaults.standard.object(forKey: AppConstant.KAppAuthenticationToken) != nil) {
if resp.statusCode == 401{
//auth token expired
self.makeRequestWithNewToken(request: request, Completion: Completion)
}
}
//check if response is Array or dictionary
var jsonArray:[Any]?
var jsonDict:[String:Any]?
// response is in array
do{
jsonArray = try JSONSerialization.jsonObject(with: responseData, options: [])as? [Any]
}catch{
print("response doesn't contain array")
}
//response is in dictionary
do{
jsonDict = try JSONSerialization.jsonObject(with: responseData, options: [])as? [String:Any]
}catch{
print("response doesn't contain dict")
}
//=====
// if resp.statusCode == 200{
if jsonArray != nil{
Completion(jsonArray! as AnyObject, true)
return
}
if jsonDict != nil{
Completion(jsonDict! as AnyObject, true)
return
}
Completion("didn't get response data" as String as AnyObject, false)
return
}
}
task.resume()
}
And through the completion handler you will get the fetched data.

Expression resolves to an unused function (Swift)

I am new to swift programming and need bit of your help forgive me if i am asking something stupid. I am trying call a function from my UIViewController for a POST request to API. Calling function is like this
#IBAction func actionStartSignIn(sender: AnyObject) {
let email: String = txtEmail.text!
let password: String = txtPassword.text!
if !email.isEmpty && !password.isEmpty && General.isValidEmail(email) && password.characters.count>6{
var request = RequestResponse()
request.email = email
request.password = password
let isValid = NSJSONSerialization.isValidJSONObject(request)
print(isValid)
var requestBody: String = ""
// Facing issue in following line
RequestManager.sharedInstance.postRequest(Constants.BASE_URL + Constants.LOGIN, body: requestBody, onCompletion: {(json: JSON) in{
let result = json["response"]
print(result)
}
}
)
}
}
And Called Function is like this
func postRequest(route: String, body: String, onCompletion: (JSON) -> Void) {
makeHTTPPostRequest(route, requestBody: body, onCompletion: { json, err in
onCompletion(json as JSON)
})
}
Further,
// MARK: Perform a POST Request
private func makeHTTPPostRequest(path: String, requestBody: String, onCompletion: ServiceResponse) {
let request = NSMutableURLRequest(URL: NSURL(string: path)!)
// Set the method to POST
request.HTTPMethod = "POST"
do {
// Set the POST body for the request
// let jsonBody = try NSJSONSerialization.dataWithJSONObject(body, options: .PrettyPrinted)
// request.HTTPBody = jsonBody
request.HTTPBody = requestBody.dataUsingEncoding(NSUTF8StringEncoding);
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
if let jsonData = data {
let json:JSON = JSON(data: jsonData)
onCompletion(json, nil)
} else {
onCompletion(nil, error)
}
})
task.resume()
}/* catch {
// error
onCompletion(nil, nil)
}*/
}
and
typealias ServiceResponse = (JSON, NSError?) -> Void
I am facing "Expression resolves to an unused function" while calling
RequestManager.sharedInstance.postRequest(Constants.BA‌​SE_URL + Constants.LOGIN, body: requestBody, onCompletion: {(json: JSON) in{ let result = json["response"] print(result) } } )
May be i am missing some basic syntax. Any help will be really appreciated.
Thank You.
Remove the { } phase after the in will solve the problem.
It should look like this:
RequestManager.sharedInstance.postRequest(Constants.BASE_URL + Constants.LOGIN, body: requestBody, onCompletion: {(json: JSON) in
let result = json["response"]
print(result)
}
)
For the closure param, you should not type it by yourself to prevent typo. Use tab key to select that param, then press enter, xCode will auto generate the code for you.
If use the way I just said, the trailing closure will look like this:
RequestManager.sharedInstance.postRequest(Constants.BASE_URL + Constants.LOGIN, body: requestBody) { (json) in
let result = json["response"]
print(result)
}

Resources