SwiftyComments 0.2.0

SwiftyComments 0.2.0

Stephane Sercu 维护。




  • Stéphane Sercu

SwiftyComments

License

基于 UITableViewDataSource 的组件,用于显示可展开/可折叠的评论层次。

HNExample ImgurExample RedditExample

安装

手动

只需将项目中的 SwiftyComments/Classes 文件夹中的 .swift 文件复制到您的项目中。

CocoaPod

将以下行添加到您的 Podfile 中

pod 'SwiftyComments', :git => 'https://github.com/tsucres/SwiftyComments.git'

使用

概述

基本上,你所要做的就是

  1. 导入 import SwiftyComments
  2. 定义你的评论视图(通常包含发布者名称、日期时间、评论内容等)。这个视图将是每个 CommentCellUITableViewCell 的子类)的主要子视图;
  3. 通过 CommentCell 类的可用属性来自定义表格视图的外观;
  4. CommentsViewController 提供你的模型。

细节

以下是关于之前步骤的更多详细信息

1) 构建你的 CommentCell

CommentCell 主要是显示你的评论和缩进的一个 UIView。这里有一个基本的实现

class YourCommentCell: CommentCell {
	
	override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
		super.init(style: style, reuseIdentifier: reuseIdentifier)
		
		// YourCommentView is a UIView aimed to contain all the info about a comment (poster's name, date, body, ...)
		self.commentViewContent = YourCommentView()
		
		// Customisation...
		// ...
	}
	required init?(coder aDecoder: NSCoder) {
		fatalError("init(coder:) has not been implemented")
	}
}
2) 自定义你的单元格

你可以通过 CommentCell 类的多个属性来自定义评论视图的周围环境(如缩进、边距)

	
	// Margin on top of a root comment
	self.rootCommentMarginColor = ...
	self.rootCommentMargin = ...
	// Margin on top of any non-root comment
	self.commentMarginColor = ...
	self.commentMargin = ...
	// Space on the left of any indented comment
	self.identationColor = ...
	// Vertical line between the indentation space and the comment
	self.indentationIndicatorColor = ...
	self.indentationIndicatorThickness = ...
	// Whether to continue the indentyation indicator on all the child comments or not
	self.extendIndentationIndicators = ...
	// thickness of the indentation offset per level
	self.indentationUnit = ...
3) 加载数据

CommentsViewController 类继承自 UITableViewController 并负责加载数据。你需要做的是将 allComments 属性填充为你的模型,并重写 tableView(_:cellForRowAt:) 方法

class YourCommentsViewController: CommentsViewController {
	private let commentCellId = "commentCellId"
	var allComments: [YourCommentModel] = [] // All the comments (nested, not in a linear format)
	
	override func viewDidLoad() {
		super.viewDidLoad()
		
		tableView.register(SimpleCommentCell.self, forCellReuseIdentifier: commentCellId)
		currentlyDisplayed = allComments // Assuming your models are loaded in allComments
    }
    
	override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> CommentCell {
		let commentCell = tableView.dequeueReusableCell(withIdentifier: commentCellId, for: indexPath) as! YourCommentCell
		let comment = currentlyDisplayed[indexPath.row] as! YourCommentModel
		commentCell.level = comment.level
		// commentCell.body = ...
		return commentCell
    }
}

注意 你的模型必须符合 AbstractComment 协议

public protocol AbstractComment: class {
    var replies: [AbstractComment]! { get set }
    var level: Int! { get set }
    weak var replyTo: AbstractComment? { get set }
}

默认情况下,当评论展开时,表格将滚动以便显示回复。你可以通过 makeExpandedCellsVisible 属性关闭此功能。

此外,可以将 fullyExpanded 属性设置为 true 以从完全展开的表格视图开始。

tableView的整体结构

以下图片展示了tableView的结构

schema_small

  • 1 表示整个 CommentCell
  • 2 是分配给cell的 commentViewContent 属性的 UIView
  • 3缩进空间,您可以通过 CommentCellindentationUnitindentationColor 属性进行个性化设置
  • 4 的颜色和粗细可以通过 CommentCellcommentMarginColorcommentMargin 属性进行个性化设置
  • 5 也可以通过 indentationIndicatorColorindentationIndicatorThickness 进行修改
  • 6 类似,可以通过 rootCommentMarginColorrootCommentMargin 进行设置

