Ios 带超链接的标准UITableView节页脚视图

Ios 带超链接的标准UITableView节页脚视图,ios,iphone,uitableview,Ios,Iphone,Uitableview,我正在尝试实现一个带有超链接的UITableViewsection页脚视图。我希望它看起来像所有其他标准分组的UITableViewsection页脚视图,具有相同的度量、字体、颜色等,只是具有可单击的超链接。我希望尽可能避免硬编码任何布局值,包括高度。理想情况下,我希望避免外部依赖,例如ttattributelabel 编辑:超链接是带下划线的文本链接,而不是带下划线的URL,因此数据检测器不适用。我认为这很容易,但似乎我错了 获取标准字体和颜色: 如果我实例化自己的UITableViewH

我正在尝试实现一个带有超链接的
UITableView
section页脚视图。我希望它看起来像所有其他标准分组的
UITableView
section页脚视图,具有相同的度量、字体、颜色等,只是具有可单击的超链接。我希望尽可能避免硬编码任何布局值,包括高度。理想情况下,我希望避免外部依赖,例如
ttattributelabel


编辑:超链接是带下划线的文本链接,而不是带下划线的URL,因此数据检测器不适用。

我认为这很容易,但似乎我错了

获取标准字体和颜色:
  • 如果我实例化自己的UITableViewHeaderFooterView实例,则
    文本标签
    字体(在iOS 9上)与UITableView的标准节页脚视图字体(SF UI文本常规17与SF UI文本常规13)不匹配。默认NSAttributedString文本颜色也是黑色,与标准灰色不匹配

  • -[UITableView footerViewForSection:
    仅适用于由
    -tableView:ViewForFooterInstruction:
    提供的自定义页脚视图,否则返回零。获取标准页脚视图(确定标准字体和颜色值)的唯一方法是不提供自定义页脚视图。传递给
    -tableView:willDisplayFooterView:forSection:
    的视图可以转换为
    UITableViewHeaderFooterView
    并进行检查。这似乎是未记录的行为,字体属性来得太晚,无法用于计算页脚视图高度

确定页脚视图高度:
  • UITableView要求查看页脚高度(
    -tableView:heightForFooterInSection:
    ),然后再要求查看(
    -tableView:viewForFooterInSection:
    )。这意味着我需要实例化视图,以便在早期计算其高度,例如在
    -viewDidLoad
    时间。但是
    -[UITableViewHeaderFooterView sizeToFit]
    将高度计算为0。事实上,
    textlab
    的高度是在
    -tableView:willDisplayFooterView:forSection:
    之后才计算出来的,这可能是因为footer视图尚未添加到任何容器视图中

  • 如果我使用
    UITableView自动标注
    ,UITableView会根据标题计算页脚视图的高度(从
    -表视图:标题或页脚分类:
    或在故事板/xib中编码的等效值)。直到紧接着
    -tableView:willDisplayFooterView:forSection:
    之前,才会发生这种情况

实施超链接:
  • UITableViewHeaderFooterView提供文本标签,但UILabel不支持可点击链接,因此我需要向页脚视图添加UITextView。在
    -tableView:willDisplayFooterView:forSection:
    时间,UITableViewHeaderFooterView的
    文本标签仍然有零帧和零superview,因此我无法确定如何匹配其帧
可能的解决办法 这是我能想出的最短、最干净的解决方案。我仍然在硬编码字体和
textContainerInset
,这并不理想

class LinkTableViewHeaderFooterView: UITableViewHeaderFooterView {
    let textView = UITextView(frame: CGRectZero)

    private func _setUpTextView() {
        textView.editable = false
        textView.scrollEnabled = false
        textView.textContainerInset = UIEdgeInsetsMake(0.0, -5.0, 0.0, -5.0) // hard-coded
        textView.backgroundColor = UIColor.clearColor()
        self.addSubview(textView)
    }

    override init(reuseIdentifier: String?) {
        super.init(reuseIdentifier: reuseIdentifier)
        _setUpTextView()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        _setUpTextView()
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        self.textView.frame = self.textLabel!.frame // Match frame
    }

}

class MyViewController: UITableViewController {

    var footerAttributedText: NSAttributedString!

    override func viewDidLoad() {
        :

        self.tableView.registerClass(LinkTableViewHeaderFooterView.self, forHeaderFooterViewReuseIdentifier: "LinkTableViewHeaderFooterView")

        let html = "<a href=\"https://en.wikipedia.org/wiki/Lorem_ipsum\">Lorem ipsum</a> dolor sit amet, <a href=\"http://www.example.com/\">consectetur</a> adipisicing elit, sed do eiusmod <a href=\"http://stackoverflow.com\">tempor incididunt ut</a> labore et dolore magna aliqua."
        // HTML -> NSAttributedString
        let data = html.dataUsingEncoding(NSUTF8StringEncoding)!
        let options: [String: AnyObject] = [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: NSUTF8StringEncoding]
        self.footerAttributedText = try? NSAttributedString(data: data, options: options, documentAttributes: nil)
}

    override func tableView(tableView: UITableView, titleForFooterInSection section: Int) -> String? {
        if section == 1 {
            return self.footerAttributedText.string // UITableView will use this value to determine footer height
        }

        return nil
    }

    override func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
        if section == 1 {
            return tableView.dequeueReusableHeaderFooterViewWithIdentifier("LinkTableViewHeaderFooterView")
        }

        return nil
    }

    override func tableView(tableView: UITableView, willDisplayFooterView view: UIView, forSection section: Int) {
        if section == 1 {
            guard let footerView = view as? LinkTableViewHeaderFooterView else { return }

            let fontAttribute = UIFont.preferredFontForTextStyle(UIFontTextStyleFootnote) // hard-coded
            let textColorAttribute = (footerView.textLabel?.attributedText?.attribute(NSForegroundColorAttributeName, atIndex: 0, effectiveRange: nil))! // preserve font color
            let attributes = [NSFontAttributeName: fontAttribute, NSForegroundColorAttributeName: textColorAttribute]

            let mutableAttributedText = self.footerAttributedText.mutableCopy() as! NSMutableAttributedString
            mutableAttributedText.addAttributes(attributes, range: NSMakeRange(0, mutableAttributedText.length))
            footerView.textView.attributedText = mutableAttributedText
            footerView.textView.tintColor = tableView.tintColor

            footerView.textLabel?.attributedText = mutableAttributedText // UITableView will use this value to layout the footer view
            footerView.textLabel?.hidden = true
        }
    }

}
类链接TableViewHeaderFooterView:UITableViewHeaderFooterView{
让textView=UITextView(帧:CGRectZero)
私有函数_setUpTextView(){
textView.editable=false
textView.scrollEnabled=false
textView.textContainerSet=UIEdgeInsetsMake(0.0,-5.0,0.0,-5.0)//硬编码
textView.backgroundColor=UIColor.clearColor()
self.addSubview(textView)
}
重写init(reuseIdentifier:String?){
super.init(reuseIdentifier:reuseIdentifier)
_setUpTextView()
}
必需的初始化?(编码器aDecoder:NSCoder){
super.init(编码者:aDecoder)
_setUpTextView()
}
覆盖func布局子视图(){
super.layoutSubviews()
self.textView.frame=self.textLabel!.frame//匹配frame
}
}
类MyViewController:UITableViewController{
var footerAttributedText:NSAttributedString!
重写func viewDidLoad(){
:
self.tableView.registerClass(LinkTableViewHeaderFooterView.self,forHeaderFooterViewReuseIdentifier:“LinkTableViewHeaderFooterView”)
让html=“多洛尔坐在阿梅特,告别精英,为我们的劳动和大事业奋斗。”
//HTML->NSAttribute字符串
让data=html.dataUsingEncoding(NSUTF8StringEncoding)!
let选项:[String:AnyObject]=[NSDocumentTypeDocumentAttribute:NSHTMLTextDocumentType,NSCharacterEncodingDocumentAttribute:NSUTF8StringEncoding]
self.footerAttributedText=try?NSAttributedString(数据:数据,选项:选项,文档属性:nil)
}
重写func tableView(tableView:UITableView,titleForFooterInstruction节:Int)->String{
如果节==1{
return self.footerAttributedText.string//UITableView将使用此值确定页脚高度
}
归零
}
重写func tableView(tableView:UITableView,ViewForFooterInstruction节:Int)->UIView{
如果节==1{
返回tableView.dequeueReusableHeaderFooterViewWithIdentifier(“LinkTableViewHeaderFooterView”)
}
归零
}
重写func tableView(tableView:UITableView,willDisplayFooterView:UIView,forSection节:Int){
如果节==1{
guard let footerView=查看为?LinkTableViewHeaderFooterView else{return}
让fontAttribute=UIFont.preferredFontForTextStyle(UIFontTextStyleFootnote)//硬编码
让textColorAttribute=(footerView.textLabel?.AttributeText?.attribute(NSForegroundColorAttributeName,atIndex:0,effectiveRange:nil))!//保留字体颜色
let attributes=[NSFontAttributeName:fontAttribute,NSForegroundColorAttributeName:textColorAttrib