Swift - 自定义 SectionIndexTitles 在 Tableview 中不起作用

Posted

技术标签:

【中文标题】Swift - 自定义 SectionIndexTitles 在 Tableview 中不起作用【英文标题】:Swift - Custom SectionIndexTitles not working in Tableview 【发布时间】:2016-01-01 21:31:00 【问题描述】:

我有一个 UISplitViewController,我用 UIViewController 替换了 UITableView。这个 ViewController 包含一个 UITableView 和一个 UIView。 UIView 包含我的自定义 SectionIndexTitles UIControl,用于滚动到右侧部分。

我的自定义 SectionIndexTitles UIControl 在带有 UICollectionView 的 ViewController 中完美运行,但不知何故它在前面提到的配置中不起作用。我该如何解决这个问题?

应用程序编译并且不会崩溃。当我擦洗 UIControl 时,不会调用 indexViewValueChanged() 函数。我已经使用 View Debugger 检查了 View 层次结构,但它位于 TableView 之上。我还尝试添加一个手势识别器,它确实有效。最后我尝试设置 zPosition,但这没有任何效果。

Github example

视图控制器

import UIKit

class ViewController: UIViewController 

    @IBOutlet weak var tableView: UITableView!
    @IBOutlet weak var indexTitlesContainer: UIView!

    /* type to represent table items
    `section` stores a `UITableView` section */
    class User: NSObject 
        let name: String
        var section: Int?

        init(name: String) 
            self.name = name
        
    

    // custom type to represent table sections
    class Section 
        var users: [User] = []

        func addUser(user: User) 
            self.users.append(user)
        
    

    // raw user data
    let names = [
        "Clementine",
        "Tim",
        "Bessie",
        "Yolande",
        "Tynisha",
        "Ellyn",
        "Trudy",
        "Fredrick",
        "Letisha",
        "Ariel",
        "Bong",
        "Jacinto",
        "Dorinda",
        "Aiko",
        "Loma",
        "Augustina",
        "Margarita",
        "Jesenia",
        "Kellee",
        "Annis",
        "Charlena"
    ]

    // `UIKit` convenience class for sectioning a table
    let collation = UILocalizedIndexedCollation.currentCollation()


    // table sections
    var sections: [Section] 
        // return if already initialized
        if self._sections != nil 
            return self._sections!
        

        // create users from the name list
        let users: [User] = names.map  name in
            let user = User(name: name)
            user.section = self.collation.sectionForObject(user, collationStringSelector: "name")
            return user
        

        // create empty sections
        var sections = [Section]()
        for i in 0..<self.collation.sectionIndexTitles.count 
            sections.append(Section())
        

        // put each user in a section
        for user in users 
            sections[user.section!].addUser(user)
        

        // sort each section
        for section in sections 
            section.users = self.collation.sortedArrayFromArray(section.users, collationStringSelector: "name") as! [User]
        

        self._sections = sections

        return self._sections!

    
    var _sections: [Section]?

    var indexTitles: IndexTitles!

    override func viewDidLoad() 
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        indexTitles = IndexTitles(frame: CGRectZero, indexTitles: collation.sectionIndexTitles)

        indexTitles.addTarget(self, action: "indexViewValueChanged:", forControlEvents: .ValueChanged)
        indexTitlesContainer.addSubview(indexTitles)

    

    func indexViewValueChanged(sender: IndexTitles) 
        print("perform function")
        var index = sender.index

        if self.sections[index].users.count == 0 

            var shouldPerform = true

            for var i = index as Int; i < self.sections[index].users.count; i++ 
                if shouldPerform == true 
                    if self.sections[index].users.count != 0 
                        shouldPerform = false
                        index = i
                    
                
            

            for var i = index as Int; i > 0; i-- 
                if shouldPerform == true 
                    if self.sections[index].users.count != 0 
                        shouldPerform = false
                        index = i
                    
                
            
        

        let path = NSIndexPath(forRow: 0, inSection: index)
        tableView.scrollToRowAtIndexPath(path, atScrollPosition: .Top, animated: false)

        let scrollPosition = tableView.contentOffset.y
        let collectionViewHeight = (tableView.contentSize.height - tableView.bounds.size.height) + 54

        if scrollPosition != collectionViewHeight 
            tableView.contentOffset = CGPoint(x: tableView.contentOffset.x, y: tableView.contentOffset.y - 22.0)
        

    

    override func viewDidLayoutSubviews() 
        let height = CGFloat(collation.sectionIndexTitles.count * 18)
        let y = (indexTitlesContainer.bounds.height - height) / 3
        indexTitles.frame = CGRectMake(0, y, indexTitlesContainer.bounds.width, height)

    

    override func didReceiveMemoryWarning() 
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    




