iOS Swift / Wordpress API - POST to custom fields user registration? - ios

When users register on my app, a user is created inside my Wordpress installation as well. I'm using Alamofire and the Wordpress API to accomplish this. That said, my user is created successfully, but for some reason any custom fields I have on the registration form aren't filled by my below code. The only fields that are filled properly are username, email and password.
How can I make it so that I'm able to POST data to custom fields on the registration form? Oddly, first_name & last_name are Wordpress fields (not custom) and data isn't saved to those either despite me POSTing to them.
My code below:
ViewController
// CREATE THE USER ACCOUNT IN WORDPRESS
#IBAction func registerNow(_ sender: Any) {
let params: Parameters = [
"username": emailAddress.text!,
"password": passwordField.text!,
"email": emailAddress.text!,
"nickname": firstName.text!,
"last_name": lastName.text!,
"first_name": firstName.text!,
"phone_number": phoneNumber.text!
]
AF.request("http://myurl.com/wp-json/wp/v2/users/register", method: .post, parameters: params, encoding: JSONEncoding.default, headers: nil).validate(statusCode: 200 ..< 299).responseJSON { AFdata in
do {
guard let jsonObject = try JSONSerialization.jsonObject(with: AFdata.data!) as? [String: Any] else {
print("Error: Cannot convert data to JSON object")
return
}
guard let prettyJsonData = try? JSONSerialization.data(withJSONObject: jsonObject, options: .prettyPrinted) else {
print("Error: Cannot convert JSON object to Pretty JSON data")
return
}
guard let prettyPrintedJson = String(data: prettyJsonData, encoding: .utf8) else {
print("Error: Could print JSON in String")
return
}
print(prettyPrintedJson)
} catch {
print("Error: Trying to convert JSON data to string")
return
}
}
}

The WordPress Core REST API does not include a user registration endpoint.
Endpoint list for Users: https://developer.wordpress.org/rest-api/reference/users/
There is a Create a User (POST /wp/v2/users) endpoint, but only logged-in admin users can add users on that endpoint if they have the create_users capability.
So the endpoint you specified is your own code. Thus, the error must be looked for primarily in that PHP code.
Your related question and the answer: WordPress Rest API - Register user - fields not saving?

Related

Alamofire.uploadmultipartFormData with JSONEncoding.default (Swift)

i have to send photo and json to server.
my json is :
{"anticorona":"Anti_Covid","time":"Time","navigateds":[{"collection_public_key":"Origin_Station.collection_public_key","station_public_key":"Origin_Station.public_key"},{"station_public_key":"Des_Station.public_key","collection_public_key":"Des_Station.collection_public_key"}],"seats":"Seats","date":"Date"}
how can i send this json with Alamofire.uploadmultipartFormData
i know i can use encoding: JSONEncoding.default in Alamofire.request but can in use JSONEncoding.default when use Alamofire.uploadmultipartFormData?
thanks
You seem to be new and it would be nice if you could perhaps add some code you have tried in future questions of yours. Anyways, as far as I can see this should be possible in the following way. I am assuming the key "navigateds" remains the same. Otherwise you could also check if the value (in the for-in-loop) is an array, too:
// set parameters for request
let antiCoronaParameters: Parameters = [
"anticorona" : "Anti_Covid",
"time":"Time",
"navigateds":[
["collection_public_key":"Origin_Station.collection_public_key", "station_public_key":"Origin_Station.public_key"],
["station_public_key":"Des_Station.public_key", "collection_public_key":"Des_Station.collection_public_key"]
],
"seats":"Seats",
"date":"Date"
]
let upload = AF.upload(multipartFormData: { (formData) in
// I would append file data here first
for (key, value) in antiCoronaParameters {
if key == "navigateds" {
do {
let arrayData = try JSONSerialization.data(withJSONObject: value, options: .prettyPrinted)
formData.append(arrayData, withName: key)
} catch {
print("could not append array, failed with error:", error)
}
} else if let string = value as? String, let stringData = string.data(using: String.Encoding.utf8, allowLossyConversion: false) {
formData.append(stringData, withName: key)
} else {
print("could not append some data in parameters")
}
}
}, to: "https://www.yourURLhere.com/link.php", method: .post).validate()
upload.responseString { (responseString) in
print(responseString)
}
This answer is based on this question. In the future, I would recommend trying lots of keywords relating to your question. Initially, searching for questions will consume more time but you will get the hang of it soon enough I'm sure. Just keep trying a little more next time maybe ;)
However, as you already mentioned there's another way, too, and I prepared it for you if you would like to check it out. You essentially mentioned it already and I'd always prefer it over the upload unless there's a very good reason:
// set parameters for request
let antiCoronaParameters: Parameters = [
"anticorona" : "Anti_Covid",
"time":"Time",
"navigateds":[
["collection_public_key":"Origin_Station.collection_public_key", "station_public_key":"Origin_Station.public_key"],
["station_public_key":"Des_Station.public_key", "collection_public_key":"Des_Station.collection_public_key"]
],
"seats":"Seats",
"date":"Date"
]
// request with json encoded parameters (e.g. sending to php)
let antiCoronaRequest = AF.request("https://www.yourURLhere.com/link.php", method: .post, parameters: antiCoronaParameters, encoding: JSONEncoding.default).validate()
antiCoronaRequest.responseString(completionHandler: { (response) in
print(response)
})
Hit me up if you have any questions.

