FBSDKGraphRequest cannot post image and text anymore (no more text) - xcode

I'm posting to a group user wall, (image and text). It have worked from a long time, and stop working recently(now, image are posted, but no text :( ). Any idea if there was a new way or rules? (no error reported)
[params setObject:sContent forKey:#"message"];
[params setObject:yourImageData forKey:#"picture"];
[[[FBSDKGraphRequest alloc]
initWithGraphPath:#"xxxxxxxxxxxxxxx/photos"
parameters: params
HTTPMethod:#"POST"]
startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
if (!error) {

Following is the working code for me(In Swift):
let params = ["message": "Test message", "sourceImage" : UIImagePNGRepresentation(UIImage(named: "test.jpg")!)!]
FBSDKGraphRequest(graphPath: "me/photos", parameters: params, HTTPMethod: "POST").startWithCompletionHandler({ (connection, result, error) -> Void in
guard let response = result else {
print("No response received")
if let errorInfo = error {
print("errorInfo: \(errorInfo)")
}
return }
print(response)
})
Check 'Publishing' section at the link for more.
Let me know if you have any difficulties to convert it to Objective-C.

Related

Swift URL POST request function with returning values [duplicate]

I am currently trying to download, parse and print JSON from an URL.
So far I got to this point:
1) A class (JSONImport.swift), which handles my import:
var data = NSMutableData();
let url = NSURL(string:"http://headers.jsontest.com");
var session = NSURLSession.sharedSession();
var jsonError:NSError?;
var response : NSURLResponse?;
func startConnection(){
let task:NSURLSessionDataTask = session.dataTaskWithURL(url!, completionHandler:apiHandler)
task.resume();
self.apiHandler(data,response: response,error: jsonError);
}
func apiHandler(data:NSData?, response:NSURLResponse?, error:NSError?)
{
do{
let jsonData : NSDictionary = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary;
print(jsonData);
}
catch{
print("API error: \(error)");
}
}
My problem is, that the data in
do{
let jsonData : NSDictionary = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary;
print(jsonData);
}
remains empty.
When I debug,the connection starts successfully, with the given url as a parameter. But my jsonData variable doesn't get printed. Instead the catch block throws the error, stating that there is no data in my variable:
API error: Error Domain=NSCocoaErrorDomain Code=3840 "No value."
Can someone please help me with this?
What am I missing?
Thank you all very much in advance!
[Edited after switching from NSURL Connection to NSURLSession]
Here's an example on how to use NSURLSession with a very convenient "completion handler".
This function contains the network call and has the "completion handler" (a callback for when the data will be available):
func getDataFrom(urlString: String, completion: (data: NSData)->()) {
if let url = NSURL(string: urlString) {
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url) { (data, response, error) in
// print(response)
if let data = data {
completion(data: data)
} else {
print(error?.localizedDescription)
}
}
task.resume()
} else {
// URL is invalid
}
}
You can use it like this, inside a new function, with a "trailing closure":
func apiManager() {
getDataFrom("http://headers.jsontest.com") { (data) in
do {
let json = try NSJSONSerialization.JSONObjectWithData(data, options: [])
if let jsonDict = json as? NSDictionary {
print(jsonDict)
} else {
// JSON data wasn't a dictionary
}
}
catch let error as NSError {
print("API error: \(error.debugDescription)")
}
}
}

This application is modifying the autolayout engine from a background thread, which can lead to engine corruption

I am getting this error This application is modifying the autolayout engine from a background thread, which can lead to engine corruption and weird crashes.This will cause an exception in a future release. I don't know what is causing this error. Can anybody help me.
func getUserDataFromTwitterWithUser(user : PFUser)
{
//NRLoader.showLoader()
let strTwURL = "https://api.twitter.com/1.1/users/show.json? screen_name="+PFTwitterUtils.twitter()!.screenName! + "&access_token="+PFTwitterUtils.twitter()!.authToken!
let twURL = NSURL (string: strTwURL)
let request = NSMutableURLRequest(URL: twURL!, cachePolicy: NSURLRequestCachePolicy.UseProtocolCachePolicy, timeoutInterval: 2.0) as NSMutableURLRequest
PFTwitterUtils.twitter()?.signRequest(request)
let session = NSURLSession.sharedSession()
session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
if error == nil {
var jsonOptional = Dictionary<String, AnyObject>()
do {
jsonOptional = try NSJSONSerialization.JSONObjectWithData(data!, options:NSJSONReadingOptions.MutableContainers ) as! Dictionary<String, AnyObject>
// use jsonData
} catch {
// report error
}
var userName = ""
if let screenName = jsonOptional["screen_name"] as? String{
userName = screenName
}
else if let name = jsonOptional["name"] as? String{
userName = name
}
var profilePicUrl = ""
if let picUrl = jsonOptional["profile_image_url"] as? String{
profilePicUrl = picUrl
}
AppUser.currentUser()?.username = userName
AppUser.currentUser()?.profileAwsURL = profilePicUrl
//NRLoader.hideLoader()
//if ParseUtils.isLoggedInUserIsAnonymous() {
let signUpVC:SignMeUpViewController = self.storyboard!.instantiateViewControllerWithIdentifier("SignMeUpViewController") as! SignMeUpViewController
signUpVC.isFromLogin = true
self.navigationController!.pushViewController(signUpVC, animated: true)
//} else {
// self.pushToSubmitDreamViewController()
//}
}
else {
//NRLoader.hideLoader()
NRToast.showToastWithMessage(error!.description)
}
}).resume()
}
The dataTaskWithRequest call runs in the background and then calls your completion handler from the same thread. Anything that updates the UI should run on the main thread, so all of your current handler code should be within a dispatch_async back onto the main queue:
dispatch_async(dispatch_get_main_queue()) {
// Do stuff to UI
}
Swift 3:
DispatchQueue.main.async() {
// Do stuff to UI
}
Therefore, ideally all the code you currently have within if error == nil should be off in another function, say called handleRequest, so your current code becomes:
session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
if error == nil {
dispatch_async(dispatch_get_main_queue(), {
self.handleRequest(...)I
})
}
Swift 3
session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
if error == nil {
DispatchQueue.main.async {
self.handleRequest(...)I
}
}
Should try Symbolic Breakpoint to detect the issue:-
Then put your UI Update code in main thread
DispatchQueue.main.async {}
You'd better change UI only in the main thread
swift3,
let liveInfoUrl = URL(string: "http://192.168.1.66/api/cloud/app/liveInfo/7777")
let task = URLSession.shared.dataTask(with: liveInfoUrl! as URL) {data, response, error in
guard let data = data, error == nil else { return }
DispatchQueue.main.async {
print(String(data: data, encoding: String.Encoding(rawValue: String.Encoding.utf8.rawValue)) ?? "aaaa")
//do some ui work
}
}
if the above suggestions still give you no joy then the sure-est way is to redesign your functions so that getting what you need with
URLSession.shared.dataTask
then hands over so a variable declared outside that function, then a separate UIControl ( button, swipe etc ) displays it to a label or textview or whatever.
After all that is what the error message is telling you. they're separate concerns

Extra argument 'error' in call - swift 2 [duplicate]

I'm currently developing my first iOS app using Swift 2.0 and Xcode Beta 2. It reads an external JSON and generates a list in a table view with the data. However, I'm getting a strange little error that I can't seem to fix:
Extra argument 'error' in call
Here is a snippet of my code:
let task = session.dataTaskWithURL(url!, completionHandler: {data, response, error -> Void in
print("Task completed")
if(error != nil){
print(error!.localizedDescription)
}
var err: NSError?
if let jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as? NSDictionary{
if(err != nil){
print("JSON Error \(err!.localizedDescription)")
}
if let results: NSArray = jsonResult["results"] as? NSArray{
dispatch_async(dispatch_get_main_queue(), {
self.tableData = results
self.appsTableView!.reloadData()
})
}
}
})
The error is thrown at this line:
if let jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as? NSDictionary{
Can someone please tell me what I'm doing wrong here?
With Swift 2, the signature for NSJSONSerialization has changed, to conform to the new error handling system.
Here's an example of how to use it:
do {
if let jsonResult = try NSJSONSerialization.JSONObjectWithData(data, options: []) as? NSDictionary {
print(jsonResult)
}
} catch let error as NSError {
print(error.localizedDescription)
}
With Swift 3, the name of NSJSONSerialization and its methods have changed, according to the Swift API Design Guidelines.
Here's the same example:
do {
if let jsonResult = try JSONSerialization.jsonObject(with: data, options: []) as? [String:AnyObject] {
print(jsonResult)
}
} catch let error as NSError {
print(error.localizedDescription)
}
Things have changed in Swift 2, methods that accepted an error parameter were transformed into methods that throw that error instead of returning it via an inout parameter. By looking at the Apple documentation:
HANDLING ERRORS IN SWIFT:
In Swift, this method returns a nonoptional result and is marked with the throws keyword to indicate that it throws an error in cases of failure.
You call this method in a try expression and handle any errors in the catch clauses of a do statement, as described in Error Handling in The Swift Programming Language (Swift 2.1) and Error Handling in Using Swift with Cocoa and Objective-C (Swift 2.1).
The shortest solution would be to use try? which returns nil if an error occurs:
let message = try? NSJSONSerialization.JSONObjectWithData(receivedData, options:.AllowFragments)
if let dict = message as? NSDictionary {
// ... process the data
}
If you're also interested into the error, you can use a do/catch:
do {
let message = try NSJSONSerialization.JSONObjectWithData(receivedData, options:.AllowFragments)
if let dict = message as? NSDictionary {
// ... process the data
}
} catch let error as NSError {
print("An error occurred: \(error)")
}
This has been changed in Swift 3.0.
do{
if let responseObj = try JSONSerialization.jsonObject(with: results, options: .allowFragments) as? NSDictionary{
if JSONSerialization.isValidJSONObject(responseObj){
//Do your stuff here
}
else{
//Handle error
}
}
else{
//Do your stuff here
}
}
catch let error as NSError {
print("An error occurred: \(error)") }

XCode 6 UILabel not refreshing text when calling from complition handler

I'm calling to refresh label after refreshQuote() function finishes. When look at the log to see what happened with label.text I can see it has been replaced however the view still looks the same.
Im calling refreshQuote() from viewDidload.
When calling setQuoteLabel directly from viewDidLoad it all works fine
Please help, loosing hope now.
Thanks in advance
func refreshQuote()
{
var url : String = "https://api.parse.com/1/classes/Quotes"
var request : NSMutableURLRequest = NSMutableURLRequest()
request.addValue("------", forHTTPHeaderField: "X-Parse-Application-Id")
request.addValue("------strong text", forHTTPHeaderField: "X-Parse-REST-API-Key")
request.URL = NSURL(string: url)
request.HTTPMethod = "GET"
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue(), completionHandler:{ (response:NSURLResponse!, data: NSData!, error: NSError!) -> Void in
var error: AutoreleasingUnsafeMutablePointer<NSError?> = nil
NSLog(error.debugDescription);
let jsonResult: NSDictionary! = NSJSONSerialization.JSONObjectWithData(data, options:NSJSONReadingOptions.MutableContainers, error: error) as? NSDictionary
if (jsonResult != nil)
{
var allResults: NSArray = jsonResult["results"] as NSArray
var pickedResult: NSDictionary = allResults[0] as NSDictionary
let q:String = pickedResult["message"] as String!
self.setQuoteLabel(q);
} else
{
// couldn't load JSON, look at error
}
})
}
func setQuoteLabel (quote:String)
{
NSLog(quote)
quoteLabel.text = quote;
quoteLabel.setNeedsDisplay();
NSLog(quoteLabel.text!)
}
All UI components must be updated from the main thread, whereas in your case you are updating most likely from a different thread, because the code is in an asynchronous block.
To force a block of code to be executed in the main thread, you can use dispatch_async as follows:
dispatch_async (dispatch_get_main_queue ()) {
self.setQuoteLabel(q)
}

NSURLSession completion block not called

var session = NSURLSession.sharedSession()
session.dataTaskWithRequest(urlRequest,
completionHandler: {(data: NSData!,
response: NSURLResponse!,
error: NSError!) in
println(data)
println(response)
println(error)
})
So I am making this request, and the completion block is never called.
What's wrong?
Also I tried a synchronous and asynchronous form of the same request with NSURLConnection and it worked perfectly.
EDIT:
I tried assigning a dataTask variable to the session.dataTaskWithRequest and displayed it right after. It says this <__NSCFLocalDataTask: 0xb41bda0> { suspended } Suspended? Why?
So I tried calling it like this
session.dataTaskWithRequest(urlRequest,
completionHandler: {(data: NSData!,
response: NSURLResponse!,
error: NSError!) in
print(data)
print(response)
print(error)
}).resume()
And it worked.
Seems like I have to call resume() on a default suspended session task.
Are you using playgrounds??
If you are, you should be careful to include:
XCPSetExecutionShouldContinueIndefinitely(continueIndefinitely: true)
In order to make the playground wait for the callback
I face the same problem and I solved it by
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * data, NSURLResponse * response, NSError * error) {
if (!error)
{
NSLog(#"Data is %#",data);
NSLog(#"Response is %#",response);
NSLog(#"Error is %#",error);
}
}];
[dataTask resume];
And check that you are added the App Transport Security Settings in your info.plist.
You can also use it simply by :-
let url = "api url"
let nsURL = NSURL
let task = NSURLSession.sharedSession().dataTaskWithURL(nsURL) {
(data, response, error) in
// your condition on success and failure
}
task.resume()
This is a fairly unique case, but if you're using a URLSession inside a unit test, you'll need to setup the expectations. Otherwise, your test case will end and it will appear that your request is never returning. Swift 3.0.1.
let expect = expectation(description: "dataTaskWithRequest - completes")
if let url = URL(string: "https://www.google.com/") {
let request = URLRequest(url: url)
URLSession.shared.dataTask(with: request) { ( data, response, error) in
print(data.debugDescription)
print(response.debugDescription)
print(error.debugDescription)
expect.fulfill()
}.resume()
waitForExpectations(timeout: 10, handler: nil)
}
It'll be something like this in Swift 2.x
NSURLSession.sharedSession().dataTaskWithRequest(theRequest) { (data, response , error) in
print(response)
}.resume()

Resources