extension ViewController:UITableViewDataSource 
    func numberOfSectionsInTableView(tableView: UITableView) -> Int 
        return self.sections.count
    

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return self.sections[section].users.count
    

    func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? 
        return collation.sectionIndexTitles[section]
    

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 
        let user = self.sections[indexPath.section].users[indexPath.row]

        let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
        cell.textLabel!.text = user.name
        cell.backgroundColor = UIColor.clearColor()
        return cell
    

自定义 UIControl

import UIKit

class IndexTitles: UIControl,UIGestureRecognizerDelegate 

    var indexTitles:NSArray!
    var visualEffect: UIVisualEffectView!
    var index:Int!

    func translate(touch:CGFloat) 
        let selectedIndex = Int(touch / 18)
        let indexCount = indexTitles.count - 1

        if selectedIndex < 0 
            index = 0
        
        else if selectedIndex > indexCount 
            index = indexCount
        
        else 
            index = selectedIndex
        

        sendActionsForControlEvents(.ValueChanged)
    

    //Sets the right index when the label is selected.
    override func beginTrackingWithTouch(touch: UITouch, withEvent event: UIEvent?) -> Bool 
        translate(touch.locationInView(self).y)
        return true
    

    override func continueTrackingWithTouch(touch: UITouch, withEvent event: UIEvent?) -> Bool 
        translate(touch.locationInView(self).y)
        return true
    

    //Setup for when the view is being initialized.
    init(frame: CGRect, indexTitles:NSArray) 
        super.init(frame: frame)
        self.indexTitles = indexTitles

        let multiplier = 18

        visualEffect = UIVisualEffectView(frame: CGRectMake(0, 0, 18, CGFloat(multiplier * indexTitles.count)))
        visualEffect.effect = UIVibrancyEffect(forBlurEffect: UIBlurEffect(style: .ExtraLight))
        self.addSubview(visualEffect)

        for var i = 0; i < indexTitles.count; i++ 
            let label = UILabel(frame: CGRectMake(0, CGFloat(multiplier * i) , 20 , 18))
            label.font = UIFont.systemFontOfSize(12, weight: UIFontWeightSemibold)
            label.numberOfLines = 0
            label.textAlignment = .Center
            label.text = indexTitles[i] as? String
            visualEffect.contentView.addSubview(label)
        

    

    required init?(coder aDecoder: NSCoder) 
        super.init(coder: aDecoder)
    



【问题讨论】:

你说不行。以什么方式不起作用?请澄清实际问题是什么。 @rmaddy UITableView 可以创建一个scrubber 来滚动到右侧部分。我不喜欢它的外观,所以我自己做了。洗涤器适用于 CollectionViews,但不适用于此配置。 我知道。你说过“它不起作用”。但这非常模糊。它编译吗?它会崩溃吗?它是否以某种意想不到的方式起作用?你做了什么调试? @rmaddy 该应用程序编译并且不会崩溃。当我擦洗 indexViewValueChanged() 函数时不会被调用。我已经使用 View Debugger 检查了 View 层次结构,但它位于 TableView 之上。我还尝试添加一个手势识别器,它确实有效。最后我尝试设置 zPosition,但这没有任何效果。 @rmaddy 嗨,我好像忘记添加 Github 链接了。我很抱歉造成混乱。 【参考方案1】:

在 UIControl 中,子视图 UserInteractionEnabled 必须设置为 false

【讨论】:

以上是关于Swift - 自定义 SectionIndexTitles 在 Tableview 中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

swift使用AVFoundation实现自定义相机

来自自定义类的 Swift addChild

swift Swift可解码多个自定义日期

swift Swift - CloudKit - 创建自定义区域

swift Swift中的自定义地图

SWIFT:从自定义单元格中的 UIswitch 展开/折叠自定义单元格