How to get facebook feed with images and videos along with text?

I want to fetch logged user feeds within ios app, I have try with graph api that, graph api returns the data, its fine.
But when I have cross check the data to the actual facebook feed on facebook user page there are some problems found:
If post has text only than text coming on message key, along with post id,
If post has text with image/video only text coming on message key
And if post has only image/video than message key not coming.
I know message key is only for description/text but images? Is there any way to get the feed with whole content just same as appeared on facebook.
I have try below code:
For Login
FBSDKLoginManager().logOut()
FBSDKLoginManager().logIn(withReadPermissions: ["email", "public_profile", "user_posts"], from: self) { (result, error) in
if error != nil {
print("failed to start graph request: \(String(describing: error))")
return
}
// self.getPosts()//old
self.getFBPost()
}
For getFBPost
func getFBPost() {
FBSDKGraphRequest(graphPath: "/me/feed", parameters: nil)?.start(completionHandler: { (fbConnectionErr, result, error) in
// print(fbConnectionErr)
print(result)
//print(error)
})
}
Coming response like this:
{
"data": [
{
"message": "https://medium.com/frame-io-engineering/huge-images-small-phone-15414b30d39e",
"created_time": "2018-12-03T13:59:01+0000",
"id": "68288174406_653966194"
},
{
"created_time": "2018-12-01T13:43:02+0000",
"id": "68288174406_6528518443724"
},
{
"message": "I love my Mom",
"created_time": "2018-11-30T13:27:38+0000",
"id": "68288174406_652289420323"
}
}
as you can see the second post has only id and created time, while we check this on facebook page this the post with image, and third post has video but only text coming from graph api
Please guide whats wrong I did? Or What should I do to getting whole feed data in json formate just same as appeared on facebook?
You are not asking for any fields in the API call, so you only get default ones. It is called "Declarative Fields" (/me?fields=message,created_time,...) and came with v2.4:
https://developers.facebook.com/docs/graph-api/changelog/archive#v2_4_new_features
https://developers.facebook.com/docs/graph-api/using-graph-api/#reading
I have read the give doc that are shared by #luschn. And got the solution I forgot the declarative fields as #luschn suggest me, Now solution given below: Only need to change in the graph api,
FBSDKGraphRequest(graphPath: "/me/feed", parameters: ["fields":"created_time,attachments,type,message"])?.start(completionHandler: { (fbConnectionErr, result, error) in
print(fbConnectionErr)
print(result)
print(error)
let re = result as? [String: Any]
let data = re?["data"] as! [[String: Any]]
for dict in data {
print(dict)
}
})
OR
If you have page id you can use below url to hit the get api.
https://graph.facebook.com/(api_version)/(page_id)?fields=feed{created_time,attachments,message}&access_token=(token_id)

Save data in specific user id iOS - Alamofire, Json

I have a job application app that when a user registers through a registration page, it is automatically generating a unique user_id for each user. This app also supports multiple different data for each user (e.g education details, experience etc) so these data have to be connected with the user id of the corresponding user.
For example, suppose user A registers a new account with user_id ABCD. When this user adds new information to the system, the data have to be linked back to this user_id, ABCD. Likewise, if a user B registers a new account with user_id EFGH, any new data added to the system by user B, the data have to be linked back to his/her user_id, EFGH.
How could I do that in iOS using Swift?
Alamofire.request(URL_USER_COMPANY_PROFILE, method: .post, parameters: parameters).responseJSON
{
response in
// Printing response
print(response)
// Getting the json value from the server
if let result = response.result.value {
// Converting it as NSDictionary
let jsonData = result as! NSDictionary
UserDefaults.standard.value(forKey: "user_id")
}
}
I found the answer with iPhone developer # Muhammed Azharuddin, by creating a class for user defaults to store datas in user_id
extension UserDefaults{
static let isLoggedIn = "com.xyz.AlotTest1isLoggedIn"
static let userId = "com.xyz.AlotTest1userId"
}
And call this extension in parameters after #IBAction
let parameters: Parameters=[
"institute_name":univ.text!,
"degree_name":grad.text!,
"start_year":cityP.text!,
"end_year":enYear.text!,
"degree_city":proj.text!,
"degree_country":eduCountry.text!,
"user_id" : AuthService.instance.userId ?? ""
]
print(parameters)
//Sending http post request
Alamofire.request(URL_USER_EDUCATION, method: .post, parameters: parameters).responseJSON
{
response in
//printing response
print(response)
//getting the json value from the server
if let result = response.result.value {
let re = UserDefaults.standard.value(forKey: "user_id") as! Array<Parameters>
print(result)
let defaults: UserDefaults = UserDefaults.standard
//This class variable needs to be defined every class where you set or fetch values from NSUserDefaults
}

Siesta REST login

How to translate my login user URLSession code into Siesta framework code? My current attempt isn't working.
I've looked at the example in the GithubBrowser but the API I have doesn't work like that.
The issue is that the user structure is kind of split by how the endpoint in the API I'm consuming works. The endpoint is http://server.com/api/key. Yes, it really is called key and not user or login. Its called that by the authors because you post a user/pass pair and get a key back. So it takes in (via post) a json struct like:
{"name": "bob", "password": "s3krit"}
and returns as a response:
{"token":"AEWasBDasd...AAsdga"}
I have a SessionUser struct:
struct SessionUser: Codable
{
let name: String
let password: String
let token: String
}
...which encapsulates the state (the "S" in REST) for the user. The trouble is name & password get posted and token is the response.
When this state changes I do my:
service.invalidateConfiguration() // So requests get config change
service.wipeResources() // Scrub all unauthenticated data
An instance is stored in a singleton, which is picked up by the configure block so that the token from the API is put in the header for all other API requests:
configure("**") {
// This block ^ is run AGAIN when the configuration is invalidated
// even if loadManifest is not called again.
if let haveToken = SessionManager.shared.currentUser?.token
{
$0.headers["Authorization"] = haveToken
}
}
That token injection part is already working well, by the way. Yay, Siesta!
URLSession version
This is bloated compared to Siesta, and I'm now not using this but here is what it used to be:
func login(user: SessionUser, endpoint: URL)
{
DDLogInfo("Logging in: \(user.name) with \(user.password)")
let json: [String: Any] = ["name": user.name, "password": user.password]
let jsonData = try? JSONSerialization.data(withJSONObject: json)
var request = URLRequest(url: endpoint)
request.httpMethod = "POST"
request.httpBody = jsonData
_currentStatus = .Unknown
weak var welf = self
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else {
handleLogin(error: error, message: "No data from login attempt")
return
}
let jsonData:Any
do {
jsonData = try JSONSerialization.jsonObject(with: data, options: [])
}
catch let jsonDecodeError {
handleLogin(error: jsonDecodeError, message: "Could not get JSON from login response data")
return
}
guard let jsonDecoded = jsonData as? [String: Any] else {
handleLogin(error: error, message: "Could not decode JSON as dictionary")
return
}
guard let token = jsonDecoded["token"] as? String else {
handleLogin(error: error, message: "No auth token in login response")
return
}
let newUser = SessionUser(name: user.name, password: "", token: token)
welf?.currentUser = newUser
welf?.saveCurrentSession()
welf?._currentStatus = .LoggedIn
DDLogInfo("User \(newUser.name) logged in")
loginUpdate(user: newUser, status: .LoggedIn, message: nil, error: nil)
}
task.resume()
}
Siesta Version
Here is my attempt right now:
func login(user: String, pass: String, status: #escaping (String?) -> ())
{
let json = [ "name": user, "password": pass]
let req = ManifestCloud.shared.keys.request(.post, json: json)
req.onSuccess { (tokenInfo) in
if let token = tokenInfo.jsonDict["token"] as? String
{
let newUser = SessionUser(name: user, password: pass, token: token)
self.currentUser = newUser
}
status("success")
}
req.onFailure { (error) in
status(error.userMessage)
}
req.onCompletion { (response) in
status(nil)
}
}
Its sort of working, but the log in credentials are not saved by Siesta and I've had to rig up a new notification system for login state which I'd hoped Siesta would do for me.
I want to use Siesta's caching so that the SessionUser object is cached locally and I can use it to get a new token, if required, using the cached credentials. At the moment I have a jury-rigged system using UserDefaults.
Any help appreciated!
The basic problem here is that you are requesting but not loading the resource. Siesta draws a distinction between those two things: the first is essentially a fancied-up URLSession request; the second means that Siesta hangs on to some state and notifies observers about it.
Funny thing, I just answered a different but related question about this a few minutes ago! You might find that answer a helpful starting point.
In your case, the problem is here:
let req = ManifestCloud.shared.keys.request(.post, json: json)
That .request(…) means that only your request hooks (onSuccess etc.) receive a notification when your POST request finishes, and Siesta doesn’t keep the state around for others to observe.
You would normally accomplish that by using .load(); however, that creates a GET request and you need a POST. You probably want to promote your POST to be a full-fledge load request like this:
let keysResource = ManifestCloud.shared.keys
let req = keysResource.load(using:
keysResource.request(.post, json: json))
This will take whatever that POST request returns and make it the (observable) latestData of ManifestCloud.shared.keys, which should give you the “notification system for login state” that you’re looking for.

Spotify sdk trackFromData method not working in swift

I have requested the current user and from the user have requested the saved tracks of the user. When making the call to the api it succeeds and I am able to convert the response into a Spotify track object, but when I access the fields of the object the values come back as the default values. I parsed this response in the same manner as I did to get the current user but it didn't work this time. Any ideas on the cause?
let savedTracksRequestHeaders: HTTPHeaders = [
"Authorization": "Bearer " + accessToken!,
]
let params = ["limit": "1"]
var userSong = SPTTrack.init()
Alamofire.request("https://api.spotify.com/v1/me/tracks", method:
.get, parameters: params, headers:
savedTracksRequestHeaders).responseJSON { response in
print("Saved Track Response")
debugPrint(response)
do {
// executes with no errors
try userSong = SPTTrack.init(from: response.data, with:
response.response)
print("user songs")
// when the variable is used all fields are default
// values
print(userSong.popularity)
} catch is Error {
print("load songs failed")
}
}

Resources