I'm trying to parse information from a php, but i need to send a dictionary parameter so i try things ... i saw tutorials,examples but i'm stuck so i went back to the start: (What it's the good way for do this?)
func asd(){
let urlPath = "http://xxxxx.php"
let url: NSURL = NSURL(string: urlPath)
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "GET"
var parm = ["id_xxxx": "900"] as Dictionary
//I THINK MY PROBLEM IT'S HERE! i dont know how to link parm with session, i try is with session.uploadTaskWithRequest(<#request: NSURLRequest?#>, fromData: <#NSData?#>) but doesn't work
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url, completionHandler: {data, response, error -> Void in
println("Task completed")
if(error) {
// If there is an error in the web request, print it to the console
println(error.localizedDescription)
}
var err: NSError?
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as NSDictionary
if(err?) {
// If there is an error parsing JSON, print it to the console
println("JSON Error \(err!.localizedDescription)")
}
println(jsonResult.debugDescription)
let results: NSArray = jsonResult["x"] as NSArray
dispatch_async(dispatch_get_main_queue(), {
self.tableData = results
self.OfertaGridViewLista!.reloadData()
})
})
task.resume()
}
Thanks!
GET data needs to be part of the url's query string. Some methods will accept a dictionary of parameters for POST/PUT requests, but these methods will not add the dictionary to the url for you if you're using the GET method.
If you'd like to keep your GET parameters in a Dictionary for cleanliness or consistency, consider adding a method like the following to your project:
func buildQueryString(fromDictionary parameters: [String:String]) -> String {
var urlVars:[String] = []
for (k, value) in parameters {
let value = value as NSString
if let encodedValue = value.addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlQueryAllowed) {
urlVars.append(k + "=" + encodedValue)
}
}
return urlVars.isEmpty ? "" : "?" + urlVars.joined(separator: "&")
}
This method will take a dictionary of key/value pairs and return a string you can append to your url.
For example, if your API requests allow for multiple request methods (GET/POST/etc.) you'll only want to append this query string to your base api url for GET requests:
if (request.HTTPMethod == "GET") {
urlPath += buildQueryString(fromDictionary: parm)
}
If you're only making GET requests, there's no need to check for which method you'll be using to send your data.
Bit crazy that none of the answers here suggest using NSURLComponents and NSURLQueryItem objects. That is the safest and most modern way to do this.
var iTunesSearchURL = URLComponents(string: "https://itunes.apple.com/search")!
iTunesSearchURL.queryItems = [URLQueryItem(name: "term", value: trackName),
URLQueryItem(name: "entity", value: "song"),
URLQueryItem(name: "limit", value: "1")]
let finalURL = iTunesSearchURL.url
#paul-mengelt's answer in Objective C:
-(NSString *) buildQueryStringFromDictionary:(NSDictionary *)parameters {
NSString *urlVars = nil;
for (NSString *key in parameters) {
NSString *value = parameters[key];
value = [value stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
urlVars = [NSString stringWithFormat:#"%#%#=%#", urlVars ? #"&": #"", key, value];
}
return [NSString stringWithFormat:#"%#%#", urlVars ? #"?" : #"", urlVars ? urlVars : #""];
}
Adapted for Swift 3
static func buildQueryString(fromDictionary parameters: [String:String]) -> String {
var urlVars:[String] = []
for (k,value) in parameters {
if let encodedValue = value.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) {
urlVars.append(k + "=" + encodedValue)
}
}
return urlVars.isEmpty ? "" : "?" + urlVars.joined(separator: "&")
}
fixed objective C function
+(NSString *)buildQueryStringFromDictionary:(NSDictionary *)parameters
{
NSString *urlVars = #"";
for (NSString *key in parameters)
{
NSString *value = parameters[key];
value = [value stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
urlVars = [NSString stringWithFormat:#"%#%#%#=%#", urlVars, urlVars.length ? #"&": #"", key, value];
}
return [NSString stringWithFormat:#"%#%#", urlVars ? #"?" : #"", urlVars ? urlVars : #""];
}
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"url_to_your_web_service.php/?key=%#",value]];
NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject];
NSURLSessionDataTask * dataTask = [defaultSession dataTaskWithURL:url
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if(error == nil){
NSString * text = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
NSLog(#"Data = %#",text);
}
}
}
];
[dataTask resume];
retrieve key's value inside your php:
$value=$_GET['key'];
Related
I'm looking to extract only the link from this string and create a new string with that link, but I'm not sure of the best way to go about doing so. If anyone could enlighten me on how I can do this effectively I would greatly appreciate it!
String
{
"timestamp": 1509507857555,
"profileId": "e58d7f751c7f498085a79a37bf22f20b",
"profileName": "Rhidlor",
"textures": {
"SKIN": {
"url": "http://textures.minecraft.net/texture/1137b867b4a2fb593cf6d05d8210937cc78bc9e0558ad63d41cc8ec2f99e7d63"
}
}
}
Your given string is JSON. You can get url from given JSON is like this :
struct Response: Decodable {
var textures: [String: Textures]
}
struct Textures: Decodable {
var url: String
}
let jsonStr = """
{"timestamp":1509507857555,"profileId":"e58d7f751c7f498085a79a37bf22f20b","profileName":"Rhidlor","textures":{"SKIN":{"url":"http://textures.minecraft.net/texture/1137b867b4a2fb593cf6d05d8210937cc78bc9e0558ad63d41cc8ec2f99e7d63"}}}
"""
let data = jsonStr.data(using: .utf8)!
let decoder = JSONDecoder()
do {
let jsonData = try decoder.decode(Response.self, from: data)
if let skin = jsonData.textures["SKIN"] {
print(skin.url)
}
}
catch {
print("error:\(error)")
}
You can use these ways for fetch an url inside of any String.
Swift4
let testString: String = "{\"timestamp\":1509507857555,\"profileId\":\"e58d7f751c7f498085a79a37bf22f20b\",\"profileName\":\"Rhidlor\",\"textures\":{\"SKIN\":{\"url\":\"http://textures.minecraft.net/texture/1137b867b4a2fb593cf6d05d8210937cc78bc9e0558ad63d41cc8ec2f99e7d63\"}}}"
let pat = "http?://([-\\w\\.]+)+(:\\d+)?(/([\\w/_\\.]*(\\?\\S+)?)?)?"
let regex = try! NSRegularExpression(pattern: pat, options: [])
let matches = regex.matches(in: testString, options: [], range: NSRange(location: 0, length: LGSemiModalNavViewController.characters.count))
var matchedUrls = [String]()
for match in matches {
let url = (htmlSource as NSString).substring(with: match.range)
matchedUrls.append(url)
}
print(matchedUrls)
Objective - C
NSString *testString = #"{\"timestamp\":1509507857555,\"profileId\":\"e58d7f751c7f498085a79a37bf22f20b\",\"profileName\":\"Rhidlor\",\"textures\":{\"SKIN\":{\"url\":\"http://textures.minecraft.net/texture/1137b867b4a2fb593cf6d05d8210937cc78bc9e0558ad63d41cc8ec2f99e7d63\"}}}";
NSError *error;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"http?://([-\\w\\.]+)+(:\\d+)?(/([\\w/_\\.]*(\\?\\S+)?)?)?" options:NSRegularExpressionCaseInsensitive error:&error];
NSArray *arrayOfAllMatches = [regex matchesInString:testString options:0 range:NSMakeRange(0, [testString length])];
NSMutableArray *arrayOfURLs = [NSMutableArray new];
for ( NSTextCheckingResult *match in arrayOfAllMatches ) {
NSString *substringForMatch = [testString substringWithRange:match.range];
NSLog(#"Extracted URL: %#", substringForMatch);
[arrayOfURLs addObject:substringForMatch];
}
NSLog(#"%#",arrayOfURLs);
Trying to consume web service in iOS using JSON but end up with the above error in the last.. not sure why that's happening..
// Just Convert NSData to String
NSString *String = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"responseObject:%#",String);
Try correcting your do and catch..
import UIKit
class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
#IBOutlet weak var lbl_studentID: UILabel!
#IBOutlet weak var image: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func btnfunc_getStudentID(sender: UIButton) {
let data:String = "http://neo4j.nannasgroup.com/service.php"
let url:NSURL = NSURL.init(string: data)!
let req:NSURLRequest = NSURLRequest.init(URL: url)
let res:AutoreleasingUnsafeMutablePointer<NSURLResponse?>=nil
do {
let dataVal = try NSURLConnection.sendSynchronousRequest(req, returningResponse: res)
do {
if let jsonResult = try NSJSONSerialization.JSONObjectWithData(dataVal, options: []) as? NSMutableArray {
lbl_studentID.text = "\(jsonResult)"
}
} catch let error as NSError {
print(error.localizedDescription)
}
} catch let error as NSError {
print("incatch" + error.localizedDescription)
}
}
#IBAction func selectPicture(sender: UIButton) {
let ImagePicker = UIImagePickerController()
ImagePicker.delegate = self
ImagePicker.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
self.presentViewController(ImagePicker, animated: true, completion: nil)
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
image.image = info[UIImagePickerControllerOriginalImage] as? UIImage
self.dismissViewControllerAnimated(true, completion: nil)
}
#IBAction func upload_request(sender: UIButton) {
}
}
I got the same issue OS_dispatch_data in Objective C when I tried to make a post request to the API and got some response. When I tried to print data that I received from API it printed OS_dispatch_data: data[0x2813d9800] = { leaf, size = 442, buf = 0x103825200 }.
This was due to some error with the data from API side.
Explanation With Example:-
I was working on 3DES Encryption and Decryption when I encountered this issue. I was unable to use the data received from API for decryption which was encrypted at the server side.
Decryption Code:
-(NSString *)tripleDesDecryptData:(NSData *)input
key:(NSString *)key
error:(NSError **)error
{
NSParameterAssert(input);
NSParameterAssert(key);
NSData *inputData = input;
NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
size_t outLength;
NSAssert(keyData.length == kCCKeySize3DES, #"the keyData is an invalid size");
NSMutableData *outputData = [NSMutableData dataWithLength:(inputData.length + kCCBlockSize3DES)];
CCCryptorStatus
result = CCCrypt(kCCDecrypt, // operation
kCCAlgorithm3DES, // Algorithm
kCCOptionPKCS7Padding | kCCOptionECBMode, // options
keyData.bytes, // key
keyData.length, // keylength
nil,// iv
inputData.bytes, // dataIn
inputData.length, // dataInLength,
outputData.mutableBytes, // dataOut
outputData.length, // dataOutAvailable
&outLength); // dataOutMoved
if (result != kCCSuccess) {
if (error != NULL) {
*error = [NSError errorWithDomain:#"com.your_domain.your_project_name.your_class_name."
code:result
userInfo:nil];
}
return nil;
}
[outputData setLength:outLength];
NSString *tempString = [[NSString alloc] initWithData:outputData encoding:NSUTF8StringEncoding];
return tempString;
}
The data I received was encrypted JSON String. Since API returned base64 string, I could not use data directly for decryption in the above method (it failed). I first converted the data to string using -
NSString *jsonStringBase64 = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
Then I reconverted back to data that could be used in the above method using -
NSData *decodedData = [[NSData alloc] initWithBase64EncodedString:jsonStringBase64 options:0];
The decoded data was null. It was unable to convert back to data because the data was inaccurate or corrupt.
Then I changed options value from 0 to NSDataBase64DecodingIgnoreUnknownCharacters in the above code -
NSData *decodedData = [[NSData alloc] initWithBase64EncodedString:plainText options:NSDataBase64DecodingIgnoreUnknownCharacters];
Using NSDataBase64DecodingIgnoreUnknownCharacters solved my problem as it ignored the Unknown Characters.
From Apple:- Use the NSDataBase64DecodingIgnoreUnknownCharacters option to modify the decoding algorithm so that it ignores unknown non-Base64 bytes, including line ending characters.
Access paging in iOS Code from JSON previous and next link
In JSON object retrieved from graph api, due to loads of information the information is paged, when I try to access the previous and next link it gives OAuth error.
Can anyone help in how to access the link through objective C in iOS app.
I want to know two things - how to retrive 'N' items using --> limit=N
and how to open a FBSDKgraphrequest and using the paged link link (containing the paging information)
paging = {
next = "https://graph.facebook.com/v2.3/897401690298128/inbox?access_token=CAAEsxMhiSe4BACWnj27BT6ZBvj2BAxNZCtCNQyCKQORXyylXXkQy3DLSF75UGSz2FydAkQx6Pj49MOS0Q3SGiU1vkQ1iUEs2fQvvlwW3Wc04DEnXZB4CZCza7tOJfyncIPrkFrudQCeRhWUUREqMpCI8Dnm6Ozc6xmwOlT1uN2ZCgQ91llcVC1kV04fiZCqO6H6edFe2YZAUZBy86pw1p4SWCUvgMshzkvZBGgpG8UWG50ZCShdeQPUc86fsuQGOcAno0ZD&limit=25&until=1428241306&__paging_token=enc_AdC9127ZCBVnZACHUlMZBTC39ZC8bSP4ZA8uwQZBdy8xhsZAyKAcxxNdqn48Er3CrVM4DkJPATHhOYBVRm8FuCvYZBU8KSpZA";
previous = "https://graph.facebook.com/v2.3/897401690298128/inbox?access_token=CAAEsxMhiSe4BACWnj27BT6ZBvj2BAxNZCtCNQyCKQORXyylXXkQy3DLSF75UGSz2FydAkQx6Pj49MOS0Q3SGiU1vkQ1iUEs2fQvvlwW3Wc04DEnXZB4CZCza7tOJfyncIPrkFrudQCeRhWUUREqMpCI8Dnm6Ozc6xmwOlT1uN2ZCgQ91llcVC1kV04fiZCqO6H6edFe2YZAUZBy86pw1p4SWCUvgMshzkvZBGgpG8UWG50ZCShdeQPUc86fsuQGOcAno0ZD&limit=25&since=1432299972&__paging_token=enc_AdDp9ZCK2ZBP40AgTi4TCzaB0QFT1Cy7s1R7HLLDDaT7nbnLYDZB4LZBjiONOqG5QR9Q22KY1oU1LzNOwS5uNZBG7uLF4&__previous=1";
};
You can still use the SDK from Facebook, you only have to give the "after" field as a parameter. Then call a recursive function.
A solution I have just implemented in Swift:
func getFBTaggableFriends(nextCursor : String?, failureHandler: (error: NSError) -> Void) {
var qry : String = "me/taggable_friends"
var parameters = Dictionary<String, String>() as? Dictionary
if nextCursor == nil {
parameters = nil
} else {
parameters!["after"] = nextCursor
}
// Facebook: get taggable friends with pictures
var request = FBSDKGraphRequest(graphPath: qry, parameters: parameters)
request.startWithCompletionHandler { (connection : FBSDKGraphRequestConnection!, result : AnyObject!, error : NSError!) -> Void in
if ((error) != nil)
{
// Process error
println("Error: \(error)")
}
else
{
//println("fetched user: \(result)")
var resultdict = result as! NSDictionary
var data : NSArray = resultdict.objectForKey("data") as! NSArray
for i in 0..<data.count {
let valueDict : NSDictionary = data[i] as! NSDictionary
let id = valueDict.objectForKey("id") as! String
let name = valueDict.objectForKey("name") as! String
let pictureDict = valueDict.objectForKey("picture") as! NSDictionary
let pictureData = pictureDict.objectForKey("data") as! NSDictionary
let pictureURL = pictureData.objectForKey("url") as! String
println("Name: \(name)")
//println("ID: \(id)")
//println("URL: \(pictureURL)")
}
if let after = ((resultdict.objectForKey("paging") as? NSDictionary)?.objectForKey("cursors") as? NSDictionary)?.objectForKey("after") as? String {
self.getFBTaggableFriends(after, failureHandler: {(error) in
println("error")})
} else {
println("Can't read next!!!")
}
}
}
}
You will then call this function with:
getFBTaggableFriends(nil, failureHandler: {(error)
in println(error)});
Page information has the current access token, and also depending up different limits restriction paging values will always change , so; its best to use the url and fetch the result.
Because the result of next will also have pointer to both previous and next , best method to parse the result obtained is by calling it through a recursive function and passing the paging next values outside and inside the calling function to traverse all pages.
Don't forget to put a restriction where you want to stop traversing other nodes.
eg:
NSURL *url = [NSURL URLWithString:PagingNext];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *errorConnection)
{
if(errorConnection == nil)
{
NSError *error;
id result = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
if (result == nil)
{
NSLog(#"Error parsing JSON:\n%#",error.userInfo);
return;
}
//if no error then extract paging next and do what you want ->
/*
result = {
data[20],
paging={
previous= "URL_of_previous"
next = "URL_of_next"
}
}
*/
if ([result isKindOfClass:[NSDictionary class]])
{
NSArray * data = [result objectForKey:#"data"];
NSDictionary *paging =[result objectForKey:#"paging"];
NSString * resultPagingNext = [paging objectForKey:#"next"];
[self call_method_recursively_with_parameter_of_next_page:data pagingNext:resultPagingNext];
}
}
else
{
NSLog(#"Connection Error:\n%#", errorConnection.userInfo);
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:#"Network Issue"
message:#"Check if you are connected to Internet" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *okAction = [UIAlertAction actionWithTitle:#"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action)
{
NSLog(#"User has pressed OK."); }];
[alertController addAction:okAction];
[self presentViewController:alertController animated:YES completion:nil];
}
}];
I am trying to parse JSON result obtained from Playframewordk 1.2 into swift.
Playframework result:
public JsonObject getJson() {
JsonObject jsonObject = new JsonObject();
if (codeJson != null) {
for (String field : codeArticleFields) {
if (codeJson.has(field)) {
jsonObject.add(field, codeJson.get(field));
}
}
}
return jsonObject;
}
view playframework
#{extends 'main.html' /}
#{set title:'Test' /}
#{set 'moreScripts' }
#{/set}
${product?.getJson()}
Here is the code of swift:
func connectProductDatabase() {
let urlString = "http://api.autoidlabs.ch/test/" + "4025089060857"
let url: NSURL = NSURL(string: urlString)!
var request : NSMutableURLRequest = NSMutableURLRequest()
request.URL = url
request.HTTPMethod = "GET"
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue(), completionHandler: {
(response:NSURLResponse!, data: NSData!, error: NSError!) -> Void in
var error: NSError?
if let result = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &error)
as? NSArray {
let dataArray = result[0] as NSArray
println(dataArray)
} else {
let resultString = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Flawed JSON String: \(resultString)")
}
})
println("not connected")
}
As a result I am getting the entire file with all HTML tag. This is because it is not entering into the if statement. (I also tried with options:NSJSONReadingOptions.MutableContainers)
I tried with lot of result found from stackoverflow, but getting the same problem. If I understand well, the playframework view is not really returning a JSON, JsonObject of java is a formatted String as JSON.
How can I solve this problem?
I was able to solve the problem.
Instead of NSArray I used NSDictionary
if let result = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &error)
as? NSDictionary {
and then in playframework I used renderJSON instead of render.
So I'm trying to study up on HTTP/TCP/IP Protocols, Nodejs, MongoJS,and MongoDB all at once. So I'm trying to figure out a couple things with the Hapi Web Framework. I am able to communicate with the server with my iOS simulator however, I can't seem to parse the payload right. I understand I could use parameters in the URL to send the information but I would like to use the payload.
So I end up with this being saved into Mongo.
(
{
"_id" = 5431f161bb859872034d2456;
"{\"userLastNameKey\":\"Kwon\",\"userEmailKey\":\"email\",\"userFirstNameKey\":\"Michael\",\"userUsernameKey\":\"username\",\"userPasswordKey\":\"password\"}" = "";
},
{
"_id" = 5431fe5694ed4721046c1f8c;
"{\"userLastNameKey\":\"Kwon2\",\"userEmailKey\":\"email2\",\"userFirstNameKey\":\"Michael2\",\"userUsernameKey\":\"username2\",\"userPasswordKey\":\"password2\"}" = "";
This is my hapi code for the call.
// This will add a new user to the database
function addUser(request, response){
db.usersCollection.save(request.payload, function (err, saved){
if(err || !saved)
{
console.log("User not saved");
} else
{
console.log("User saved");
}
});
}
My end result I would like to try and get it to be like this
(
{
"_id" = 5431f161bb859872034d2456,
"userLastNameKey" = "Kwon",
"userEmailKey" = "email",
"userFirstNameKey"= "Michael",
"userUsernameKey" = "username",
"userPasswordKey" = "password",
}
)
Here's the iOS code
NSDictionary *userData = [User userToDictionary: newUserInfo];
NSData *userJSON = [NSJSONSerialization dataWithJSONObject: userData options: 0 error: nil];
NSURL *url = [NSURL URLWithString: urlString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL: url];
[request setHTTPMethod: #"POST"];
[request addValue: #"application/json" forHTTPHeaderField: #"Content-Type"];
// This will set up the url session
NSURLSessionConfiguration* config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration: config];
NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest: request fromData: userJSON completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if(error)
{
} else
{
}
}];
[uploadTask resume];
}
Anyone know how I can achieve this?
{
"_id" = 5431f161bb859872034d2456;
"userLastNameKey" = "Kwon";
"userEmailKey" = "email";
"userFirstNameKey"= "Michael";
"userUsernameKey" = "username";
"userPasswordKey" = "password";
}
That is NOT a JSON object. You need to use commas instead of semicolons. and colons instead of equals. Your ID is also not a decimal number so it's probably best to make it a string.
Your object would look like :
{
"_id" : "5431f161bb859872034d2456",
"userLastNameKey" : "Kwon",
"userEmailKey" : "email",
"userFirstNameKey" : "Michael",
"userUsernameKey" : "username",
"userPasswordKey" : "password"
}
To parse a (well-formatted) JSON string, use : var JSONObject = JSON.parse(JSONstring);