文章目录
  1. 1. 各种姿势的@objc @objcMembers
    1. 1.1. @objc
    2. 1.2. @objcMembers
  2. 2. swift3遗留的tableview delegate坑
  3. 3. 扫描功能没反应了
  4. 4. ipad上自定义UIBarButtonItem显示位置异常
  5. 5. UITableView 顶部莫名留白

ps: 时隔一年差一个月,xcode9也出来了,swift4也升级了。犹记得上次swift3代码升级的惊悚场景,这次心中默默打了个底,一定不能手贱,一定要在xcode9.1出来我再升级。然而终究抵不住心中的好奇升级了,升级,升级了……幸好,幸好,相比xcode8,xcode9真是良心了。犹记得xcode8.0出来我是等了一个月xcode8.1出来我才能发版的,等的感觉要被公司辞退了T.T。

忆苦思甜过后,细数下代码升级中遇到的坑吧。

各种姿势的@objc @objcMembers

@objc

swift4里面所有的#selector(action) action方法都要加上@objc标记,资料说是为了兼容object-c代码。代码里面#selector的普及率还是相当高的,一个个改的手残。

@objcMembers

swift4里面NSObject的取值方法value(forkey)方法会造成运行时崩溃,有很多对象copy用了反射的免不得都会崩溃。然而编译器不会提示你代码错了。这里简单点处理可以给class对象添加@objcMembers标记, 也可以给属性添加@objc dynamic,realm就这是这么做的,当然所有realm数据库对象也得要改造下

@objcMembers
class StockDetailItem:NSObject {
    @objc dynamic var title = ""
    @objc dynamic var quantity = 0.0
    var actualNum = 0.0
    var fulllessNum = 0.0

    override init() {
        super.init()
    }

}

let item = StockDetailItem()
item.title = "haha"
item.value(forKey: "title")
item.value(forKey: "quantity")

这个代码修改也挺多,为了对象copy简便,自己写了个反射方法

swift3遗留的tableview delegate坑

在swift3里面大部分代理函数名称都简化了,比如

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell

原来是

func tableView(_ tableView: UITableView, cellForRowAtIndexPath indexPath: IndexPath) -> UITableViewCell

问题是不是所有的代理方法都改造,还落了几个 didselect 和canedit 这几个方法还是老样子,swift4里面全简化了。然而也没有警告或者错误提示。

扫描功能没反应了

切了swift4之后扫码全部失效了。一脸茫然,代码也没有任何错误提示。幸好stackoverflow上的有个解答,原来是代理方法名改了。

func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!)

改成了

func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection)

ipad上自定义UIBarButtonItem显示位置异常

一般这种显示异常的按钮都是自定义的customview。使用正常的UIBarButtonItem是没问题的.

如果确定要使用CustomView,需要专门设置view的intrinsicContentSize, 也就是设置大小即可。
参考代码如下

  • intrinsicContentSize是只读属性,需要继承后重写

    class CommonNavigationView: UIView {
    
        init(size: CGSize) {
            super.init(frame: CGRect(origin: CGPoint.zero, size: size))
            self.overrideSize = size
        }
    
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    
        lazy var overrideSize = CGSize.zero
    
        override var intrinsicContentSize: CGSize {
            get {
                return overrideSize
            }
        }
    }
    
  • 放上个UIBarButton的扩展,这里使用Cartography做约束

    import Cartography
    
    extension UIBarButtonItem {
        enum Style {
            case left
            case right
        }
    
        convenience init(style: Style, customView: UIView, target:Any, action: Selector) {
            let backView = CommonNavigationView(size: CGSize(width: 44, height: 44))
            backView.addSubview(customView)
            let gesturer = UITapGestureRecognizer(target: target, action: action)
            backView.addGestureRecognizer(gesturer)
            constrain(customView) {
                imgv in
                if style == .left {
                    imgv.left == imgv.superview!.left
                } else {
                    imgv.right == imgv.superview!.right
                }
                imgv.centerY == imgv.superview!.centerY
                imgv.width == 25
                imgv.height == 25
            }
            self.init(customView: backView)
        }
    
        convenience init(style: Style, img: UIImage, target:Any, action: Selector) {
            let backView = CommonNavigationView(size: CGSize(width: 44, height: 44))
            let imgView = UIImageView(image: img)
            backView.addSubview(imgView)
            let gesturer = UITapGestureRecognizer(target: target, action: action)
            backView.addGestureRecognizer(gesturer)
            constrain(imgView) {
                imgv in
                if style == .left {
                    imgv.left == imgv.superview!.left
                } else {
                    imgv.right == imgv.superview!.right
                }
                imgv.centerY == imgv.superview!.centerY
                imgv.width == 25
                imgv.height == 25
            }
            self.init(customView: backView)
        }
    }
    

UITableView 顶部莫名留白

网上还是挺多解释的,然而基本都不适用,研究了好久,关闭行高估算, 设置头部高度。两者缺一不可

tableView.estimatedRowHeight = 0
tableView.estimatedSectionHeaderHeight = 0
tableView.estimatedSectionFooterHeight = 0

  func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return 0.1
}

就先这样吧,祝各位升级愉快!

文章目录
  1. 1. 各种姿势的@objc @objcMembers
    1. 1.1. @objc
    2. 1.2. @objcMembers
  2. 2. swift3遗留的tableview delegate坑
  3. 3. 扫描功能没反应了
  4. 4. ipad上自定义UIBarButtonItem显示位置异常
  5. 5. UITableView 顶部莫名留白