Status update call gives 401 even after login is called (iOS)


#1

I’m using fabric to post a tweet with a photo
At the start up of my application I call Twitter.sharedInstance().logInWithCompletion, and this call succeeds.
Then I want to post a tweet with a photo, the photo upload goes well, and I receive the media_id_string.
I use the response of this call to construct the parameters of the status update call.

But this call always fails with :
Error Domain=TWTRNetworkingErrorDomain Code=-1011 “Request failed: unauthorized (401)” UserInfo=0x174263440 {NSErrorFailingURLKey=https://api.twitter.com/1.1/statuses/update.json, NSLocalizedDescription=Request failed: unauthorized (401), NSLocalizedFailureReason=Twitter API error : (code (null))}

Can someone please point out to me why I am getting this 401, while I am clearly signed in (otherwise the upload call would fail too right?)

My code:

class func postToFabricTwitter(krumb:Krumb, imageUrl:NSURL, handler:(success:Bool, error:NSError?) -> ()) {

    let strUploadUrl = "https://upload.twitter.com/1.1/media/upload.json"
    let strStatusUrl = "https://api.twitter.com/1.1/statuses/update.json"
    
    var parameters:[String:String] = [:]
    let imageData = NSData(contentsOfURL: imageUrl)!
    parameters["media"] = imageData.base64EncodedStringWithOptions(nil)
    
    var uploadRequestError: NSError?
    
    var twUploadRequest = Twitter.sharedInstance().APIClient.URLRequestWithMethod("POST", URL: strUploadUrl, parameters: parameters, error: &uploadRequestError)
    
    if twUploadRequest != nil {
        Twitter.sharedInstance().APIClient.sendTwitterRequest(twUploadRequest) {
            (uploadResponse, uploadResultData, uploadConnectionError) -> Void in
            if (uploadConnectionError == nil) {
                
                if let parameters = self.getParametersForStatusUpdateFromResponse(uploadResultData) {
                    println("result = \(parameters)")
                    
                    var statusRequestError:NSError?
                    var twStatusRequest = Twitter.sharedInstance().APIClient.URLRequestWithMethod("POST", URL: strStatusUrl, parameters: parameters, error: &statusRequestError)
                    if (twStatusRequest != nil)
                    {
                        Twitter.sharedInstance().APIClient.sendTwitterRequest(twStatusRequest) { (statusResponse, statusData, statusConnectionError) -> Void in
                            if (statusConnectionError != nil) {
                                println("Error posting status \(statusConnectionError)")
                            }
                            else {
                                var jsonError : NSError?
                                let json : AnyObject? =
                                NSJSONSerialization.JSONObjectWithData(statusData,
                                    options: nil,
                                    error: &jsonError)
                                
                                println("\(json)")
                            }
                        }
                    } else {
                        println("Error creating status request \(statusRequestError)")
                    }
                    
                } else {
                    println("parameters where nil")
                }
            } else {
                println("Error uploading image \(uploadConnectionError)")
            }
        }
    } else {
        println("Error creating upload request \(uploadRequestError)")
    }
}

class func getParametersForStatusUpdateFromResponse(uploadResponse:NSData) -> [String:String]?{
    var parameters:[String:String] = [:]
    var parsingError: NSError?
    let json: [String:AnyObject] = NSJSONSerialization.JSONObjectWithData(uploadResponse, options: NSJSONReadingOptions.MutableContainers, error: &parsingError) as [String:AnyObject]
    
    // check for media id in result
    if (json["media_id_string"] != nil) {
        println("result = \(json)")
        
        // post a status with link to media
        parameters["status"] = "Hey look at this"
        parameters["media_ids"] = json["media_id_string"] as? String
        return parameters
    }
    else {
        println("Media_id not found in result = \(json)")
        return nil
    }
}

#2

When you log in, are you using a System iOS Account (set up in Preferences) or logging in through the webview that is presented?


#3

I’m logging in via this method:
Twitter.sharedInstance().logInWithCompletion


#4

I even get this error when trying to post a tweet without the media:

  let parameters = ["status" : "check this out"]
  Twitter.sharedInstance().logInWithCompletion({ (session:TWTRSession!, error:NSError!) -> Void in
     if error == nil {
             self.updateTwitterStatus(parameters, handler: { (success, error) -> () in
             handler(success: success, error: error)
             })
     } else {
             handler(success: false, error: error)
     }
 })

_

class func updateTwitterStatus(parameters:[String:String], handler:(success:Bool, error:NSError?) -> ()) {
    let strStatusUrl = "https://api.twitter.com/1.1/statuses/update.json"
    
    var statusRequestError:NSError?
    var twStatusRequest = Twitter.sharedInstance().APIClient.URLRequestWithMethod("POST", URL: strStatusUrl, parameters: parameters, error: &statusRequestError)
    
    if (twStatusRequest != nil)
    {
        Twitter.sharedInstance().APIClient.sendTwitterRequest(twStatusRequest) { (statusResponse, statusData, statusConnectionError) -> Void in
            if (statusConnectionError != nil) {
                println("Error posting status \(statusConnectionError)")
                handler(success: false, error: statusConnectionError)
            }
            else {
                var jsonError : NSError?
                let json : AnyObject? =  NSJSONSerialization.JSONObjectWithData(statusData, options: nil, error: &jsonError)
                println("\(json)")
                handler(success: true, error: nil)
            }
        }
    } else {
        handler(success: false, error: statusRequestError)
        println("Error creating status request \(statusRequestError)")
    }
}

Result: Error posting status: Error Domain=TWTRNetworkingErrorDomain Code=-1011 “Request failed: unauthorized (401)” UserInfo=0x1746725c0 {NSErrorFailingURLKey=https://api.twitter.com/1.1/statuses/update.json, NSLocalizedDescription=Request failed: unauthorized (401), NSLocalizedFailureReason=Twitter API error : (code (null))}


#5

I am experiencing this issue.

I am using “System iOS Account (set up in Preferences)” to login.


#6

What is the content of your Tweet? Are you using any special characters? There are several older versions of Twitter Kit that would fail to send a Tweet which contained square brackets [ ] or curly brackets { }.

These issues are both fixed in the upcoming Twitter Kit 2.0 release.


#7

im having this issue now, whats the solution for this?


#8

I’m having this issue too. It’s weird, I had it all working with my iOS app and a Twitter app (at apps.twitter.com) created under my personal account - I needed to have the app under my company’s account (there was no way of moving an app between accounts) so I created a new one under the company’s account. I changed the url scheme and the key/secret in the info.plist. I’m not sure what else I obviously forgot to do.


#9

Would you know what I might have forgotten, changing Twitter apps in my app?


#10

I got it to work. Not sure what I did or did not do, but all I think I did was just make sure the key+secret from the app’s settings page was correct in Info.plist - I changed it back to the old keys, made sure tweets worked (they did), then changed to the new key+secret again… and suddenly it just works.

So, tweets now work again using the new app at apps.twitter.com. Sorry for bumping! :grin: