質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Xcode 7

Xcode 7は、ソフトウェア開発のためのアップルの統合開発環境であるXcodeのバージョン。UIを作成するために用いるグラフィカルツールです。iOS9/OS X El Capitan/watchOS2に対応。Swift 2コンパイラーが搭載されています。

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Swift 2

Swift 2は、Apple社が独自に開発を行っている言語「Swift」のアップグレード版です。iOSやOS X、さらにLinuxにも対応可能です。また、throws-catchベースのエラーハンドリングが追加されています。

Q&A

解決済

1回答

1521閲覧

if !obj!.isKindOfClass(NSArray)とは

in221

総合スコア11

Xcode 7

Xcode 7は、ソフトウェア開発のためのアップルの統合開発環境であるXcodeのバージョン。UIを作成するために用いるグラフィカルツールです。iOS9/OS X El Capitan/watchOS2に対応。Swift 2コンパイラーが搭載されています。

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Swift 2

Swift 2は、Apple社が独自に開発を行っている言語「Swift」のアップグレード版です。iOSやOS X、さらにLinuxにも対応可能です。また、throws-catchベースのエラーハンドリングが追加されています。

0グッド

0クリップ

投稿2015/11/05 15:25

編集2015/11/05 15:29

###前提・実現したいこと
最近プログラミングを始め、「iPhone/iPadプログラミングバイブル」という本を参考に勉強しています。この本に掲載されているツイッタークライアントを作成していてわからないところがあるので教えて下さい。

サンプルコードを実機(iPad mini2)で使用してみたんですが、更新ボタンを数回連続して押すとエラーの「パースに失敗しました2」と表示されます。

エラー表示のif文2つ目に引っかかっているようなんですがこれがどういったものかわかりません。if !obj!.isKindOfClass(NSArray)とはどういったものなのか教えて下さい。

また、そのエラーが出た場合、アプリやipadを再起動してもエラーのままでした。
合わせてこの場合の解決策もあればお願いします。

###発生している問題・エラーメッセージ
「パースに失敗しました2」というアラート

###ソースコード
import UIKit
import Social
import Accounts

//Twitterクライアント
class ViewController: UIViewController,
UITableViewDelegate, UITableViewDataSource {
//画面サイズ定数
let SCREEN = UIScreen.mainScreen().bounds.size //画面サイズ

//変数 @IBOutlet var _tableView: UITableView! //テーブルビュー var _accountStore: ACAccountStore! //アカウントストア var _account: ACAccount! //アカウント var _items = [Status]() //要素群

//====================
//UI
//====================
//ロード完了時に呼ばれる
override func viewDidLoad() {
super.viewDidLoad()

//UI self.title = "Twitterクライアント" //Twitterアカウントの取得(1) initTwitterAccount() } //ツールバーボタンクリック時に呼ばれる @IBAction func onClick(sender: UIBarButtonItem) { if _account == nil { initTwitterAccount() return } if sender.tag == 0 { timeline() } else if sender.tag == 1 { twit() } } //ラベルの生成 func makeLabel(frame: CGRect, text: String, font: UIFont) -> UILabel { let label = UILabel() label.frame = frame label.text = text label.font = font label.textColor = UIColor.blackColor() label.backgroundColor = UIColor.clearColor() label.textAlignment = NSTextAlignment.Left label.lineBreakMode = NSLineBreakMode.ByWordWrapping label.numberOfLines = 0 return label } //イメージビューの生成 func makeImageView(frame: CGRect, image: UIImage?) -> UIImageView { let imageView = UIImageView() imageView.frame = frame imageView.image = image return imageView } //アラートの表示 func showAlert(title: String?, text: String?) { let alert = UIAlertController(title: title, message: text, //(5) preferredStyle: UIAlertControllerStyle.Alert) alert.addAction(UIAlertAction(title: "OK", //(6) style: UIAlertActionStyle.Default, handler: nil)) self.presentViewController(alert, animated: true, completion: nil)//(7) } //インジケーターの指定 func setIndicator(indicator: Bool) { UIApplication.sharedApplication( ).networkActivityIndicatorVisible = indicator }

//====================
//UITableViewDelegate
//====================
//セルの高さの取得
func tableView(tableView: UITableView,
heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
let status = _items[indexPath.row]
let label = makeLabel(CGRectMake(60, 30, SCREEN.width-70, 1024),
text: status.text, font: UIFont.systemFontOfSize(14))
label.sizeToFit()
let height = 30+label.frame.size.height+10
return height < 60 ? 60 : height
}
//====================
//UITableViewDataSource
//====================
//セルの数取得時に呼ばれる
func tableView(tableView: UITableView,
numberOfRowsInSection section: Int) -> Int {
return _items.count
}
//セルの取得時に呼ばれる(7)
func tableView(tableView: UITableView,
cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//テーブルのセルの生成
let c = tableView.dequeueReusableCellWithIdentifier("table_cell")
let cell = (c != nil) ? c! :
UITableViewCell(style: UITableViewCellStyle.Default,
reuseIdentifier: "table_cell")
if c == nil {
//アイコンの追加
let imgIcon = makeImageView(CGRectMake(10, 10, 40, 40), image: nil)
imgIcon.tag = 1
cell.contentView.addSubview(imgIcon)
//名前の追加
let lblName = makeLabel(CGRectMake(60, 10, 250, 16), text: "",
font: UIFont.boldSystemFontOfSize(16))
lblName.tag = 2
cell.contentView.addSubview(lblName)
//テキストの追加
let lblText = makeLabel(CGRectMake(60, 30, 320, 1024),
text: "", font: UIFont.systemFontOfSize(14))
lblText.tag = 3
cell.contentView.addSubview(lblText)
}
if _items.count <= indexPath.row {return cell}
//ステータスの取得
let status = _items[indexPath.row]
//アイコンの指定
let imgIcon = cell.contentView.viewWithTag(1) as! UIImageView
imgIcon.image = status.icon
//名前の指定
let lblName = cell.contentView.viewWithTag(2) as! UILabel
lblName.text = status.name
//テキストの追加
let lblText = cell.contentView.viewWithTag(3) as! UILabel
lblText.text = status.text
lblText.frame = CGRectMake(60, 30, SCREEN.width-70, 1024)
lblText.sizeToFit()
return cell
}
//====================
//Twitter
//====================
//Twitterのアカウント情報の取得(1)
func initTwitterAccount() {
_account = nil
_accountStore = ACAccountStore()
let twitterType = _accountStore
.accountTypeWithAccountTypeIdentifier(ACAccountTypeIdentifierTwitter)
_accountStore.requestAccessToAccountsWithType(
twitterType, options:nil) {(granted, error) in
if granted {
let accounts = self._accountStore
.accountsWithAccountType(twitterType)
if accounts!.count > 0 {
self._account = accounts![0] as? ACAccount
self.timeline()
return
}
}
dispatch_async(dispatch_get_main_queue(), {
self.showAlert(nil, text: "Twitterアカウントが登録されていません")
})
}
}
//アイコンの読み込み
func loadIcon(status: Status) {
//通信によるアイコン読み込み
let request = NSURLRequest(URL: NSURL(string: status.iconURL)!,
cachePolicy: NSURLRequestCachePolicy.UseProtocolCachePolicy,
timeoutInterval: 30.0)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request, completionHandler: {
(data, response, error) in
if data != nil && error == nil {
dispatch_async(dispatch_get_main_queue()) {
status.icon = UIImage(data: data!)
self._tableView.reloadData()
}
}
})
task.resume()
}
//タイムラインの取得
func timeline() {
//インジケータ表示
self.setIndicator(true)
//タイムラインの読み込み(2)
let url = NSURL(string:
"https://api.twitter.com/1.1/statuses/home_timeline.json")!
let params: [String: String] = ["count": "20"]
let timeline = SLRequest(forServiceType: SLServiceTypeTwitter,
requestMethod: SLRequestMethod.GET, URL: url, parameters: params)
timeline.account = self._account
timeline.performRequestWithHandler(){(responseData: NSData!,
urlResponse: NSHTTPURLResponse!, error: NSError!) in
//JSONのパース(3)
var obj : AnyObject? = nil
do {
if responseData != nil {
obj = try NSJSONSerialization.JSONObjectWithData(
responseData, options: [])
}
} catch _ {
obj = nil
}
//エラー表示
if error != nil {
self.showAlert(nil, text: "通信失敗しました")
} else if obj == nil {
self.showAlert(nil, text: "パースに失敗しました")
} else if !obj!.isKindOfClass(NSArray) {
self.showAlert(nil, text: "パースに失敗しました2")
} else {
//JSONをパースしたデータをStatusクラスの配列に変換(4)
self._items.removeAll()
let statuses = obj as! NSArray
for var i = 0; i < statuses.count; i++ {
let item = Status()
let status = statuses[i] as! NSDictionary
let user = status["user"] as! NSDictionary
item.text = status["text"] as! String
item.name = user["screen_name"] as! String
item.iconURL = user["profile_image_url"] as! String
self.loadIcon(item)
self._items.append(item)
}
}
//テーブル更新
dispatch_async(dispatch_get_main_queue(), {
self._tableView.reloadData()
})
//インジケータ非表示
self.setIndicator(false)
}
}
//つぶやきの送信(5)
func twit() {
let twitterCtl = SLComposeViewController(
forServiceType: SLServiceTypeTwitter)
self.presentViewController(twitterCtl, animated: true, completion: nil)
}
//====================
//ユーティリティ
//====================
//バイト配列を文字列に変換
func data2str(data: NSData) -> NSString {
return NSString(data: data, encoding: NSUTF8StringEncoding)!
}
}

###補足情報(言語/FW/ツール等のバージョンなど)
Swift2 Xcode7

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

下記のようにobjの内容をprintしてみると

Swift

1 } else if !obj!.isKindOfClass(NSArray) { 2 print("\(obj)") 3 self.showAlert(nil, text: "パースに失敗しました2") 4 } else {

手元では下記のような内容が出ました。

Swift

1Optional({ 2 errors = ( 3 { 4 code = 88; 5 message = "Rate limit exceeded"; 6 } 7 ); 8})

これはTwitterAPIはリクエストの回数に制限があるのでその制限を超えてしまったということのようです。
なのでしばらく待てばまた成功するようになると思います。

なお、制限の詳細は15分ごとに何回までのように決まっているようです。
https://dev.twitter.com/rest/public/rate-limits

投稿2015/11/06 07:01

jollyjoester

総合スコア1585

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

in221

2015/11/08 06:28

ありがとうございます。 ツイッターにそのようなリクエストの回数制限があったんですね。 勉強になりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問