iOS开发:如何提取CGFloat首位数字并转换为CGFloat类型?
解决CGFloat提取首位数字并应用于UICollectionView列数动态调整的问题
问题根源分析
你的代码之所以失败,核心问题有两个:
- 可选值处理失误:
widthInStringFormat.first返回的是Optional<Character>,直接用String(describing: firstCharacter)会生成类似Optional("3")的字符串——这个内容包含非数字的Optional(和),自然无法转成有效的CGFloat。 - 类型转换错误:尝试
(firstCharacter as NSString).floatValue是完全错误的,因为Character类型不能直接强转为NSString。
两种可行的解决方案
方案1:字符串处理法(直观易理解)
先将CGFloat转为纯数字字符串,安全提取首位数字字符后再转回CGFloat:
let width: CGFloat = 375.0 // 转为不带小数的字符串(屏幕宽度是整数,所以可以这么处理) let widthStr = String(Int(width)) // 安全提取首位字符并确认是数字 guard let firstChar = widthStr.first, firstChar.isNumber else { fatalError("Invalid screen width value") } // 转成CGFloat guard let firstDigit = CGFloat(String(firstChar)) else { fatalError("Failed to convert digit to CGFloat") } print(firstDigit) // 输出3.0
方案2:数学计算法(更高效,无需字符串转换)
通过数值运算直接提取首位数字,避免字符串转换的开销:
func getFirstDigit(from value: CGFloat) -> CGFloat { var num = value // 确保数值为正(屏幕宽度不会为负,此步可省略,但让方法更通用) num = abs(num) // 不断除以10,直到数值小于10 while num >= 10 { num /= 10 } // 取整数部分得到首位数字 return floor(num) } // 测试示例 print(getFirstDigit(from: 375.0)) // 3.0 print(getFirstDigit(from: 637.0)) // 6.0 print(getFirstDigit(from: 995.0)) // 9.0
结合你的UICollectionView场景优化
根据你动态调整列数的需求,单纯依赖首位数字可能会有例外(比如1000宽度的首位是1,但你想显示10列),用区间判断会更精准:
func columnCount(for screenWidth: CGFloat) -> Int { switch screenWidth { case 0..<400: return 3 case 400..<700: return 6 case 700..<1000: return 9 default: return 10 // 1000及以上宽度显示10列 } } // 计算单元格尺寸 let screenWidth = UIScreen.main.bounds.width let columns = columnCount(for: screenWidth) let cellWidth = screenWidth / CGFloat(columns) let cellSize = CGSize(width: cellWidth, height: cellWidth) // 正方形单元格示例
这样既满足了屏幕越大列数越多的需求,又避免了极端数值的逻辑漏洞。
内容的提问来源于stack exchange,提问作者Ibrahim Azhar Armar
相关产品推荐
相关产品推荐

