From 74b7ca34e28c23f0248dc315598c8d8efcc75a5c Mon Sep 17 00:00:00 2001 From: Thomas Ricouard Date: Sat, 26 Dec 2015 22:12:10 +0100 Subject: [PATCH 1/5] Refactor to support JSON API --- Hacker News WatchKit Extension/Info.plist | 5 + .../InterfaceController.swift | 17 +-- SwiftHN/AppDelegate.swift | 16 +-- SwiftHN/Cells/CommentsCell.swift | 20 ++- SwiftHN/Cells/NewsCell.swift | 63 +++++---- SwiftHN/Utils/Preferences.swift | 2 +- .../CategoriesViewController.swift | 5 +- .../DetailViewController.swift | 54 +++++--- .../ViewControllers/NewsViewController.swift | 94 ++++--------- .../ViewControllers/UserViewController.swift | 37 +---- SwiftHNShared/Extension/NSDate+TimeAgo.swift | 129 ++---------------- .../HNKit/HNTableViewController.swift | 22 +-- SwiftHNToday/Info.plist | 5 + SwiftHNToday/TodayViewController.swift | 20 ++- SwiftHNToday/TodayWidgetCell.swift | 16 ++- 15 files changed, 188 insertions(+), 317 deletions(-) diff --git a/Hacker News WatchKit Extension/Info.plist b/Hacker News WatchKit Extension/Info.plist index 3cd01bb..31ee5d7 100644 --- a/Hacker News WatchKit Extension/Info.plist +++ b/Hacker News WatchKit Extension/Info.plist @@ -22,6 +22,11 @@ ???? CFBundleVersion 22 + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + NSExtension NSExtensionAttributes diff --git a/Hacker News WatchKit Extension/InterfaceController.swift b/Hacker News WatchKit Extension/InterfaceController.swift index 205f467..fa10c9a 100644 --- a/Hacker News WatchKit Extension/InterfaceController.swift +++ b/Hacker News WatchKit Extension/InterfaceController.swift @@ -20,16 +20,15 @@ class HNNewsRow: NSObject { class InterfaceController: WKInterfaceController { @IBOutlet var tableView: WKInterfaceTable! - var datasource: [Post]! + var datasource: [Int]! override func awakeWithContext(context: AnyObject?) { super.awakeWithContext(context) - Post.fetch(Post.PostFilter.Top, completion: {(posts: [Post]!, error: Fetcher.ResponseError!, local: Bool) in + Post.fetchPost(.Top) { (posts, error, local) -> Void in self.datasource = posts self.setupTable(); - }) - + } } func setupTable() { @@ -37,10 +36,12 @@ class InterfaceController: WKInterfaceController { var rowCount = 0 for item in self.datasource { let row = self.tableView.rowControllerAtIndex(rowCount) as! HNNewsRow - row.voteLabel.setText(String(item.points)) - row.titleLabel.setText(item.title) - row.usernameLabel.setText(String(item.commentsCount) + " Comments") - row.domainLabel.setText(item.domain) + Post.fetchPost(item, completion: { (post, error, local) -> Void in + row.voteLabel.setText(String(post.score)) + row.titleLabel.setText(post.title!) + row.usernameLabel.setText(String(post.commentsCount) + " Comments") + row.domainLabel.setText(post.domain!) + }) rowCount++ } } diff --git a/SwiftHN/AppDelegate.swift b/SwiftHN/AppDelegate.swift index bbfe540..e2fec38 100644 --- a/SwiftHN/AppDelegate.swift +++ b/SwiftHN/AppDelegate.swift @@ -33,14 +33,14 @@ class AppDelegate: UIResponder, UIApplicationDelegate { } func application(application: UIApplication, performFetchWithCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) { - Post.fetch(Post.PostFilter.Top, completion: {(posts: [Post]!, error: Fetcher.ResponseError!, local: Bool) in - if (!local) { - completionHandler(UIBackgroundFetchResult.NewData) - } - else if (error != nil) { - completionHandler(UIBackgroundFetchResult.Failed) - } - }) + Post.fetchPost(.Top) { (posts, error, local) -> Void in + if (!local) { + completionHandler(UIBackgroundFetchResult.NewData) + } + else if (error != nil) { + completionHandler(UIBackgroundFetchResult.Failed) + } + } } func applicationWillResignActive(application: UIApplication) { diff --git a/SwiftHN/Cells/CommentsCell.swift b/SwiftHN/Cells/CommentsCell.swift index 18b1e43..0b959ab 100644 --- a/SwiftHN/Cells/CommentsCell.swift +++ b/SwiftHN/Cells/CommentsCell.swift @@ -19,10 +19,10 @@ let CommentCellBottomMargin: CGFloat = 16.0 class CommentsCell: UITableViewCell { - var comment: Comment! { + var comment: Post! { didSet { - let username = comment.username - let date = " - " + comment.prettyTime! + let username = comment!.username + let date = " - " + NSDate(timeIntervalSince1970: comment!.time).timeAgo let usernameAttributed = NSAttributedString(string: username!, attributes: [NSFontAttributeName : UIFont.boldSystemFontOfSize(CommentCellFontSize), @@ -36,7 +36,15 @@ class CommentsCell: UITableViewCell { self.commentLabel.font = UIFont.systemFontOfSize(CommentCellFontSize) self.usernameLabel.attributedText = fullAttributed - self.commentLabel.text = comment.text + self.commentLabel.text = comment!.text + } + } + + var commentId: Int? { + didSet { + Post.fetchPost(self.commentId!) { (post, error, local) -> Void in + + } } } @@ -84,8 +92,8 @@ class CommentsCell: UITableViewCell { self.commentLabel.textContainerInset = UIEdgeInsetsZero self.commentLabel.contentInset = UIEdgeInsetsZero - self.commentLabel.frame.size.width = self.contentView.bounds.width - (self.commentLeftMarginConstraint.constant * 2) - (CommentCellMarginConstant * CGFloat(self.comment.depth)) - self.indentation = CommentCellMarginConstant + (CommentCellMarginConstant * CGFloat(self.comment.depth)) + self.commentLabel.frame.size.width = self.contentView.bounds.width - (self.commentLeftMarginConstraint.constant * 2) - (CommentCellMarginConstant * CGFloat(0)) + self.indentation = CommentCellMarginConstant + (CommentCellMarginConstant * CGFloat(0)) } class func heightForText(text: String, bounds: CGRect, level: Int) -> CGFloat { diff --git a/SwiftHN/Cells/NewsCell.swift b/SwiftHN/Cells/NewsCell.swift index b0bdd37..0cebce7 100644 --- a/SwiftHN/Cells/NewsCell.swift +++ b/SwiftHN/Cells/NewsCell.swift @@ -8,6 +8,7 @@ import UIKit import HackerSwifter +import SwiftHNShared let NewsCellsId = "newsCellId" let NewsCellHeight: CGFloat = 110.0 @@ -23,39 +24,42 @@ enum NewsCellActionType: Int { @objc protocol NewsCellDelegate { func newsCellDidSelectButton(cell: NewsCell, actionType: Int, post: Post) + func newsCellPostDidLoad(cell: NewsCell) } class NewsCell: UITableViewCell { - @IBOutlet var titleLabel : UILabel! = nil - @IBOutlet var urlLabel : UILabel! = nil - @IBOutlet var voteLabel : BorderedButton! = nil - @IBOutlet var commentsLabel : BorderedButton! = nil - @IBOutlet var usernameLabel: BorderedButton! = nil - @IBOutlet var readLaterIndicator: UIView! = nil + @IBOutlet var titleLabel : UILabel! + @IBOutlet var urlLabel : UILabel! + @IBOutlet var voteLabel : BorderedButton! + @IBOutlet var commentsLabel : BorderedButton! + @IBOutlet var usernameLabel: BorderedButton! + @IBOutlet var readLaterIndicator: UIView! - @IBOutlet var titleMarginConstrain: NSLayoutConstraint! = nil + @IBOutlet var titleMarginConstrain: NSLayoutConstraint! weak var cellDelegate: NewsCellDelegate? - var post: Post! { - didSet{ - self.titleLabel.text = self.post.title! - if let _time = self.post.time { - let date = NSDate(timeIntervalSince1970: NSTimeInterval(_time)) - self.urlLabel.text = self.post.domain! + " - " + date.timeAgo - } - else { - self.urlLabel.text = self.post.domain! + " - " + self.post.prettyTime! + var post: Post? { + didSet { + + self.titleLabel.text = self.post!.title! + + if self.post!.time != 0 { + let time = self.post!.time + self.urlLabel.text = self.post!.domain! + " - " + NSDate(timeIntervalSince1970: NSTimeInterval(time)).timeAgo } - self.voteLabel.labelText = String(self.post.points) + " votes" - self.commentsLabel.labelText = String(self.post.commentsCount) + " comments" - self.usernameLabel.labelText = self.post.username! + + self.voteLabel.labelText = String(self.post!.score) + " votes" + self.commentsLabel.labelText = String(self.post!.commentsCount) + " comments" + self.usernameLabel.labelText = self.post!.username! + self.voteLabel.onButtonTouch = {(sender: UIButton) in self.selectedAction(.Vote) } + self.commentsLabel.onButtonTouch = {(sender: UIButton) in self.selectedAction(.Comment) } @@ -63,17 +67,25 @@ class NewsCell: UITableViewCell { self.usernameLabel.onButtonTouch = {(sender: UIButton) in self.selectedAction(.Username) } + if self.readLaterIndicator != nil { - self.readLaterIndicator.hidden = !Preferences.sharedInstance.isInReadingList(self.post.postId!) + self.readLaterIndicator.hidden = !Preferences.sharedInstance.isInReadingList(String(self.post!.id)) } + } } - var postId: Int! { + var postId: Int? { didSet { - Post.fetchPost(self.postId) { (post, error, local) -> Void in - if let _post = post { - self.post = _post + self.titleLabel.text = "Loading" + self.urlLabel.text = "" + self.voteLabel.labelText = "" + self.usernameLabel.labelText = "" + self.commentsLabel.labelText = "" + Post.fetchPost(self.postId!) { (post, error, local) -> Void in + if (self.postId == post.id) { + self.post = post + self.cellDelegate?.newsCellPostDidLoad(self) } } } @@ -88,9 +100,10 @@ class NewsCell: UITableViewCell { } func selectedAction(action: NewsCellActionType) { - self.cellDelegate?.newsCellDidSelectButton(self, actionType: action.rawValue, post: self.post) + self.cellDelegate?.newsCellDidSelectButton(self, actionType: action.rawValue, post: self.post!) } + override func layoutSubviews() { super.layoutSubviews() diff --git a/SwiftHN/Utils/Preferences.swift b/SwiftHN/Utils/Preferences.swift index af612eb..f6c186a 100644 --- a/SwiftHN/Utils/Preferences.swift +++ b/SwiftHN/Utils/Preferences.swift @@ -33,7 +33,7 @@ class Preferences { if (array == nil) { array = [] } - array.append(post.postId!) + array.append(String(post.id)) self.pUserDefault.setObject(array, forKey: pReadLater) } diff --git a/SwiftHN/ViewControllers/CategoriesViewController.swift b/SwiftHN/ViewControllers/CategoriesViewController.swift index 590dcb0..4f10048 100644 --- a/SwiftHN/ViewControllers/CategoriesViewController.swift +++ b/SwiftHN/ViewControllers/CategoriesViewController.swift @@ -10,7 +10,7 @@ import UIKit import HackerSwifter protocol CategoriesViewControllerDelegate { - func categoriesViewControllerDidSelecteFilter(controller: CategoriesViewController, filer: Post.PostFilter, title: String) + func categoriesViewControllerDidSelecteFilter(controller: CategoriesViewController, filer: Fetcher.APIEndpoint, title: String) } class CategoriesViewController: UITableViewController { @@ -56,9 +56,6 @@ class CategoriesViewController: UITableViewController { else if (cell?.textLabel?.text == "Ask HN") { self.delegate?.categoriesViewControllerDidSelecteFilter(self, filer: .Ask, title: "HN:Ask") } - else if (cell?.textLabel?.text == "Best") { - self.delegate?.categoriesViewControllerDidSelecteFilter(self, filer: .Best, title: "HN:Best") - } else if (cell?.textLabel?.text == "Show HN") { self.delegate?.categoriesViewControllerDidSelecteFilter(self, filer: .Show, title: "HN:Show") } diff --git a/SwiftHN/ViewControllers/DetailViewController.swift b/SwiftHN/ViewControllers/DetailViewController.swift index 2ed280b..d9004ae 100644 --- a/SwiftHN/ViewControllers/DetailViewController.swift +++ b/SwiftHN/ViewControllers/DetailViewController.swift @@ -12,7 +12,12 @@ import HackerSwifter class DetailViewController: HNTableViewController, NewsCellDelegate { - var post: Post! + var post: Post? { + didSet { + self.tableView.reloadData() + } + } + var cellHeightCache: [CGFloat] = [] override func viewDidLoad() { @@ -26,19 +31,14 @@ class DetailViewController: HNTableViewController, NewsCellDelegate { func onPullToFresh() { - Comment.fetch(forPost: self.post, completion: {(comments: [Comment]!, error: Fetcher.ResponseError!, local: Bool) in - if let realDatasource = comments { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, UInt(0)), { ()->() in - self.cacheHeight(realDatasource) - dispatch_async(dispatch_get_main_queue(), { ()->() in - self.datasource = realDatasource - }) - }) - } - if (!local) { - self.refreshing = false - } - }) + Post.fetchPost(self.post!.id) { (post, error, local) -> Void in + dispatch_async(dispatch_get_main_queue(), { () -> Void in + self.post = post + if (!local) { + self.refreshing = false + } + }) + } } func cacheHeight(comments: NSArray) { @@ -58,15 +58,19 @@ class DetailViewController: HNTableViewController, NewsCellDelegate { } func onShareButton() { - Helper.showShareSheet(self.post, controller: self, barbutton: self.navigationItem.rightBarButtonItem) + Helper.showShareSheet(self.post!, controller: self, barbutton: self.navigationItem.rightBarButtonItem) } override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { if (indexPath.section == 0) { - let title: NSString = self.post.title! - return NewsCell.heightForText(title, bounds: self.tableView.bounds) + if let _post = post { + if let title: NSString = _post.title! as NSString { + return NewsCell.heightForText(title, bounds: self.tableView.bounds) + } + } + return 0 } return self.cellHeightCache[indexPath.row] as CGFloat } @@ -80,8 +84,8 @@ class DetailViewController: HNTableViewController, NewsCellDelegate { return 1 } - if (self.datasource != nil) { - return self.datasource.count + if (self.post?.kids != nil) { + return self.post!.kids!.count } return 0 @@ -96,8 +100,8 @@ class DetailViewController: HNTableViewController, NewsCellDelegate { } let cell = tableView.dequeueReusableCellWithIdentifier(CommentsCellId) as! CommentsCell! - let comment = self.datasource[indexPath.row] as! Comment - cell.comment = comment + let comment = self.datasource[indexPath.row] as! Int + cell.commentId = comment return cell } @@ -113,10 +117,16 @@ class DetailViewController: HNTableViewController, NewsCellDelegate { } } + func newsCellPostDidLoad(cell: NewsCell) { + + } + + + //MARK: Controller override func shouldPerformSegueWithIdentifier(identifier: String, sender: AnyObject?) -> Bool { if #available(iOS 9, *) { if identifier == "toWebview" { - if let url = (sender as? NewsCell)?.post.url { + if let url = (sender as? NewsCell)?.post!.url { presentViewController(SafariViewController(URL: url), animated: true, completion: nil) return false } diff --git a/SwiftHN/ViewControllers/NewsViewController.swift b/SwiftHN/ViewControllers/NewsViewController.swift index 284a42a..ed04e4d 100644 --- a/SwiftHN/ViewControllers/NewsViewController.swift +++ b/SwiftHN/ViewControllers/NewsViewController.swift @@ -12,71 +12,25 @@ import HackerSwifter class NewsViewController: HNTableViewController, NewsCellDelegate, CategoriesViewControllerDelegate { - var filter: Post.PostFilter = .Top - var loadMoreEnabled = false - var infiniteScrollingView:UIView? + var filter: Fetcher.APIEndpoint = .Top override func viewDidLoad() { super.viewDidLoad() self.title = "HN:News" - self.setupInfiniteScrollingView() self.setupNavigationItems() } - private func setupInfiniteScrollingView() { - self.infiniteScrollingView = UIView(frame: CGRectMake(0, self.tableView.contentSize.height, self.tableView.bounds.size.width, 60)) - self.infiniteScrollingView!.autoresizingMask = UIViewAutoresizing.FlexibleWidth - self.infiniteScrollingView!.backgroundColor = UIColor.LoadMoreLightGrayColor() - let activityViewIndicator = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.WhiteLarge) - activityViewIndicator.color = UIColor.darkGrayColor() - activityViewIndicator.frame = CGRectMake(self.infiniteScrollingView!.frame.size.width/2-activityViewIndicator.frame.width/2, self.infiniteScrollingView!.frame.size.height/2-activityViewIndicator.frame.height/2, activityViewIndicator.frame.width, activityViewIndicator.frame.height) - activityViewIndicator.startAnimating() - self.infiniteScrollingView!.addSubview(activityViewIndicator) - } func onPullToFresh() { self.refreshing = true - Post.fetch(self.filter, completion: {(posts: [Post]!, error: Fetcher.ResponseError!, local: Bool) in - if let realDatasource = posts { - self.datasource = realDatasource - if (self.datasource.count % 30 == 0) { - self.loadMoreEnabled = true - } else { - self.loadMoreEnabled = false - } - } - if (!local) { - self.refreshing = false - } - }) - } - - func loadMore() { - let fetchPage = Int(ceil(Double(self.datasource.count)/30))+1 - Post.fetch(self.filter, page:fetchPage, completion: {(posts: [Post]!, error: Fetcher.ResponseError!, local: Bool) in - if let realDatasource = posts { - let tempDatasource:NSMutableArray = NSMutableArray(array: self.datasource) - let postsNotFromNewPageCount = ((fetchPage-1)*30) - if (tempDatasource.count - postsNotFromNewPageCount > 0) { - tempDatasource.removeObjectsInRange(NSMakeRange(postsNotFromNewPageCount, tempDatasource.count-postsNotFromNewPageCount)) - } - tempDatasource.addObjectsFromArray(realDatasource) - self.datasource = tempDatasource - if (self.datasource.count % 30 == 0) { - self.loadMoreEnabled = true - } else { - self.loadMoreEnabled = false - } - } - if (!local) { - self.refreshing = false - self.tableView.tableFooterView = nil - } - }) + Post.fetchPost(self.filter) { (post, error, local) -> Void in + self.ids = post + self.refreshing = false + } } override func viewDidAppear(animated: Bool) { @@ -104,6 +58,11 @@ class NewsViewController: HNTableViewController, NewsCellDelegate, CategoriesVie } + func post(indexpath: NSIndexPath) -> Post? { + let cell: NewsCell = self.tableView.cellForRowAtIndexPath(indexpath) as! NewsCell + return cell.post + } + //MARK: Alert management func showFirstTimeEditingCellAlert() { if (!Preferences.sharedInstance.firstTimeLaunch) { @@ -156,33 +115,29 @@ class NewsViewController: HNTableViewController, NewsCellDelegate, CategoriesVie } override func tableView(tableView: UITableView,numberOfRowsInSection section: Int) -> Int { - if (self.datasource != nil) { - return self.datasource.count + if (self.ids != nil) { + return self.ids.count } return 0 } override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { - let title: NSString = (self.datasource[indexPath.row] as! Post).title! - return NewsCell.heightForText(title, bounds: self.tableView.bounds) + return 120.0 } override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier(NewsCellsId) as? NewsCell - cell!.post = self.datasource[indexPath.row] as! Post + cell!.postId = self.ids[indexPath.row] cell!.cellDelegate = self - if (loadMoreEnabled && indexPath.row == self.datasource.count-3) { - self.tableView.tableFooterView = self.infiniteScrollingView - loadMore() - } + return cell! } override func shouldPerformSegueWithIdentifier(identifier: String, sender: AnyObject?) -> Bool { if #available(iOS 9, *) { if identifier == "toWebview" { - if let url = (sender as? NewsCell)?.post.url { + if let url = (sender as? NewsCell)?.post!.url { presentViewController(SafariViewController(URL: url), animated: true, completion: nil) return false } @@ -195,7 +150,7 @@ class NewsViewController: HNTableViewController, NewsCellDelegate, CategoriesVie if (segue.identifier == "toWebview") { let destination = segue.destinationViewController as! WebviewController if let selectedRows = self.tableView.indexPathsForSelectedRows { - destination.post = self.datasource[selectedRows[0].row] as? Post + destination.post = self.post(selectedRows[0]) } } } @@ -213,10 +168,9 @@ class NewsViewController: HNTableViewController, NewsCellDelegate, CategoriesVie let readingList = UITableViewRowAction(style: UITableViewRowActionStyle.Normal, title: "Read\nLater", handler: {(action: UITableViewRowAction, indexpath: NSIndexPath) -> Void in - if (Helper.addPostToReadingList(self.datasource[indexPath.row] as! Post)) { + if (Helper.addPostToReadingList(self.post(indexPath)!)) { } - _ = self.datasource - Preferences.sharedInstance.addToReadLater(self.datasource[indexPath.row] as! Post) + Preferences.sharedInstance.addToReadLater(self.post(indexPath)!) let cell = self.tableView.cellForRowAtIndexPath(indexPath) as! NewsCell cell.readLaterIndicator.hidden = false self.tableView.setEditing(false, animated: true) @@ -226,7 +180,7 @@ class NewsViewController: HNTableViewController, NewsCellDelegate, CategoriesVie let more = UITableViewRowAction(style: UITableViewRowActionStyle.Normal, title: "More", handler: {(action: UITableViewRowAction, indexpath: NSIndexPath) -> Void in - self.showActionSheetForPost(self.datasource[indexPath.row] as! Post) + self.showActionSheetForPost(self.post(indexPath)!) }) return [readingList, more] @@ -257,10 +211,14 @@ class NewsViewController: HNTableViewController, NewsCellDelegate, CategoriesVie } } + func newsCellPostDidLoad(cell: NewsCell) { + //let indexpath = self.tableView.indexPathForCell(cell) + //self.tableView.reloadRowsAtIndexPaths([indexpath!], withRowAnimation: UITableViewRowAnimation.Automatic) + } + //MARK: CategoriesDelegate - func categoriesViewControllerDidSelecteFilter(controller: CategoriesViewController, filer: Post.PostFilter, title: String) { + func categoriesViewControllerDidSelecteFilter(controller: CategoriesViewController, filer: Fetcher.APIEndpoint, title: String) { self.filter = filer - self.datasource = nil self.onPullToFresh() self.title = title } diff --git a/SwiftHN/ViewControllers/UserViewController.swift b/SwiftHN/ViewControllers/UserViewController.swift index 740ca7f..a30ae3c 100644 --- a/SwiftHN/ViewControllers/UserViewController.swift +++ b/SwiftHN/ViewControllers/UserViewController.swift @@ -25,42 +25,11 @@ class UserViewController: NewsViewController { self.refreshing = true - Post.fetch(self.user, completion: {(posts: [Post]!, error: Fetcher.ResponseError!, local: Bool) in - if let realPosts = posts { - self.datasource = realPosts - if (self.datasource.count % 30 == 0) { - self.loadMoreEnabled = true - } else { - self.loadMoreEnabled = false - } - } - if (!local) { - self.refreshing = false - } - }) - } - override func loadMore() { - let fetchPage = Int(ceil(Double(self.datasource.count)/30))+1 - Post.fetch(self.user, page:fetchPage, lastPostId:(self.datasource.lastObject as! Post).postId, completion: {(posts: [Post]!, error: Fetcher.ResponseError!, local: Bool) in - if let realPosts = posts { - let tempPosts:NSMutableArray = NSMutableArray(array: self.datasource) - let postsNotFromNewPageCount = ((fetchPage-1)*30) - if (postsNotFromNewPageCount > 0) { - tempPosts.removeObjectsInRange(NSMakeRange(postsNotFromNewPageCount, tempPosts.count-postsNotFromNewPageCount)) - } - tempPosts.addObjectsFromArray(realPosts) - self.datasource = tempPosts - if (self.datasource.count % 30 == 0) { - self.loadMoreEnabled = true - } else { - self.loadMoreEnabled = false - } - } + Post.fetchPost(self.user) { (posts, error, local) -> Void in + self.ids = posts if (!local) { self.refreshing = false - self.tableView.tableFooterView = nil } - }) + } } - } diff --git a/SwiftHNShared/Extension/NSDate+TimeAgo.swift b/SwiftHNShared/Extension/NSDate+TimeAgo.swift index 8c23f93..436733b 100644 --- a/SwiftHNShared/Extension/NSDate+TimeAgo.swift +++ b/SwiftHNShared/Extension/NSDate+TimeAgo.swift @@ -1,94 +1,23 @@ -// -// NSDate+Extension.swift -// Tasty -// -// Created by Vitaliy Kuzmenko on 17/10/14. -// http://github.com/vitkuzmenko -// Copyright (c) 2014 Vitaliy Kuz'menko. All rights reserved. -// - import Foundation -func NSDateTimeAgoLocalizedStrings(key: String) -> String { - let resourcePath: String? - - if let frameworkBundle = NSBundle(identifier: "com.kevinlawler.NSDateTimeAgo") { - // Load from Framework - resourcePath = frameworkBundle.resourcePath - } else { - // Load from Main Bundle - resourcePath = NSBundle.mainBundle().resourcePath - } - - if resourcePath == nil { - return "" - } - - let path = NSURL(fileURLWithPath: resourcePath!).URLByAppendingPathComponent("NSDateTimeAgo.bundle") - guard let bundle = NSBundle(URL: path) else { - return "" - } - - return NSLocalizedString(key, tableName: "NSDateTimeAgo", bundle: bundle, comment: "") -} - extension NSDate { - // shows 1 or two letter abbreviation for units. - // does not include 'ago' text ... just {value}{unit-abbreviation} - // does not include interim summary options such as 'Just now' - public var timeAgoSimple: String { - let components = self.dateComponents() - - if components.year > 0 { - return stringFromFormat("%%d%@yr", withValue: components.year) - } - - if components.month > 0 { - return stringFromFormat("%%d%@mo", withValue: components.month) - } - - // TODO: localize for other calanders - if components.day >= 7 { - let value = components.day/7 - return stringFromFormat("%%d%@w", withValue: value) - } - - if components.day > 0 { - return stringFromFormat("%%d%@d", withValue: components.day) - } - - if components.hour > 0 { - return stringFromFormat("%%d%@h", withValue: components.hour) - } - - if components.minute > 0 { - return stringFromFormat("%%d%@m", withValue: components.minute) - } - - if components.second > 0 { - return stringFromFormat("%%d%@s", withValue: components.second ) - } - - return "" - } - public var timeAgo: String { let components = self.dateComponents() if components.year > 0 { if components.year < 2 { - return NSDateTimeAgoLocalizedStrings("Last year") + return "Last year" } else { - return stringFromFormat("%%d %@years ago", withValue: components.year) + return String(format: "%@ years ago", arguments: [String(components.year)]) } } if components.month > 0 { if components.month < 2 { - return NSDateTimeAgoLocalizedStrings("Last month") + return "Last month" } else { - return stringFromFormat("%%d %@months ago", withValue: components.month) + return String(format: "%@ months ago", arguments: [String(components.month)]) } } @@ -96,41 +25,41 @@ extension NSDate { if components.day >= 7 { let week = components.day/7 if week < 2 { - return NSDateTimeAgoLocalizedStrings("Last week") + return "Last week" } else { - return stringFromFormat("%%d %@weeks ago", withValue: week) + return String(format: "%@ weeks ago", arguments: [String(week)]) } } if components.day > 0 { if components.day < 2 { - return NSDateTimeAgoLocalizedStrings("Yesterday") + return "Yesterday" } else { - return stringFromFormat("%%d %@days ago", withValue: components.day) + return String(format: "%@ days ago", arguments: [String(Double(components.day))]) } } if components.hour > 0 { if components.hour < 2 { - return NSDateTimeAgoLocalizedStrings("An hour ago") + return "An hour ago" } else { - return stringFromFormat("%%d %@hours ago", withValue: components.hour) + return String(format: "%@ hours ago", arguments: [String(components.hour)]) } } if components.minute > 0 { if components.minute < 2 { - return NSDateTimeAgoLocalizedStrings("A minute ago") + return "A minute ago" } else { - return stringFromFormat("%%d %@minutes ago", withValue: components.minute) + return String(format: "%@ minutes ago", arguments: [String(components.minute)]) } } if components.second > 0 { if components.second < 5 { - return NSDateTimeAgoLocalizedStrings("Just now") + return "Just now" } else { - return stringFromFormat("%%d %@seconds ago", withValue: components.second) + return String(format: "%@ seconds ago", arguments: [String(Double(components.second))]) } } @@ -142,35 +71,5 @@ extension NSDate { return calander.components([.Second, .Minute, .Hour, .Day, .Month, .Year], fromDate: self, toDate: NSDate(), options: []) } - private func stringFromFormat(format: String, withValue value: Int) -> String { - let localeFormat = String(format: format, getLocaleFormatUnderscoresWithValue(Double(value))) - return String(format: NSDateTimeAgoLocalizedStrings(localeFormat), value) - } - - private func getLocaleFormatUnderscoresWithValue(value: Double) -> String { - guard let localeCode = NSLocale.preferredLanguages().first else { - return "" - } - - // Russian (ru) and Ukrainian (uk) - if localeCode == "ru" || localeCode == "uk" { - let XY = Int(floor(value)) % 100 - let Y = Int(floor(value)) % 10 - - if Y == 0 || Y > 4 || (XY > 10 && XY < 15) { - return "" - } - - if Y > 1 && Y < 5 && (XY < 10 || XY > 20) { - return "_" - } - - if Y == 1 && XY != 11 { - return "__" - } - } - - return "" - } } diff --git a/SwiftHNShared/HNKit/HNTableViewController.swift b/SwiftHNShared/HNKit/HNTableViewController.swift index 26ffb8b..d4f2049 100644 --- a/SwiftHNShared/HNKit/HNTableViewController.swift +++ b/SwiftHNShared/HNKit/HNTableViewController.swift @@ -9,19 +9,19 @@ import UIKit public class HNTableViewController: UITableViewController { - + public var refreshing: Bool = false { - didSet { - if (self.refreshing) { - self.refreshControl?.beginRefreshing() - self.refreshControl?.attributedTitle = NSAttributedString(string: "Loading...") - } - else { - self.refreshControl?.endRefreshing() - self.refreshControl?.attributedTitle = NSAttributedString(string: "Pull to Refresh") + didSet { + if (self.refreshing) { + self.refreshControl?.beginRefreshing() + self.refreshControl?.attributedTitle = NSAttributedString(string: "Loading...") + } + else { + self.refreshControl?.endRefreshing() + self.refreshControl?.attributedTitle = NSAttributedString(string: "Pull to Refresh") + } } } - } public var datasource: NSArray! { didSet { @@ -37,7 +37,7 @@ public class HNTableViewController: UITableViewController { public override func viewDidLoad() { super.viewDidLoad() - + self.refreshControl = UIRefreshControl() self.refreshControl?.addTarget(self, action: "onPullToFresh", forControlEvents: UIControlEvents.ValueChanged) } diff --git a/SwiftHNToday/Info.plist b/SwiftHNToday/Info.plist index 3314827..f271b12 100644 --- a/SwiftHNToday/Info.plist +++ b/SwiftHNToday/Info.plist @@ -22,6 +22,11 @@ ???? CFBundleVersion 1 + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + NSExtension NSExtensionMainStoryboard diff --git a/SwiftHNToday/TodayViewController.swift b/SwiftHNToday/TodayViewController.swift index b1ef6b0..26ae917 100644 --- a/SwiftHNToday/TodayViewController.swift +++ b/SwiftHNToday/TodayViewController.swift @@ -18,7 +18,7 @@ class TodayViewController: UIViewController, NCWidgetProviding, UITableViewDeleg let topBottomWidgetInset: CGFloat = 10.0 var completionHandler: ((NCUpdateResult) -> Void)? - var posts: [Post] = [] { + var posts: [Int] = [] { didSet { self.tableView.reloadData() self.preferredContentSize = CGSizeMake(0, self.tableView.contentSize.height) @@ -39,12 +39,10 @@ class TodayViewController: UIViewController, NCWidgetProviding, UITableViewDeleg self.tableView.backgroundColor = UIColor.clearColor() - Post.fetch(Post.PostFilter.Top, completion: {(posts: [Post]!, error: Fetcher.ResponseError!, local: Bool) in - if let realDatasource = posts { - self.posts = realDatasource - self.completionHandler?(NCUpdateResult.NewData) - } - }) + Post.fetchPost(.Top) { (posts, error, local) -> Void in + self.posts = posts + self.completionHandler?(NCUpdateResult.NewData) + } } override func viewWillAppear(animated: Bool) { @@ -124,14 +122,14 @@ class TodayViewController: UIViewController, NCWidgetProviding, UITableViewDeleg func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = self.tableView.dequeueReusableCellWithIdentifier(todayCellId) as? TodayWidgetCell - let post = self.posts[indexPath.row] as Post - cell!.post = post + let post = self.posts[indexPath.row] as Int + cell!.postId = post return cell! } func tableView(tableView: UITableView , didSelectRowAtIndexPath indexPath: NSIndexPath) { - let post = self.posts[indexPath.row] as Post - self.extensionContext!.openURL(post.url!, completionHandler: nil) + let cell: TodayWidgetCell = self.tableView.cellForRowAtIndexPath(indexPath) as! TodayWidgetCell + self.extensionContext!.openURL(cell.post!.url!, completionHandler: nil) } } diff --git a/SwiftHNToday/TodayWidgetCell.swift b/SwiftHNToday/TodayWidgetCell.swift index 9a5a91a..aaa170f 100644 --- a/SwiftHNToday/TodayWidgetCell.swift +++ b/SwiftHNToday/TodayWidgetCell.swift @@ -19,14 +19,22 @@ class TodayWidgetCell: UITableViewCell { @IBOutlet var postVoteLabel: RoundedLabel! @IBOutlet var subtitleWrapperView: UIView! - var post: Post! { + var post: Post? { didSet { - self.postTitleLabel.text = self.post.title! - self.postVoteLabel.text = String(self.post.points) - self.postSubtitleLabel.text = self.post.domain! + " - " + self.post.prettyTime! + self.postTitleLabel.text = self.post!.title! + self.postVoteLabel.text = String(self.post!.score) + self.postSubtitleLabel.text = self.post!.domain! + " - " + NSDate(timeIntervalSince1970: self.post!.time).timeAgo } } + var postId: Int? { + didSet { + self.postTitleLabel.text = "Loading" + Post.fetchPost(self.postId!) { (post, error, local) -> Void in + self.post = post + } + } + } override func awakeFromNib() { super.awakeFromNib() From 2cc341fa3fe42494ac881e789b53f4cc01cd9a9e Mon Sep 17 00:00:00 2001 From: Thomas Ricouard Date: Sat, 26 Dec 2015 22:19:12 +0100 Subject: [PATCH 2/5] Fix HackerSwifter reference --- SwiftHN/libs/submodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SwiftHN/libs/submodules b/SwiftHN/libs/submodules index d9622e1..3087a2b 160000 --- a/SwiftHN/libs/submodules +++ b/SwiftHN/libs/submodules @@ -1 +1 @@ -Subproject commit d9622e1385bc04a14b2e6c1394bfb841be12c8f9 +Subproject commit 3087a2b810ba0792b83e8e4083c043c78d4d8cc8 From 8fa5653710b8483f242fa4e1332f5fa6ddd441cb Mon Sep 17 00:00:00 2001 From: Thomas Ricouard Date: Mon, 28 Dec 2015 13:51:15 +0100 Subject: [PATCH 3/5] WIP API support --- .../CommentsInterfaceController.swift | 24 +++--- .../InterfaceController.swift | 6 +- SwiftHN/AppDelegate.swift | 2 +- SwiftHN/Cells/CommentsCell.swift | 19 ++--- SwiftHN/Cells/NewsCell.swift | 43 ++++------- SwiftHN/Utils/Helpers.swift | 10 +-- SwiftHN/Utils/Preferences.swift | 4 +- .../DetailViewController.swift | 47 +++++------ .../ViewControllers/NewsViewController.swift | 77 +++++++++++-------- .../ViewControllers/UserViewController.swift | 4 +- .../ViewControllers/WebviewController.swift | 8 +- SwiftHN/libs/submodules | 2 +- .../HNKit/HNTableViewController.swift | 14 ++-- SwiftHNToday/TodayViewController.swift | 12 +-- SwiftHNToday/TodayWidgetCell.swift | 12 +-- 15 files changed, 142 insertions(+), 142 deletions(-) diff --git a/Hacker News WatchKit Extension/CommentsInterfaceController.swift b/Hacker News WatchKit Extension/CommentsInterfaceController.swift index e71f012..f0b6416 100644 --- a/Hacker News WatchKit Extension/CommentsInterfaceController.swift +++ b/Hacker News WatchKit Extension/CommentsInterfaceController.swift @@ -16,18 +16,14 @@ class HNCommentRow: NSObject { } class CommentsInterfaceController: WKInterfaceController { - var post: Post! - var datasource: [Comment]! + var post: Item! + var datasource: [Int]! @IBOutlet var tableView: WKInterfaceTable! override func awakeWithContext(context: AnyObject?) { - if let realPost = context as? Post { + if let realPost = context as? Item { self.post = realPost - - Comment.fetch(forPost: self.post, completion: {(comments: [Comment]!, error: Fetcher.ResponseError!, local: Bool) in - self.datasource = comments - self.setupTable() - }) + setupTable() } } @@ -36,11 +32,15 @@ class CommentsInterfaceController: WKInterfaceController { var rowCount = 0 for item in self.datasource { let row = self.tableView.rowControllerAtIndex(rowCount) as! HNCommentRow - if let realtext = item.text { - row.commentLabel.setText(realtext) - row.usernameLabel.setText(item.username) - } + setupRow(row, id: item) rowCount++ } } + + func setupRow(row: HNCommentRow, id: Int) { + Item.fetchPost(id, completion: { (item, error, local) -> Void in + row.commentLabel.setText(item.text!) + row.usernameLabel.setText(item.username!) + }) + } } diff --git a/Hacker News WatchKit Extension/InterfaceController.swift b/Hacker News WatchKit Extension/InterfaceController.swift index fa10c9a..00d9b79 100644 --- a/Hacker News WatchKit Extension/InterfaceController.swift +++ b/Hacker News WatchKit Extension/InterfaceController.swift @@ -25,8 +25,8 @@ class InterfaceController: WKInterfaceController { override func awakeWithContext(context: AnyObject?) { super.awakeWithContext(context) - Post.fetchPost(.Top) { (posts, error, local) -> Void in - self.datasource = posts + Item.fetchPost(.Top) { (items, error, local) -> Void in + self.datasource = items self.setupTable(); } } @@ -36,7 +36,7 @@ class InterfaceController: WKInterfaceController { var rowCount = 0 for item in self.datasource { let row = self.tableView.rowControllerAtIndex(rowCount) as! HNNewsRow - Post.fetchPost(item, completion: { (post, error, local) -> Void in + Item.fetchPost(item, completion: { (post, error, local) -> Void in row.voteLabel.setText(String(post.score)) row.titleLabel.setText(post.title!) row.usernameLabel.setText(String(post.commentsCount) + " Comments") diff --git a/SwiftHN/AppDelegate.swift b/SwiftHN/AppDelegate.swift index e2fec38..9c182b7 100644 --- a/SwiftHN/AppDelegate.swift +++ b/SwiftHN/AppDelegate.swift @@ -33,7 +33,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { } func application(application: UIApplication, performFetchWithCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) { - Post.fetchPost(.Top) { (posts, error, local) -> Void in + Item.fetchPost(.Top) { (items, error, local) -> Void in if (!local) { completionHandler(UIBackgroundFetchResult.NewData) } diff --git a/SwiftHN/Cells/CommentsCell.swift b/SwiftHN/Cells/CommentsCell.swift index 0b959ab..3547a3f 100644 --- a/SwiftHN/Cells/CommentsCell.swift +++ b/SwiftHN/Cells/CommentsCell.swift @@ -19,12 +19,15 @@ let CommentCellBottomMargin: CGFloat = 16.0 class CommentsCell: UITableViewCell { - var comment: Post! { + var comment: Item! { didSet { - let username = comment!.username + var username = "" + if let _username = comment!.username { + username = _username + } let date = " - " + NSDate(timeIntervalSince1970: comment!.time).timeAgo - let usernameAttributed = NSAttributedString(string: username!, + let usernameAttributed = NSAttributedString(string: username, attributes: [NSFontAttributeName : UIFont.boldSystemFontOfSize(CommentCellFontSize), NSForegroundColorAttributeName: UIColor.HNColor()]) let dateAttribute = NSAttributedString(string: date, @@ -36,14 +39,14 @@ class CommentsCell: UITableViewCell { self.commentLabel.font = UIFont.systemFontOfSize(CommentCellFontSize) self.usernameLabel.attributedText = fullAttributed - self.commentLabel.text = comment!.text + self.commentLabel.text = comment!.text } } var commentId: Int? { didSet { - Post.fetchPost(self.commentId!) { (post, error, local) -> Void in - + Item.fetchPost(self.commentId!) { (item, error, local) -> Void in + self.comment = item } } } @@ -85,9 +88,7 @@ class CommentsCell: UITableViewCell { override func layoutSubviews() { super.layoutSubviews() - - self.commentLabel.text = comment.text - + self.commentLabel.textContainer.lineFragmentPadding = 0 self.commentLabel.textContainerInset = UIEdgeInsetsZero self.commentLabel.contentInset = UIEdgeInsetsZero diff --git a/SwiftHN/Cells/NewsCell.swift b/SwiftHN/Cells/NewsCell.swift index 0cebce7..fc1faf1 100644 --- a/SwiftHN/Cells/NewsCell.swift +++ b/SwiftHN/Cells/NewsCell.swift @@ -23,8 +23,7 @@ enum NewsCellActionType: Int { } @objc protocol NewsCellDelegate { - func newsCellDidSelectButton(cell: NewsCell, actionType: Int, post: Post) - func newsCellPostDidLoad(cell: NewsCell) + func newsCellDidSelectButton(cell: NewsCell, actionType: Int, item: Item) } class NewsCell: UITableViewCell { @@ -40,19 +39,21 @@ class NewsCell: UITableViewCell { weak var cellDelegate: NewsCellDelegate? - var post: Post? { + var index: Int = -1 + + var item: Item? { didSet { - self.titleLabel.text = self.post!.title! + self.titleLabel.text = self.item!.title! - if self.post!.time != 0 { - let time = self.post!.time - self.urlLabel.text = self.post!.domain! + " - " + NSDate(timeIntervalSince1970: NSTimeInterval(time)).timeAgo + if self.item!.time != 0 { + let time = self.item!.time + self.urlLabel.text = self.item!.domain! + " - " + NSDate(timeIntervalSince1970: NSTimeInterval(time)).timeAgo } - self.voteLabel.labelText = String(self.post!.score) + " votes" - self.commentsLabel.labelText = String(self.post!.commentsCount) + " comments" - self.usernameLabel.labelText = self.post!.username! + self.voteLabel.labelText = String(self.item!.score) + " votes" + self.commentsLabel.labelText = String(self.item!.commentsCount) + " comments" + self.usernameLabel.labelText = self.item!.username! self.voteLabel.onButtonTouch = {(sender: UIButton) in @@ -69,28 +70,12 @@ class NewsCell: UITableViewCell { } if self.readLaterIndicator != nil { - self.readLaterIndicator.hidden = !Preferences.sharedInstance.isInReadingList(String(self.post!.id)) + self.readLaterIndicator.hidden = !Preferences.sharedInstance.isInReadingList(String(self.item!.id)) } } } - - var postId: Int? { - didSet { - self.titleLabel.text = "Loading" - self.urlLabel.text = "" - self.voteLabel.labelText = "" - self.usernameLabel.labelText = "" - self.commentsLabel.labelText = "" - Post.fetchPost(self.postId!) { (post, error, local) -> Void in - if (self.postId == post.id) { - self.post = post - self.cellDelegate?.newsCellPostDidLoad(self) - } - } - } - } - + required init?(coder aDecoder: NSCoder) { // required for Xcode6-Beta5 super.init(coder: aDecoder) } @@ -100,7 +85,7 @@ class NewsCell: UITableViewCell { } func selectedAction(action: NewsCellActionType) { - self.cellDelegate?.newsCellDidSelectButton(self, actionType: action.rawValue, post: self.post!) + self.cellDelegate?.newsCellDidSelectButton(self, actionType: action.rawValue, item: self.item!) } diff --git a/SwiftHN/Utils/Helpers.swift b/SwiftHN/Utils/Helpers.swift index 8d3c577..f2a3732 100644 --- a/SwiftHN/Utils/Helpers.swift +++ b/SwiftHN/Utils/Helpers.swift @@ -13,12 +13,12 @@ import HackerSwifter class Helper { - class func addPostToReadingList(post: Post) -> Bool { + class func addPostToReadingList(item: Item) -> Bool { let readingList = SSReadingList.defaultReadingList() var error: NSError? - if let url: String = post.url?.absoluteString { + if let url: String = item.url?.absoluteString { do { - try readingList!.addReadingListItemWithURL(NSURL(string: url)!, title: post.title, previewText: nil) + try readingList!.addReadingListItemWithURL(NSURL(string: url)!, title: item.title, previewText: nil) } catch let error1 as NSError { error = error1 } @@ -27,8 +27,8 @@ class Helper { return false } - class func showShareSheet(post: Post, controller: UIViewController, barbutton: UIBarButtonItem!) { - let sheet = UIActivityViewController(activityItems: [NSString(string: post.title!), post.url!], applicationActivities: [OpenSafariActivity()]) + class func showShareSheet(item: Item, controller: UIViewController, barbutton: UIBarButtonItem!) { + let sheet = UIActivityViewController(activityItems: [NSString(string: item.title!), item.url!], applicationActivities: [OpenSafariActivity()]) if sheet.popoverPresentationController != nil { sheet.modalPresentationStyle = UIModalPresentationStyle.Popover sheet.popoverPresentationController?.sourceView = controller.view diff --git a/SwiftHN/Utils/Preferences.swift b/SwiftHN/Utils/Preferences.swift index f6c186a..c956757 100644 --- a/SwiftHN/Utils/Preferences.swift +++ b/SwiftHN/Utils/Preferences.swift @@ -28,12 +28,12 @@ class Preferences { } } - func addToReadLater(post: Post) { + func addToReadLater(item: Item) { var array: [AnyObject]! = self.pUserDefault.arrayForKey(pReadLater) if (array == nil) { array = [] } - array.append(String(post.id)) + array.append(String(item)) self.pUserDefault.setObject(array, forKey: pReadLater) } diff --git a/SwiftHN/ViewControllers/DetailViewController.swift b/SwiftHN/ViewControllers/DetailViewController.swift index d9004ae..008a5ff 100644 --- a/SwiftHN/ViewControllers/DetailViewController.swift +++ b/SwiftHN/ViewControllers/DetailViewController.swift @@ -12,11 +12,7 @@ import HackerSwifter class DetailViewController: HNTableViewController, NewsCellDelegate { - var post: Post? { - didSet { - self.tableView.reloadData() - } - } + var item: Item? var cellHeightCache: [CGFloat] = [] @@ -31,9 +27,12 @@ class DetailViewController: HNTableViewController, NewsCellDelegate { func onPullToFresh() { - Post.fetchPost(self.post!.id) { (post, error, local) -> Void in + Item.fetchPost(self.item!.id) { (item, error, local) -> Void in dispatch_async(dispatch_get_main_queue(), { () -> Void in - self.post = post + self.item = item + if let kids = item.kids { + self.ids = kids + } if (!local) { self.refreshing = false } @@ -42,6 +41,7 @@ class DetailViewController: HNTableViewController, NewsCellDelegate { } func cacheHeight(comments: NSArray) { + /* cellHeightCache = [] for comment : AnyObject in comments { if let realComment = comment as? Comment { @@ -49,6 +49,7 @@ class DetailViewController: HNTableViewController, NewsCellDelegate { cellHeightCache.append(height) } } + */ } @@ -58,21 +59,17 @@ class DetailViewController: HNTableViewController, NewsCellDelegate { } func onShareButton() { - Helper.showShareSheet(self.post!, controller: self, barbutton: self.navigationItem.rightBarButtonItem) + Helper.showShareSheet(self.item!, controller: self, barbutton: self.navigationItem.rightBarButtonItem) } override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { if (indexPath.section == 0) { - if let _post = post { - if let title: NSString = _post.title! as NSString { - return NewsCell.heightForText(title, bounds: self.tableView.bounds) - } - } - return 0 + return NewsCell.heightForText((self.item?.title)!, bounds: self.tableView.bounds) } - return self.cellHeightCache[indexPath.row] as CGFloat + return 100.0 + //return self.cellHeightCache[indexPath.row] as CGFloat } override func numberOfSectionsInTableView(tableView: UITableView) -> Int { @@ -84,32 +81,28 @@ class DetailViewController: HNTableViewController, NewsCellDelegate { return 1 } - if (self.post?.kids != nil) { - return self.post!.kids!.count - } - - return 0 + return self.ids.count } override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { if (indexPath.section == 0) { let cell = tableView.dequeueReusableCellWithIdentifier(NewsCellsId) as? NewsCell - cell!.post = self.post + cell!.item = self.item cell!.cellDelegate = self; return cell! } let cell = tableView.dequeueReusableCellWithIdentifier(CommentsCellId) as! CommentsCell! - let comment = self.datasource[indexPath.row] as! Int + let comment = self.ids[indexPath.row] cell.commentId = comment return cell } //MARK: NewsCellDelegate - func newsCellDidSelectButton(cell: NewsCell, actionType: Int, post: Post) { + func newsCellDidSelectButton(cell: NewsCell, actionType: Int, item: Item) { if (actionType == NewsCellActionType.Username.rawValue) { - if let realUsername = post.username { + if let realUsername = item.username { let detailVC = self.storyboard?.instantiateViewControllerWithIdentifier("UserViewController") as! UserViewController detailVC.user = realUsername self.showDetailViewController(detailVC, sender: self) @@ -126,7 +119,7 @@ class DetailViewController: HNTableViewController, NewsCellDelegate { override func shouldPerformSegueWithIdentifier(identifier: String, sender: AnyObject?) -> Bool { if #available(iOS 9, *) { if identifier == "toWebview" { - if let url = (sender as? NewsCell)?.post!.url { + if let url = (sender as? NewsCell)?.item!.url { presentViewController(SafariViewController(URL: url), animated: true, completion: nil) return false } @@ -138,7 +131,7 @@ class DetailViewController: HNTableViewController, NewsCellDelegate { override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) { if (segue.identifier == "toWebview") { let destination = segue.destinationViewController as! WebviewController - destination.post = self.post + destination.item = self.item } } @@ -149,7 +142,7 @@ class DetailViewController: HNTableViewController, NewsCellDelegate { //Event if it's useless in our case. }, completion: { (context: UIViewControllerTransitionCoordinatorContext!) -> Void in dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, UInt(0)), { ()->() in - self.cacheHeight(self.datasource) + //self.cacheHeight(self.datasource) dispatch_async(dispatch_get_main_queue(), { ()->() in self.tableView.reloadData() }) diff --git a/SwiftHN/ViewControllers/NewsViewController.swift b/SwiftHN/ViewControllers/NewsViewController.swift index ed04e4d..cf3c645 100644 --- a/SwiftHN/ViewControllers/NewsViewController.swift +++ b/SwiftHN/ViewControllers/NewsViewController.swift @@ -27,9 +27,11 @@ class NewsViewController: HNTableViewController, NewsCellDelegate, CategoriesVie self.refreshing = true - Post.fetchPost(self.filter) { (post, error, local) -> Void in - self.ids = post - self.refreshing = false + Item.fetchPost(self.filter) { (items, error, local) -> Void in + self.ids = items + if !local { + self.refreshing = false + } } } @@ -58,9 +60,9 @@ class NewsViewController: HNTableViewController, NewsCellDelegate, CategoriesVie } - func post(indexpath: NSIndexPath) -> Post? { + func item(indexpath: NSIndexPath) -> Item? { let cell: NewsCell = self.tableView.cellForRowAtIndexPath(indexpath) as! NewsCell - return cell.post + return cell.item } //MARK: Alert management @@ -76,24 +78,24 @@ class NewsViewController: HNTableViewController, NewsCellDelegate, CategoriesVie } } - func showActionSheetForPost(post: Post) { + func showActionSheetForPost(item: Item) { var titles = ["Share", "Open", "Open in Safari", "Cancel"] - let sheet = UIAlertController(title: post.title, message: nil, preferredStyle: UIAlertControllerStyle.ActionSheet) + let sheet = UIAlertController(title: item.title, message: nil, preferredStyle: UIAlertControllerStyle.ActionSheet) let handler = {(action: UIAlertAction?) -> () in self.tableView.setEditing(false, animated: true) if let _ = action { if (action!.title == titles[0]) { - Helper.showShareSheet(post, controller: self, barbutton: nil) + Helper.showShareSheet(item, controller: self, barbutton: nil) } else if (action!.title == titles[1]) { let webview = self.storyboard?.instantiateViewControllerWithIdentifier("WebviewController") as! WebviewController - webview.post = post + webview.item = item self.showDetailViewController(webview, sender: nil) } else if (action!.title == titles[2]) { - UIApplication.sharedApplication().openURL(post.url!) + UIApplication.sharedApplication().openURL(item.url!) } } } @@ -109,35 +111,54 @@ class NewsViewController: HNTableViewController, NewsCellDelegate, CategoriesVie self.presentViewController(sheet, animated: true, completion: nil) } + + override func defaultCellHeight() -> CGFloat { + return 120.0 + } + //MARK: TableView Management override func numberOfSectionsInTableView(tableView: UITableView) -> Int { return 1 } override func tableView(tableView: UITableView,numberOfRowsInSection section: Int) -> Int { - if (self.ids != nil) { - return self.ids.count - } - return 0 + return self.ids.count } override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { - return 120.0 + return self.cellHeight[indexPath.row] } override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier(NewsCellsId) as? NewsCell - cell!.postId = self.ids[indexPath.row] + cell!.index = indexPath.row + let item = self.cachedItems[indexPath.row] + if item.id != -1 { + cell!.item = item + } + else { + self.loadPost(indexPath) + } cell!.cellDelegate = self - return cell! } + private func loadPost(indexPath: NSIndexPath) { + let id = self.ids[indexPath.row] + Item.fetchPost(self.ids[indexPath.row]) { (item, error, local) -> Void in + if (item != nil && id == item.id) { + self.cellHeight[indexPath.row] = NewsCell.heightForText(item.title!, bounds: self.tableView.bounds) + self.cachedItems[indexPath.row] = item + self.tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .None) + } + } + } + override func shouldPerformSegueWithIdentifier(identifier: String, sender: AnyObject?) -> Bool { if #available(iOS 9, *) { if identifier == "toWebview" { - if let url = (sender as? NewsCell)?.post!.url { + if let url = (sender as? NewsCell)?.item!.url { presentViewController(SafariViewController(URL: url), animated: true, completion: nil) return false } @@ -150,7 +171,7 @@ class NewsViewController: HNTableViewController, NewsCellDelegate, CategoriesVie if (segue.identifier == "toWebview") { let destination = segue.destinationViewController as! WebviewController if let selectedRows = self.tableView.indexPathsForSelectedRows { - destination.post = self.post(selectedRows[0]) + destination.item = self.item(selectedRows[0]) } } } @@ -168,9 +189,9 @@ class NewsViewController: HNTableViewController, NewsCellDelegate, CategoriesVie let readingList = UITableViewRowAction(style: UITableViewRowActionStyle.Normal, title: "Read\nLater", handler: {(action: UITableViewRowAction, indexpath: NSIndexPath) -> Void in - if (Helper.addPostToReadingList(self.post(indexPath)!)) { + if (Helper.addPostToReadingList(self.item(indexPath)!)) { } - Preferences.sharedInstance.addToReadLater(self.post(indexPath)!) + Preferences.sharedInstance.addToReadLater(self.item(indexPath)!) let cell = self.tableView.cellForRowAtIndexPath(indexPath) as! NewsCell cell.readLaterIndicator.hidden = false self.tableView.setEditing(false, animated: true) @@ -180,14 +201,14 @@ class NewsViewController: HNTableViewController, NewsCellDelegate, CategoriesVie let more = UITableViewRowAction(style: UITableViewRowActionStyle.Normal, title: "More", handler: {(action: UITableViewRowAction, indexpath: NSIndexPath) -> Void in - self.showActionSheetForPost(self.post(indexPath)!) + self.showActionSheetForPost(self.item(indexPath)!) }) return [readingList, more] } //MARK: NewsCellDelegate - func newsCellDidSelectButton(cell: NewsCell, actionType: Int, post: Post) { + func newsCellDidSelectButton(cell: NewsCell, actionType: Int, item: Item) { let indexPath = self.tableView.indexPathForCell(cell) if let realIndexPath = indexPath { @@ -199,11 +220,11 @@ class NewsViewController: HNTableViewController, NewsCellDelegate, CategoriesVie } if (actionType == NewsCellActionType.Comment.rawValue) { let detailVC = self.storyboard?.instantiateViewControllerWithIdentifier("DetailViewController") as! DetailViewController - detailVC.post = post + detailVC.item = item self.showDetailViewController(detailVC, sender: self) } else if (actionType == NewsCellActionType.Username.rawValue) { - if let realUsername = post.username { + if let realUsername = item.username { let detailVC = self.storyboard?.instantiateViewControllerWithIdentifier("UserViewController") as! UserViewController detailVC.user = realUsername self.showDetailViewController(detailVC, sender: self) @@ -211,14 +232,10 @@ class NewsViewController: HNTableViewController, NewsCellDelegate, CategoriesVie } } - func newsCellPostDidLoad(cell: NewsCell) { - //let indexpath = self.tableView.indexPathForCell(cell) - //self.tableView.reloadRowsAtIndexPaths([indexpath!], withRowAnimation: UITableViewRowAnimation.Automatic) - } - //MARK: CategoriesDelegate func categoriesViewControllerDidSelecteFilter(controller: CategoriesViewController, filer: Fetcher.APIEndpoint, title: String) { self.filter = filer + self.ids = [] self.onPullToFresh() self.title = title } diff --git a/SwiftHN/ViewControllers/UserViewController.swift b/SwiftHN/ViewControllers/UserViewController.swift index a30ae3c..b952874 100644 --- a/SwiftHN/ViewControllers/UserViewController.swift +++ b/SwiftHN/ViewControllers/UserViewController.swift @@ -25,8 +25,8 @@ class UserViewController: NewsViewController { self.refreshing = true - Post.fetchPost(self.user) { (posts, error, local) -> Void in - self.ids = posts + Item.fetchPost(self.user) { (items, error, local) -> Void in + self.ids = items if (!local) { self.refreshing = false } diff --git a/SwiftHN/ViewControllers/WebviewController.swift b/SwiftHN/ViewControllers/WebviewController.swift index 723e81e..85a54c6 100644 --- a/SwiftHN/ViewControllers/WebviewController.swift +++ b/SwiftHN/ViewControllers/WebviewController.swift @@ -14,7 +14,7 @@ class WebviewController: UIViewController, UIWebViewDelegate { @IBOutlet var webView : UIWebView! = nil var activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.White) - var post: Post! + var item: Item! required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) @@ -24,8 +24,8 @@ class WebviewController: UIViewController, UIWebViewDelegate { super.viewDidLoad() self.webView.delegate = self - if let _ = self.post { - if let realUrl = self.post.url { + if let _ = self.item { + if let realUrl = self.item.url { self.webView.loadRequest(NSURLRequest(URL: realUrl)) } } @@ -45,7 +45,7 @@ class WebviewController: UIViewController, UIWebViewDelegate { } func onShareButton() { - Helper.showShareSheet(self.post, controller: self, barbutton: self.navigationItem.rightBarButtonItem) + Helper.showShareSheet(self.item, controller: self, barbutton: self.navigationItem.rightBarButtonItem) } func webViewDidStartLoad(webView: UIWebView) { diff --git a/SwiftHN/libs/submodules b/SwiftHN/libs/submodules index 3087a2b..9ab7f46 160000 --- a/SwiftHN/libs/submodules +++ b/SwiftHN/libs/submodules @@ -1 +1 @@ -Subproject commit 3087a2b810ba0792b83e8e4083c043c78d4d8cc8 +Subproject commit 9ab7f46678c30f80f5679bfc4bd820ce0067a474 diff --git a/SwiftHNShared/HNKit/HNTableViewController.swift b/SwiftHNShared/HNKit/HNTableViewController.swift index d4f2049..19cd501 100644 --- a/SwiftHNShared/HNKit/HNTableViewController.swift +++ b/SwiftHNShared/HNKit/HNTableViewController.swift @@ -7,6 +7,7 @@ // import UIKit +import HackerSwifter public class HNTableViewController: UITableViewController { @@ -23,16 +24,19 @@ public class HNTableViewController: UITableViewController { } } - public var datasource: NSArray! { + public var cellHeight: [CGFloat] = [] + public var cachedItems: [Item] = [] + + public var ids: [Int] = [] { didSet { + self.cellHeight = [CGFloat](count: self.ids.count, repeatedValue: self.defaultCellHeight()) + self.cachedItems = [Item](count: self.ids.count, repeatedValue: Item(id: -1)) self.tableView.reloadData() } } - public var ids: [Int]! { - didSet { - self.tableView.reloadData() - } + public func defaultCellHeight() -> CGFloat { + return 100.0 } public override func viewDidLoad() { diff --git a/SwiftHNToday/TodayViewController.swift b/SwiftHNToday/TodayViewController.swift index 26ae917..d1eef9c 100644 --- a/SwiftHNToday/TodayViewController.swift +++ b/SwiftHNToday/TodayViewController.swift @@ -18,7 +18,7 @@ class TodayViewController: UIViewController, NCWidgetProviding, UITableViewDeleg let topBottomWidgetInset: CGFloat = 10.0 var completionHandler: ((NCUpdateResult) -> Void)? - var posts: [Int] = [] { + var items: [Int] = [] { didSet { self.tableView.reloadData() self.preferredContentSize = CGSizeMake(0, self.tableView.contentSize.height) @@ -39,8 +39,8 @@ class TodayViewController: UIViewController, NCWidgetProviding, UITableViewDeleg self.tableView.backgroundColor = UIColor.clearColor() - Post.fetchPost(.Top) { (posts, error, local) -> Void in - self.posts = posts + Item.fetchPost(.Top) { (items, error, local) -> Void in + self.items = items self.completionHandler?(NCUpdateResult.NewData) } } @@ -80,7 +80,7 @@ class TodayViewController: UIViewController, NCWidgetProviding, UITableViewDeleg if self.expanded { return 7 } - return self.posts.count > 5 ? 5 : self.posts.count + return self.items.count > 5 ? 5 : self.items.count } func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { @@ -122,7 +122,7 @@ class TodayViewController: UIViewController, NCWidgetProviding, UITableViewDeleg func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = self.tableView.dequeueReusableCellWithIdentifier(todayCellId) as? TodayWidgetCell - let post = self.posts[indexPath.row] as Int + let post = self.items[indexPath.row] as Int cell!.postId = post return cell! } @@ -130,6 +130,6 @@ class TodayViewController: UIViewController, NCWidgetProviding, UITableViewDeleg func tableView(tableView: UITableView , didSelectRowAtIndexPath indexPath: NSIndexPath) { let cell: TodayWidgetCell = self.tableView.cellForRowAtIndexPath(indexPath) as! TodayWidgetCell - self.extensionContext!.openURL(cell.post!.url!, completionHandler: nil) + self.extensionContext!.openURL(cell.item!.url!, completionHandler: nil) } } diff --git a/SwiftHNToday/TodayWidgetCell.swift b/SwiftHNToday/TodayWidgetCell.swift index aaa170f..e5e3935 100644 --- a/SwiftHNToday/TodayWidgetCell.swift +++ b/SwiftHNToday/TodayWidgetCell.swift @@ -19,19 +19,19 @@ class TodayWidgetCell: UITableViewCell { @IBOutlet var postVoteLabel: RoundedLabel! @IBOutlet var subtitleWrapperView: UIView! - var post: Post? { + var item: Item? { didSet { - self.postTitleLabel.text = self.post!.title! - self.postVoteLabel.text = String(self.post!.score) - self.postSubtitleLabel.text = self.post!.domain! + " - " + NSDate(timeIntervalSince1970: self.post!.time).timeAgo + self.postTitleLabel.text = self.item!.title! + self.postVoteLabel.text = String(self.item!.score) + self.postSubtitleLabel.text = self.item!.domain! + " - " + NSDate(timeIntervalSince1970: self.item!.time).timeAgo } } var postId: Int? { didSet { self.postTitleLabel.text = "Loading" - Post.fetchPost(self.postId!) { (post, error, local) -> Void in - self.post = post + Item.fetchPost(self.postId!) { (item, error, local) -> Void in + self.item = item } } } From fbe8a11f3e33abb9a29ba77edaf3cf012689138c Mon Sep 17 00:00:00 2001 From: Thomas Ricouard Date: Mon, 28 Dec 2015 14:24:45 +0100 Subject: [PATCH 4/5] WIP: Mor functional --- SwiftHN/Cells/CommentsCell.swift | 52 +++++++-------- SwiftHN/Cells/NewsCell.swift | 64 +++++++++++-------- SwiftHN/Utils/Preferences.swift | 2 +- .../DetailViewController.swift | 42 ++++++------ .../ViewControllers/NewsViewController.swift | 5 +- SwiftHN/libs/submodules | 2 +- SwiftHNShared/Extension/NSDate+TimeAgo.swift | 4 +- 7 files changed, 94 insertions(+), 77 deletions(-) diff --git a/SwiftHN/Cells/CommentsCell.swift b/SwiftHN/Cells/CommentsCell.swift index 3547a3f..638ec01 100644 --- a/SwiftHN/Cells/CommentsCell.swift +++ b/SwiftHN/Cells/CommentsCell.swift @@ -19,38 +19,38 @@ let CommentCellBottomMargin: CGFloat = 16.0 class CommentsCell: UITableViewCell { + var index: Int = -1 + var comment: Item! { didSet { - var username = "" - if let _username = comment!.username { - username = _username + if comment == nil { + self.usernameLabel.text = "Loading..." + self.commentLabel.text = "" } - let date = " - " + NSDate(timeIntervalSince1970: comment!.time).timeAgo - - let usernameAttributed = NSAttributedString(string: username, - attributes: [NSFontAttributeName : UIFont.boldSystemFontOfSize(CommentCellFontSize), - NSForegroundColorAttributeName: UIColor.HNColor()]) - let dateAttribute = NSAttributedString(string: date, - attributes: [NSFontAttributeName: UIFont.systemFontOfSize(CommentCellFontSize), - NSForegroundColorAttributeName: UIColor.DateLighGrayColor()]) - let fullAttributed = NSMutableAttributedString(attributedString: usernameAttributed) - fullAttributed.appendAttributedString(dateAttribute) - - self.commentLabel.font = UIFont.systemFontOfSize(CommentCellFontSize) - - self.usernameLabel.attributedText = fullAttributed - self.commentLabel.text = comment!.text - } - } - - var commentId: Int? { - didSet { - Item.fetchPost(self.commentId!) { (item, error, local) -> Void in - self.comment = item + else { + var username = "" + if let _username = comment!.username { + username = _username + } + let date = " - " + NSDate(timeIntervalSince1970: comment!.time).timeAgo + + let usernameAttributed = NSAttributedString(string: username, + attributes: [NSFontAttributeName : UIFont.boldSystemFontOfSize(CommentCellFontSize), + NSForegroundColorAttributeName: UIColor.HNColor()]) + let dateAttribute = NSAttributedString(string: date, + attributes: [NSFontAttributeName: UIFont.systemFontOfSize(CommentCellFontSize), + NSForegroundColorAttributeName: UIColor.DateLighGrayColor()]) + let fullAttributed = NSMutableAttributedString(attributedString: usernameAttributed) + fullAttributed.appendAttributedString(dateAttribute) + + self.commentLabel.font = UIFont.systemFontOfSize(CommentCellFontSize) + + self.usernameLabel.attributedText = fullAttributed + self.commentLabel.text = comment!.text } } } - + var indentation: CGFloat { didSet { self.commentLeftMarginConstraint.constant = indentation diff --git a/SwiftHN/Cells/NewsCell.swift b/SwiftHN/Cells/NewsCell.swift index fc1faf1..76dc296 100644 --- a/SwiftHN/Cells/NewsCell.swift +++ b/SwiftHN/Cells/NewsCell.swift @@ -43,36 +43,43 @@ class NewsCell: UITableViewCell { var item: Item? { didSet { - - self.titleLabel.text = self.item!.title! - - if self.item!.time != 0 { - let time = self.item!.time - self.urlLabel.text = self.item!.domain! + " - " + NSDate(timeIntervalSince1970: NSTimeInterval(time)).timeAgo + if item == nil { + self.titleLabel.text = "Loding..." + self.urlLabel.text = "" + self.usernameLabel.labelText = "..." + self.voteLabel.labelText = "..." + self.commentsLabel.labelText = "..." } - - self.voteLabel.labelText = String(self.item!.score) + " votes" - self.commentsLabel.labelText = String(self.item!.commentsCount) + " comments" - self.usernameLabel.labelText = self.item!.username! - - - self.voteLabel.onButtonTouch = {(sender: UIButton) in - self.selectedAction(.Vote) + else { + self.titleLabel.text = self.item!.title! + + if self.item!.time != 0 { + let time = self.item!.time + self.urlLabel.text = self.item!.domain! + " - " + NSDate(timeIntervalSince1970: NSTimeInterval(time)).timeAgo + } + + self.voteLabel.labelText = String(self.item!.score) + " votes" + self.commentsLabel.labelText = String(self.item!.commentsCount) + " comments" + self.usernameLabel.labelText = self.item!.username! + + + self.voteLabel.onButtonTouch = {(sender: UIButton) in + self.selectedAction(.Vote) + } + + + self.commentsLabel.onButtonTouch = {(sender: UIButton) in + self.selectedAction(.Comment) + } + + self.usernameLabel.onButtonTouch = {(sender: UIButton) in + self.selectedAction(.Username) + } + + if self.readLaterIndicator != nil { + self.readLaterIndicator.hidden = !Preferences.sharedInstance.isInReadingList(String(self.item!.id)) + } } - - - self.commentsLabel.onButtonTouch = {(sender: UIButton) in - self.selectedAction(.Comment) - } - - self.usernameLabel.onButtonTouch = {(sender: UIButton) in - self.selectedAction(.Username) - } - - if self.readLaterIndicator != nil { - self.readLaterIndicator.hidden = !Preferences.sharedInstance.isInReadingList(String(self.item!.id)) - } - } } @@ -82,6 +89,7 @@ class NewsCell: UITableViewCell { override init(style: UITableViewCellStyle, reuseIdentifier: String!) { super.init(style: style, reuseIdentifier: reuseIdentifier) + } func selectedAction(action: NewsCellActionType) { diff --git a/SwiftHN/Utils/Preferences.swift b/SwiftHN/Utils/Preferences.swift index c956757..cfdcdd8 100644 --- a/SwiftHN/Utils/Preferences.swift +++ b/SwiftHN/Utils/Preferences.swift @@ -33,7 +33,7 @@ class Preferences { if (array == nil) { array = [] } - array.append(String(item)) + array.append(String(item.id)) self.pUserDefault.setObject(array, forKey: pReadLater) } diff --git a/SwiftHN/ViewControllers/DetailViewController.swift b/SwiftHN/ViewControllers/DetailViewController.swift index 008a5ff..226036f 100644 --- a/SwiftHN/ViewControllers/DetailViewController.swift +++ b/SwiftHN/ViewControllers/DetailViewController.swift @@ -14,8 +14,6 @@ class DetailViewController: HNTableViewController, NewsCellDelegate { var item: Item? - var cellHeightCache: [CGFloat] = [] - override func viewDidLoad() { super.viewDidLoad() @@ -39,20 +37,7 @@ class DetailViewController: HNTableViewController, NewsCellDelegate { }) } } - - func cacheHeight(comments: NSArray) { - /* - cellHeightCache = [] - for comment : AnyObject in comments { - if let realComment = comment as? Comment { - let height = CommentsCell.heightForText(realComment.text!, bounds: self.tableView.bounds, level: realComment.depth) - cellHeightCache.append(height) - } - } - */ - } - - + func setupBarButtonItems() { let shareItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Action, target: self, action: "onShareButton") self.navigationItem.rightBarButtonItem = shareItem @@ -84,6 +69,19 @@ class DetailViewController: HNTableViewController, NewsCellDelegate { return self.ids.count } + private func loadComment(indexPath: NSIndexPath) { + let id = self.ids[indexPath.row] + Item.fetchPost(self.ids[indexPath.row]) { (item, error, local) -> Void in + if (item != nil && id == item.id) { + if let text = item.text { + self.cellHeight[indexPath.row] = CommentsCell.heightForText(text, bounds: self.tableView.bounds, level:0) + } + self.cachedItems[indexPath.row] = item + self.tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .None) + } + } + } + override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { if (indexPath.section == 0) { let cell = tableView.dequeueReusableCellWithIdentifier(NewsCellsId) as? NewsCell @@ -93,8 +91,16 @@ class DetailViewController: HNTableViewController, NewsCellDelegate { } let cell = tableView.dequeueReusableCellWithIdentifier(CommentsCellId) as! CommentsCell! - let comment = self.ids[indexPath.row] - cell.commentId = comment + cell!.index = indexPath.row + cell!.comment = nil + let item = self.cachedItems[indexPath.row] + if item.id != -1 { + cell!.comment = item + } + else { + self.loadComment(indexPath) + } + return cell } diff --git a/SwiftHN/ViewControllers/NewsViewController.swift b/SwiftHN/ViewControllers/NewsViewController.swift index cf3c645..5512a4d 100644 --- a/SwiftHN/ViewControllers/NewsViewController.swift +++ b/SwiftHN/ViewControllers/NewsViewController.swift @@ -133,6 +133,7 @@ class NewsViewController: HNTableViewController, NewsCellDelegate, CategoriesVie override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier(NewsCellsId) as? NewsCell cell!.index = indexPath.row + cell!.item = nil let item = self.cachedItems[indexPath.row] if item.id != -1 { cell!.item = item @@ -148,7 +149,9 @@ class NewsViewController: HNTableViewController, NewsCellDelegate, CategoriesVie let id = self.ids[indexPath.row] Item.fetchPost(self.ids[indexPath.row]) { (item, error, local) -> Void in if (item != nil && id == item.id) { - self.cellHeight[indexPath.row] = NewsCell.heightForText(item.title!, bounds: self.tableView.bounds) + if let title = item.title { + self.cellHeight[indexPath.row] = NewsCell.heightForText(title, bounds: self.tableView.bounds) + } self.cachedItems[indexPath.row] = item self.tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .None) } diff --git a/SwiftHN/libs/submodules b/SwiftHN/libs/submodules index 9ab7f46..1a8921c 160000 --- a/SwiftHN/libs/submodules +++ b/SwiftHN/libs/submodules @@ -1 +1 @@ -Subproject commit 9ab7f46678c30f80f5679bfc4bd820ce0067a474 +Subproject commit 1a8921c685964ec4436f49d05d0f14aaddfee21e diff --git a/SwiftHNShared/Extension/NSDate+TimeAgo.swift b/SwiftHNShared/Extension/NSDate+TimeAgo.swift index 436733b..034f6d6 100644 --- a/SwiftHNShared/Extension/NSDate+TimeAgo.swift +++ b/SwiftHNShared/Extension/NSDate+TimeAgo.swift @@ -35,7 +35,7 @@ extension NSDate { if components.day < 2 { return "Yesterday" } else { - return String(format: "%@ days ago", arguments: [String(Double(components.day))]) + return String(format: "%@ days ago", arguments: [String(Int(components.day))]) } } @@ -59,7 +59,7 @@ extension NSDate { if components.second < 5 { return "Just now" } else { - return String(format: "%@ seconds ago", arguments: [String(Double(components.second))]) + return String(format: "%@ seconds ago", arguments: [String(Int(components.second))]) } } From 57965b128fb674b155f08a01a6d71c6eb1c27fc1 Mon Sep 17 00:00:00 2001 From: Thomas Ricouard Date: Mon, 28 Dec 2015 15:33:25 +0100 Subject: [PATCH 5/5] Fixes --- SwiftHN.xcodeproj/project.pbxproj | 2 ++ SwiftHN/Cells/CommentsCell.swift | 2 +- SwiftHN/ViewControllers/DetailViewController.swift | 3 +-- SwiftHN/libs/submodules | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/SwiftHN.xcodeproj/project.pbxproj b/SwiftHN.xcodeproj/project.pbxproj index e713308..9d1ee50 100644 --- a/SwiftHN.xcodeproj/project.pbxproj +++ b/SwiftHN.xcodeproj/project.pbxproj @@ -1329,6 +1329,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; EMBEDDED_CONTENT_CONTAINS_SWIFT = YES; + ENABLE_BITCODE = NO; INFOPLIST_FILE = SwiftHN/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; @@ -1351,6 +1352,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; EMBEDDED_CONTENT_CONTAINS_SWIFT = YES; + ENABLE_BITCODE = NO; GCC_OPTIMIZATION_LEVEL = s; INFOPLIST_FILE = SwiftHN/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; diff --git a/SwiftHN/Cells/CommentsCell.swift b/SwiftHN/Cells/CommentsCell.swift index 638ec01..4c0d300 100644 --- a/SwiftHN/Cells/CommentsCell.swift +++ b/SwiftHN/Cells/CommentsCell.swift @@ -21,7 +21,7 @@ class CommentsCell: UITableViewCell { var index: Int = -1 - var comment: Item! { + var comment: Item? { didSet { if comment == nil { self.usernameLabel.text = "Loading..." diff --git a/SwiftHN/ViewControllers/DetailViewController.swift b/SwiftHN/ViewControllers/DetailViewController.swift index 226036f..67d1352 100644 --- a/SwiftHN/ViewControllers/DetailViewController.swift +++ b/SwiftHN/ViewControllers/DetailViewController.swift @@ -53,8 +53,7 @@ class DetailViewController: HNTableViewController, NewsCellDelegate { if (indexPath.section == 0) { return NewsCell.heightForText((self.item?.title)!, bounds: self.tableView.bounds) } - return 100.0 - //return self.cellHeightCache[indexPath.row] as CGFloat + return self.cellHeight[indexPath.row] } override func numberOfSectionsInTableView(tableView: UITableView) -> Int { diff --git a/SwiftHN/libs/submodules b/SwiftHN/libs/submodules index 1a8921c..d651e16 160000 --- a/SwiftHN/libs/submodules +++ b/SwiftHN/libs/submodules @@ -1 +1 @@ -Subproject commit 1a8921c685964ec4436f49d05d0f14aaddfee21e +Subproject commit d651e16472a03f2255d8c7411916b94cf28a19b5