【问题标题】:How to make IndexPath rawRepresentable?如何使 IndexPath rawRepresentable?
【发布时间】:2019-06-13 12:14:40
【问题描述】:

我正在尝试重构代码并创建一个枚举类来保存表格视图单元格的 indexPath。

我想让代码这样工作:

enum TableViewCell: IndexPath {
     case shopImageView = [0,0]
     case selectShopImageButton = [0,1]
}

但是编译器说 indexPath 不是 rawRepresentable:

“TableViewCell”声明了原始类型“IndexPath”,但不符合 RawRepresentable 且无法合成一致性

枚举大小写的原始值必须是文字

如何使 indexPath rawRepresentable?代码目前是这样工作的,我想改进它。

enum TableViewCell {
    case shopImageView
    case selectShopImageButton
    case shopNameLocal
    case shopNameEN
    case addressLocal
    case addressEN
    case selectAddressButton
    case openingHours
    case datePickers
    case phone
    case email
    case uploadShopFormButton
    
    var indexPath: IndexPath {
        switch self {
        case .shopImageView:         return [0,0]
        case .selectShopImageButton: return [0,1]
        case .shopNameLocal:         return [0,2]
        case .shopNameEN:            return [0,3]
        case .addressLocal:          return [0,4]
        case .addressEN:             return [0,5]
        case .selectAddressButton:   return [0,6]
        case .openingHours:          return [0,7]
        case .datePickers:           return [0,8]
        case .phone:                 return [0,9]
        case .email:                 return [0,10]
        case .uploadShopFormButton:  return [0,11]
        }
    }
}

【问题讨论】:

    标签: swift xcode indexpath


    【解决方案1】:

    使用硬编码TableViewIndexPath 的另一种方法是使用具有静态属性的enum。这样做的好处是,如果您在各种TableView 委托方法中引用了IndexPath,并且您需要更改IndexPath 引用,那么您只需在枚举中更改一次即可。

     private enum TableIndex {
        // Section 0: Information
        static let information =        IndexPath(row: 0, section: 0)
        // Section 1: Preferences
        static let notifications =      IndexPath(row: 0, section: 1)
        static let units =              IndexPath(row: 1, section: 1)
        static let hapticFeedback =     IndexPath(row: 2, section: 1)
        // Section 2: Links
        static let leaveReview =        IndexPath(row: 0, section: 2)
        static let support =            IndexPath(row: 1, section: 2)
        static let privacyPolicy =      IndexPath(row: 2, section: 2)
        static let disclaimer =         IndexPath(row: 3, section: 2)
    }
    

    然后您可以像这样引用它们:

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        switch indexPath {
        case TableIndex.information:
            // do something
        case TableIndex.notifications:
            // do something
        case TableIndex.units:
            // do something
    
            // etc
    
        default:
            break
        }
    }
    

    【讨论】:

      【解决方案2】:

      还有其他方法,但不一定更好,反正你可以把代码剪成这样。

      enum TableViewCell: Int  {
          case shopImageView = 0
          case selectShopImageButton = 1
          case shopNameLocal = 2
          case shopNameEN = 3
          case addressLocal
          case addressEN
          case selectAddressButton
          case openingHours
          case datePickers
          case phone
          case email
          case uploadShopFormButton
          
          var indexPath: IndexPath {
              return [0, self.rawValue]
          }
      }
      

      另外请记住,这还取决于您如何使用它们,例如您在何处以及如何传递参数。

      其中一种方式。

      extension IndexPath {
           init(using type: TableViewCell) {
              self.init(row: type.rawValue, section: 0)
          }
      }
      
      let indexPath = IndexPath(using: .shopNameEN)
      

      【讨论】:

        【解决方案3】:
        extension IndexPath : RawRepresentable {
            public init?(rawValue: (Int, Int)) {
                self.init(row: rawValue.0, section: rawValue.1)
            }
            public var rawValue: (Int, Int) {
                (self.row, self.section)
            }
        }
        
        // We can't use array literal for raw value of an enum, but we can use `String` literal instead.
        extension IndexPath: ExpressibleByStringLiteral {
            public init(stringLiteral: StringLiteralType) {
                let a = stringLiteral.split(separator: ",")
                if let row = Int(a[0]), let section = Int(a[1]) {
                     self.init(row: row, section: section)
                } else {
                    self.init(row: 0, section: 0)
                }
            }
        }
        // We can use array literals to initialize `IndexPath` but not to define an enum case.
        enum TableViewCell: IndexPath {
             case shopImageView = "0,0" // `String` literal
             case selectShopImageButton = "0,1" // `String` literal
        }
        
        print(TableViewCell.selectShopImageButton.rawValue)
        

        【讨论】:

        • 这似乎无法修复问题中的编译器错误。 IndexPath 可以用作具有此扩展名的枚举的原始值吗?
        • 是的,但是原始值也必须可以通过String 或数字来表达。我已经更新了答案。在操场上试试吧,@pkamb。
        猜你喜欢
        • 2018-12-19
        • 2012-07-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多