本記事は、
【Swift】UITableViewでTwitterのタイムラインを実装してみた(その2)
の続きになります。
その2の記事をご覧になっていない方は是非そちらもご覧ください!
GitHubリポジトリはコチラになります。
では前回の続きになります。
前回はある程度の機能を実装しましたが幾つか課題があったと思います。
今回はその実装をしていきます。
課題としては下記があげられました。
・投稿時間の部分が適切な記載になっていない。
-> 本来はhh : mm : ss YYYY / MM / ddの表記
-> 全てのツイートが同じ時刻になっている
・いいね、リツイートなどの値も全て同じ
・リプライがない場合は下の部分をグレー表示にする
・右上のオプションボタン(・・・)がない。
-> 押すとブロックや非表示だできるやつ
・リプライの内容を実装していない
では、一つずつ実装していきます。
まずは各ツイートに時間やいいね、リツイートの情報を持たせます。
今回はTweetの内容が格納されている型を作成してその型を配列にしようと思います。
TweetModel型を定義します。
ツイートの内容やいいね、リツイートの数を保持するためのプロパティと、
ツイート時の時間をHH:mm:ss yyyy/MM/dd
の
形式で表示するためのメソッドを定義しました。
import Foundation
struct TweetModel {
var name: String
var content: String
var time: TimeInterval
var good: Double
var retweet: Double
var quoteRetweet: Double
func chengeDateFormatter(time: TimeInterval) -> String {
let date = Date(timeIntervalSince1970: time)
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "HH:mm:ss yyyy/MM/dd"
let dateString = dateFormatter.string(from: date)
return dateString
}
}
配列itemに修正を加え、TweetModel型を格納した配列に変更します。
var tweetArray = [
TweetModel(name: "山田一郎", content: "今日はいい天気です。午前中に洗濯を干したいと思います。", time: Date().timeIntervalSince1970 - 12345678, good: 10, retweet: 2, quoteRetweet: 1),
TweetModel(name: "山田二郎", content: "おはようございます。", time: Date().timeIntervalSince1970 - 1234567, good: 1000, retweet: 10, quoteRetweet: 7),
TweetModel(name: "山田三郎", content: "朝ごはんは目玉焼きとパンです。", time: Date().timeIntervalSince1970 - 123456, good: 20392, retweet: 1232, quoteRetweet: 1221),
TweetModel(name: "佐藤健", content: "映画「るろうに剣心」よろしくお願いします。", time: Date().timeIntervalSince1970 - 12345, good: 100022, retweet: 12911, quoteRetweet: 1292),
TweetModel(name: "新垣結衣", content: "逃げるは恥だが役にたつ", time: Date().timeIntervalSince1970 - 1234, good: 1212121, retweet: 21321, quoteRetweet: 12131),
TweetModel(name: "夏目漱石", content: "吾輩は猫である", time: Date().timeIntervalSince1970 - 123, good: 1200, retweet: 12, quoteRetweet: 12),
TweetModel(name: "李朴", content: "なるべくしてなっている", time: Date().timeIntervalSince1970 - 12, good: 2112, retweet: 2112, quoteRetweet: 2112),
TweetModel(name: "呉鳳明", content: "すりつぶせ", time: Date().timeIntervalSince1970 - 1, good: 1000000, retweet: 100000, quoteRetweet: 100000)
]
他にはcellForRowAt
やdidSelectRowAt
内に記述されている配列の参照の処理を、
itemからtweetArrayを参照するように変更しました。
これで各ツイートにそれぞれの情報を持たせることができました。
次に実装する機能は「リプライがない場合は下の部分をグレー表示にする」です。
表示のないセルをグレー表示にするのは実は簡単で、
TableViewのstyleを変更することで実装できます。
.plain
だったのを.grouped
に変更しました。
let tableView = UITableView(frame: self.view.bounds, style: .grouped)
ぱっと見は大丈夫そうですが一つ問題点がございます。
ツイートの上にグレーの隙間が存在してしまっています。
上にグレーの隙間があることは望まない結果なのでこちらの対処を行います。
遭遇したことのない事象でしたのでいろいろ調べてみました。
どうやら下記の二つが必要ですので追加してみてください!
どちらか一つでは変化がありませんでした。
sectionHeaderHeight
はTableViewのヘッダーの高さを変更します。
0を指定すると他のオブジェクトの影響を受けてしまうため0.1にしました。
viewForHeaderInSection
は、UIViewを返しそれをヘッダーに表示するのですが、
何も指定せずにUIView()を返すことでヘッダーをなくしています。
override func viewDidLoad() {
super.viewDidLoad()
tableView.sectionHeaderHeight = 0.1
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
return UIView()
}
次に実装する機能は「右上のオプションボタン(・・・)がない」です。
カスタムセルの右上に新しくボタンを追加しました。
このボタンが押された時の処理をカスタムセルの方のファイルに書いていきます。
今回はprint()
でログに出力するだけにしておこうと思います。
次に実装する機能は「リプライの内容を実装していない」に対しての実装です。
TweetModel型
の内容を少し変更します。
var reply: [TweetModel]
を追加しました。
リプライがある場合はこの配列replyの中にTweetModel型の要素を格納していきます。
var name: String
var content: String
var time: TimeInterval
var good: Double
var retweet: Double
var quoteRetweet: Double
var reply: [TweetModel]
型にプロパティを追加したのでtweetArrayの内容も変わります。
最後にreply: []
が追加されています。
リプライがある場合はここに値が入っていきます。
var tweetArray = [
TweetModel(name: "山田一郎",
content: "今日はいい天気です。午前中に洗濯を干したいと思います。",
time: Date().timeIntervalSince1970 - 12345678,
good: 10,
retweet: 2,
quoteRetweet: 1,
reply: [])
]
今回はviewDidLoad内で追加していきます。
override func viewDidLoad() {
super.viewDidLoad()
let reply1 = TweetModel(name: "山田二郎", content: "本当ですよね。", time: Date().timeIntervalSince1970 - 1234567, good: 11, retweet: 1, quoteRetweet: 2, reply: [])
let reply2 = TweetModel(name: "山田三郎", content: "こっちは雨です。", time: Date().timeIntervalSince1970 - 12345634, good: 12, retweet: 4, quoteRetweet: 2, reply: [])
let reply3 = TweetModel(name: "麃公", content: "バハァ!!!", time: Date().timeIntervalSince1970 - 5, good: 120031020, retweet: 1032000, quoteRetweet: 1122, reply: [])
let reply4 = TweetModel(name: "王騎", content: "天下の大将軍ですよぉ", time: Date().timeIntervalSince1970 - 1, good: 1223456543, retweet: 123123, quoteRetweet: 123123, reply: [])
tweetArray[0].reply.append(reply1)
tweetArray[0].reply.append(reply2)
tweetArray[7].reply.append(reply3)
tweetArray[7].reply[0].reply.append(reply4)
}
今までのdidSelectRowAt
では
DetailViewController.swiftのreplyプロパティに値を渡していないので、
配列内のreplyの値をDetailVCのreplyに渡す処理を追記します。
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let detailVC = storyboard?.instantiateViewController(identifier: "detailView") as! DetailViewController
detailVC.reply = tweetArray[indexPath.row].reply
navigationController?.pushViewController(detailVC, animated: true)
}
DetailViewController.swiftで下記の宣言があります。
var reply: [TweetModel] = []
このreplyプロパティにタップしたセルに対してのリプライが格納されています。
セルをタップ後の画面でもTableViewを構成するわけですが、
最初のセルから4番目のセルまではタップしたツイートの詳細が表示され、
5番目以降がリプライ情報になります。
リプライはデフォルトケースで実装されるのでデフォルトケース内を修正します。
let past = reply[count - 4].time
で
リプライの時間をTimeinterval型で取得しています。
let now = Date().timeIntervalSince1970
で現在の時刻を取得し、
cell.time.text = reply[count - 4].timeCheck(now: now, past: past)
で
現在の時刻と投稿時の時刻の差分をチェックしています。
reply[count - 4]
は、
リプライを読み込む際のcountの値が最低でも4なのでそこから4を引くことで
配列0番目から読み込むことが可能になっています。
default:
tableView.register(UINib(nibName: "CustomTableViewCell", bundle: nil), forCellReuseIdentifier: "customCell")
let cell = tableView.dequeueReusableCell(withIdentifier: "customCell", for: indexPath) as! CustomTableViewCell
let past = reply[count - 4].time
let now = Date().timeIntervalSince1970
cell.name.text = reply[count - 4].name
cell.time.text = reply[count - 4].timeCheck(now: now, past: past)
cell.content.text = reply[count - 4].content
count += 1
return cell
}
しっかりとリプライが表示されていることが確認できました。
以上でタイムラインの実装を終了にしたいと思います。
まだまだいろいろと実装できることはありますが、
実装しはじめたら終わらないのでこのくらいにしたいと思います。
最後までご覧いただきありがとうございました!