【问题标题】:Access Twitter using Swift使用 Swift 访问 Twitter
【发布时间】:2015-04-28 08:54:26
【问题描述】:

我正在使用 Swifter 库在我的 Swift iOS 8 应用程序中访问 Twitter:https://github.com/mattdonnelly/Swifter。问题是我从 Twitter 收到 401 Not Authorized 错误。我仔细检查了任何可能的原因:

  1. 用户密钥/密码错误
  2. 确保不要使用 API v1(使用 1.1)

解决了这两个问题(根据 Twitter 文档),我仍然面临这个问题。我认为这与我的身份验证方式有关。我正在尝试在不使用设备上的 ACAccount 的情况下访问公共提要。

这是我的代码:

// MARK: Twitter
    var swifter: Swifter

    required init(coder aDecoder: NSCoder) {
        self.swifter = Swifter(consumerKey: "KEY", consumerSecret: "SECRET")
        super.init(coder: aDecoder)
    }

    func getTwitterTimeline() {
        let failureHandler: ((NSError) -> Void) = {
            error in
            self.alertWithTitle("Error", message: error.localizedDescription)
        }

        self.swifter.getStatusesUserTimelineWithUserID("erhsannounce", count: 20, sinceID: nil, maxID: nil, trimUser: true, contributorDetails: false, includeEntities: true, success: {
            (statuses: [JSONValue]?) in

            if statuses != nil {
                self.tweets = statuses!
            }

        }, failure: failureHandler)
    }

    func alertWithTitle(title: String, message: String) {
        var alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.Alert)
        alert.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
        self.presentViewController(alert, animated: true, completion: nil)
    }

更新:我一直在开发应用程序,试图实现仅使用应用程序(不是基于用户)身份验证和访问令牌来读取公共时间线的功能。

我更新了代码以使用访问令牌和仅应用程序身份验证。不过还是不行。

required init(coder aDecoder: NSCoder) {
        let accessToken = SwifterCredential.OAuthAccessToken(key: "KEY", secret: "SECRET")
        let credential = SwifterCredential(accessToken: accessToken)

        self.swifter = Swifter(consumerKey: "cKEY", consumerSecret: "cSECRET", appOnly: true)
        swifter.client.credential = credential
        super.init(coder: aDecoder)
    }