AttributedStrings

您可以使用具有 NSAttributedStringUITextView 在注释内容视图中轻松添加特殊样式(标题、链接、段落间距、粗体/斜体字体等)。

尽管如此,如果您的注释内容是HTML格式,您可能需要重新考虑使用 DocumentReadingOptionKey.documentType: NSAttributedString.DocumentType.html 选项的计划。即使这种方法非常简单直接,但它并不高效,并且加载字符串需要很长时间(在我的经验中,约为.15 - .2秒)。由于单元格的高度是基于其内容自动计算的,这种延迟会导致故障/延迟。

一个替代方案(如 HNCommentsViewController 示例所示)是自行解析HTML并手动添加属性来构建 NSAttributedString

这取决于您的评论格式的复杂性,可能更难实现,但效率高得多。

如果不信任我,请在 HNCommentsViewController.swift 中查看并取消加载注释的注释部分...

此示例使用 SwiftScanner 解析hackernews评论的HTML。请查看 HNCommentContentParser.swift 文件以了解更多有关如何构建 AttributedString 的详细信息。

CommentsViewDelegate

public protocol CommentsViewDelegate: class {
    func commentCellExpanded(atIndex index: Int)
    func commentCellFolded(atIndex index: Int)
}

您可以实现此协议,并正确设置 CommentsViewControllerdelegate 属性,以便在单元格展开/折叠时接收到通知。

例如,您可以使用此功能在折叠时最小化评论。查看 RedditCommentsViewController 的示例获取更多细节。

滑动隐藏

SwipeCellKit 被用于在每个评论单元格上添加 "滑动隐藏" 动作。

启用/禁用

您可以使用 CommentsViewControllerswipeToHide 属性来禁用此功能。

自定义

外观

通过 CommentsViewControllerswipeActionAppearance 属性,您可以自定义滑动操作的外观。这样就可以改变所有以下滑动操作属性:

open var swipeActionColor: UIColor
open var swipeActionHighlightedColor: UIColor

open var swipeActionText: String
open var swipeActionTextColor: UIColor
open var swipeActionHighlightedTextColor: UIColor
open var swipeActionTextFont: UIFont

open var swipeActionImage: UIImage
open var swipeActionHighlightedImage: UIImage

有关更多信息,请参阅 SwipeCellKit 的官方文档。

您可以通过(仔细地)重写以下方法进一步进行自定义:

public func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> [SwipeAction]?
添加操作

要添加操作,您必须重写 editActionsForRowAt 方法。

override public func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> [SwipeAction]? {
	// Retrieve the "collapseAction"
	var actions = super.tableView(tableView, editActionsForRowAt: indexPath, for: orientation)

	// Create you additional action(s) according to the documentation of SwipeCellKit
	let oneMoreAction = SwipeAction(...)
	actions.append(oneMoreAction)

	return actions
}

备注

相较于iOS 8中引入的默认UITableViewRowAction,更倾向于使用SwipeCellKit。主要原因在于UITableViewRowAction在处理单元格的调整大小动画(折叠时)方面表现不佳:随着单元格尺寸减小,UITableViewRowAction始终保持最初的大小并与其他单元格重叠。另一个原因是SwipeCellKit的更强大的自定义性。

示例

要运行示例项目,请克隆仓库,并从示例目录中运行pod install

本项目对CommentsViewController有四种不同的实现方法

  • SimpleCommentsViewController展示了基本实现;
  • ImgurCommentsViewController是Imgur iOS应用程序评论系统的复制品;
  • RedditCommentsViewController是Reddit iOS应用程序评论系统的复制品;
  • HNCommentsViewController展示了使用AttributedStrings的实现。

待办事项

  • 对tableView进行更多抽象
    • 移除init(style: UITableViewCellStyle, reuseIdentifier: String?)
    • 覆盖func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> CommentCell
  • iOS 11中添加/删除行动画有些奇怪..有解决方案吗?
  • 标记评论为展开/折叠,以便在展开评论时保持其回复的展开/折叠状态。目前,当一个折叠回等的评论被折叠后再次展开,其回复也会被展开。
  • 更好的文档/README

许可证

SwiftyComments遵从MIT许可证。更多详情请参阅LICENSE文件。