IBEnum.swift 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. //
  2. // Created by jason akakpo on 27/06/16.
  3. // Copyright © 2016 IBAnimatable. All rights reserved.
  4. //
  5. import Foundation
  6. /**
  7. A protocol provides extension method for converting `String` into `enum`.
  8. Because `@IBInspectable` property can not support `enum` directly. To provide both `enum` API in code and `@IBInspectable` supported type `String` in Interface Builder, we use `IBEnum` to bridge Swift `enum` and `String`
  9. */
  10. public protocol IBEnum {
  11. /**
  12. Initializes a swift `enum` with provided optional string
  13. - Parameter string: The optional string to be converted into `enum`.
  14. */
  15. init?(string: String?)
  16. }
  17. public extension IBEnum {
  18. /**
  19. Helper function that returns a tuple containing the name and params from a string `string`
  20. - Parameter from string: The string to be converted into `enum`.
  21. - Discussion: the string format is like "enumName(param1,param2,param3)"
  22. - Returns: A tuple containing the name and an array of parameter string
  23. */
  24. static func extractNameAndParams(from string: String) -> (name: String, params: [String]) {
  25. let tokens = string.lowercased().components(separatedBy: CharacterSet(charactersIn: "()")).filter { !$0.isEmpty }
  26. let name = tokens.first ?? ""
  27. let paramsString = tokens.count >= 2 ? tokens[1] : ""
  28. let params = paramsString.components(separatedBy: ",").filter { !$0.isEmpty }.map { $0.trimmingCharacters(in: .whitespaces) }
  29. return (name: name, params: params)
  30. }
  31. }
  32. extension IBEnum {
  33. init(string: String?, default defaultValue: Self) {
  34. self = Self(string: string) ?? defaultValue
  35. }
  36. }
  37. /// IBEnum provide default initializer for RawRepresentable Enum
  38. #if swift(>=4.2)
  39. public extension IBEnum where Self: RawRepresentable & CaseIterable {
  40. init?(string: String?) {
  41. if let item = getCase(for: string, from: iterateEnum(from: Self.self)) {
  42. self = item
  43. } else {
  44. return nil
  45. }
  46. }
  47. }
  48. #else
  49. public extension IBEnum where Self: RawRepresentable & Hashable {
  50. init?(string: String?) {
  51. if let item = getCase(for: string, from: iterateEnum(from: Self.self)) {
  52. self = item
  53. } else {
  54. return nil
  55. }
  56. }
  57. }
  58. #endif
  59. private func getCase<T: IBEnum & RawRepresentable>(for string: String?, from iterator: AnyIterator<T>) -> T? {
  60. let lowerString = string?.lowercased()
  61. for item in iterator {
  62. if String(describing: item.rawValue).lowercased() == lowerString {
  63. return item
  64. }
  65. }
  66. return nil
  67. }