【问题讨论】:

    标签: swift twitter oauth


    【解决方案1】:

    2015 年 2 月 3 日更新

    您需要使用 App Only Authentication 向服务器进行身份验证,而不是传入 OAuth 令牌。

    除此之外,当您传入用户的屏幕名称时,您也没有正确使用 userId 请求状态。您需要获取用户名和用户名,然后请求状态'。

    完整的工作代码如下:

    required init(coder aDecoder: NSCoder) {
        self.swifter = Swifter(consumerKey: "cKEY", consumerSecret: "cSECRET", appOnly: true)
        super.init(coder: aDecoder)
    
        self.swifter.authorizeAppOnlyWithSuccess({ (accessToken, response) -> Void in
            self.twitterIsAuthenticated = true
        }, failure: { (error) -> Void in
            println("Error Authenticating: \(error.localizedDescription)")
        })
    }
    
    @IBAction func getUserButtonPressed(sender: UIButton?) {
        if (self.twitterIsAuthenticated) {
            self.getTwitterUserWithName("erhsannounce")
        } else {
            // Authenticate twitter again.
        }
    }
    
    func getTwitterUserWithName(userName: String) {
        self.swifter.getUsersShowWithScreenName(userName, includeEntities: true, success: { (user) -> Void in
            if let userDict = user {
                if let userId = userDict["id_str"] {
                    self.getTwitterStatusWithUserId(userId.string!)
                }
            }
            }, failure: failureHandler)
    }
    
    func getTwitterStatusWithUserId(idString: String) {
        let failureHandler: ((error: NSError) -> Void) = {
            error in
            println("Error: \(error.localizedDescription)")
        }
    
        self.swifter.getStatusesUserTimelineWithUserID(idString, count: 20, sinceID: nil, maxID: nil, trimUser: true, contributorDetails: false, includeEntities: true, success: {
            (statuses: [JSONValue]?) in
    
            if statuses != nil {
                self.tweets = statuses
            }
    
            }, failure: failureHandler)
    }
    

    您似乎没有通过服务器进行身份验证。

    从您的代码中,我可以看到您正在使用 OAuth 身份验证初始化,但未能调用身份验证函数。

    swifter.authorizeWithCallbackURL(callbackURL, success: {
        (accessToken: SwifterCredential.OAuthAccessToken?, response: NSURLResponse) in
    
        // Handle success
    
        },
        failure: {
            (error: NSError) in
    
            // Handle Failure
    
        })
    

    添加它,然后调用您的 getTwitterTimeline()。

    希望对你有帮助

    【讨论】:

    • 这非常适合让 Swifter 访问 Twitter,但我对它的访问方式有疑问。我正在尝试使用 Twitter 阅读公共时间线,因此我不希望最终用户需要进行身份验证。此方法需要用户登录。有什么想法吗?
    • @ShaanSingh 你能告诉我你在失败处理程序中遇到的错误吗?
    • 当然可以。这是错误 HTTP 状态 401:未经授权,响应:无法验证 oauth 签名和令牌。 (顺便感谢您的帮助!)
    • 你有什么想法吗?
    【解决方案2】:

    我将展示如何(在 2021 年)不需要每次都登录。请按照以下步骤操作(将 YOURAPPNAME 替换为您的应用名称):

    1. 将 YOURAPPNAME:// 添加为 twitter 开发者门户的回调 URL,在身份验证设置下。为此,您需要启用 3-legged OAuth,并将其添加到回调 URLS 中。您还需要输入一个网站 URL,但它可以是任何东西(我有 https://www.google.com)。还要确保(如果您想发推文)您在设置中更改应用程序的读写权限

    2. 在您的 podfile 中,确保您有以下行:

    pod 'Swifter' , :git => 'https://github.com/mattdonnelly/Swifter.git'
    

    不要只使用 pod 'Swifter',因为有另一个名为 Swifter 的项目不是由 mattdonnelly 开发的,因此无法运行。

    1. 在项目浏览器中单击您的项目,选择信息选项卡。在底部,您将看到 URL 类型。展开它并单击加号。在 URL Schemes 中输入 YOURAPPNAME(如果您的应用名称是“demoApp”,请输入 demoApp 而不是 demoApp://
    2. 如果您的应用程序代理尚未在您的应用程序代理中使用开放 url 功能(标准是没有,但我的是因为我有 google 登录,在我的情况下我不需要做任何事情)在您的应用程序代理中 import Swifter 并添加此功能:
    func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
            
        Swifter.handleOpenURL(url, callbackURL: URL(string: "YOURAPPNAME://")!)
            
        return true
    }
    
    1. 在您的视图控制器中,您需要首先授权 twitter,然后您可以执行任何操作(推文、查找提要等)。您可以使用 swifter.authorize 来执行此操作,它会打开一个浏览器。对于那些希望在第一次之后不再需要它的人,这就是 swifter.verifyAccountCredentials 的用武之地。要找到 CONSUMER_KEY 和 CONSUMER_SECRET,请转到 twitter 开发者门户的密钥和令牌区域。
    import Swifter
    import AuthenticationServices
    
    class ViewController: UIViewController, ASWebAuthenticationPresentationContextProviding {
        func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
            return self.view.window!
        }
        
        var swifter: Swifter!
        
        override func viewDidLoad() {
            super.viewDidLoad()
            if UserDefaults.standard.string(forKey: "twitterOAuthToken") == nil {
                swifter = Swifter(consumerKey: CONSUMER_KEY, consumerSecret: CONSUMER_SECRET)
                if let url = URL(string: "YOURAPPNAME://") {
                    swifter.authorize(withProvider: self, callbackURL: url) { (token, response) in
                        UserDefaults.standard.set(token?.key, forKey: "twitterOAuthToken")
                        UserDefaults.standard.set(token?.secret, forKey: "twitterOAuthSecret")
                        print("signed in!!")
                    }
                }
                
            } else {
                swifter = Swifter(consumerKey: CONSUMER_KEY, consumerSecret: CONSUMER_SECRET, oauthToken: UserDefaults.standard.string(forKey: "twitterOAuthToken") ?? "", oauthTokenSecret: UserDefaults.standard.string(forKey: "twitterOAuthSecret") ?? "")
                swifter.verifyAccountCredentials(includeEntities: nil, skipStatus: nil, includeEmail: nil) { (json) in
                    print("signed in!")
                } failure: { (error) in
                    self.swifter = Swifter(consumerKey: CONSUMER_KEY, consumerSecret: CONSUMER_SECRET)
                    if let url = URL(string: "YOURAPPNAME://") {
                        self.swifter.authorize(withProvider: self, callbackURL: url) { (token, response) in
                            UserDefaults.standard.set(token?.key, forKey: "twitterOAuthToken")
                            UserDefaults.standard.set(token?.secret, forKey: "twitterOAuthSecret")
                            print("signed in!!")
                        }
                    }
                }
            }
            
            
            
           let button = UIButton()
            button.layer.backgroundColor = #colorLiteral(red: 0.8078431487, green: 0.02745098062, blue: 0.3333333433, alpha: 1)
            button.frame = CGRect(x: 200, y:0, width: 200, height: 200)
            button.center = view.center
            button.addTarget(self, action: #selector(tweet), for: .touchUpInside)
            view.addSubview(button)
    
        }
        
        @objc func tweet() {
            swifter.postTweet(status: "wild") { (json) in
                print("tweeted!")
            } failure: { (error) in
                print("tweet failed")
            }
        }
    }
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-04-18
      • 2011-06-11
      • 2013-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-22
      • 2012-06-13
      相关资源
      最近更新 更多