15.Swift3.0版爱鲜蜂

前言:在学习Swift的过程中,在网上找到一个swift版的爱鲜蜂工程(http://www.jianshu.com/p/879f58fe3542#),十分感谢大神慷慨的分享。但是这个项目是Swift2.0版的,无法正常运行,花了一天的时间将这个项目改成3.0版可以正常使用的项目。其中各种坑。。。。但是还好最后终于可以正常使用了。

下面来介绍一下在2.0转到3.0的过程中,遇到的各种bug。
标注:下面会将改好的工程传到github上面,仅供学习,不做他用。
修改后的版本的github地址,请使用Xcode 8.0打开,9打开会一直提示你升级swift4,而且一些xib支持也会有点问题。
https://github.com/yaoyao66/-swift3.0.git

1.首先是最坑的一个,在解析JSON数据的时候,遍历模型字典返回数据为空?
  • 最后发现判断一个可选择类型的对象是数组还是字典的方法出错了,在Swift2.0中使用
 let type = "\(value.self?.classForCoder)"  //获取当前对象的类型

但是这个方法在swift3.0中这个返回的值不是 NSDictionary或者 NSArray 字符串,所以我将这部分直接改成

 if value is NSDictionary  //判断这个可选类型对象的类型是否是NSDictionary
 else if value is NSArray
2.Swift编译时报错:Command failed due to signal: Segmentation fault: 11
这个我首先用的是Xcode Beta9版的,你只要选择Xcode8版本的就可以了。
3.Xcode8版本的模拟器不见了?
应该是你打开了多个Xcode,将所有的Xcode和模拟器全部关掉,重新打开就可以了
4. 方法发生了变化
let p1 = transitionLayer.position;
let p3 = CGPoint(x: view.width - 40, y: self.view.layer.bounds.size.height - 40);
        
let positionAnimation = CAKeyframeAnimation(keyPath: "position")
let path = CGMutablePath();
        
//  CGPathMoveToPoint(path, nil, p1.x, p1.y);
//  CGPathAddCurveToPoint(path, nil, p1.x, p1.y - 30, p3.x, p1.y 
- 30, p3.x, p3.y);
替换为
path.move(to: CGPoint(x:p1.x,y:p1.y));
path.addCurve(to: CGPoint(x:p3.x,y:p3.y), control1: CGPoint(x:p1.x,y:p1.y - 30), control2: CGPoint(x:p3.x,y:p1.y - 30));

positionAnimation.path = path;
5.override func animationDidStop(_ anim: CAAnimation, finished flag: Bool) 报下面的错误 Method does not override any method from its superclass

这是因为animationDidStop是CAAnimationDelegate里面的方法,所以在class加上CAAnimationDelegate代理,然后去掉override关键字就好了

6.sd_setImage(with:placeholderImage:completed:)’ 报下面的错误 Ambiguous use of 我查了一下资料,好像是有sd_setImage有2个方法太相近了,所以才会出现这个错误

代码修正为

backImageView.sd_setImage(with:URL(string: imageName!),placeholderImage: UIImage(named: placeholderImageName!),options:SDWebImageOptions()) { (image, error,_ ,_ ) in

7. Swift3.0中采用下面的方法来判断代理是否实现
 if (delegate.customClassMapping != nil)
例子
swift2.0
if tmpSelf!.delegate != nil && ((tmpSelf!.delegate?.responds(to: #selector(HomeTableHeadViewDelegate.tableHeadView(_:iconClick:)))) != nil) 
swift3.0  ?代替responds
if ((tmpSelf!.delegate?.tableHeadView(_:iconClick:)) != nil) 
用weak定义代理
weak var delegate:DelegateName?
// - MARK: Delegate
//在Swift中,制定协议需要遵守NSObjectProtocol协议,除了类可以遵守协议,结构体也可以遵守协议
@objc protocol HomeTableHeadViewDelegate: NSObjectProtocol {
    @objc optional func tableHeadView(_ headView: HomeTableHeadView, focusImageViewClick index: Int)
    @objc optional func tableHeadView(_ headView: HomeTableHeadView, iconClick index: Int)
}
8. Swift3.0中通知
NotificationCenter.default.addObserver(self, selector: #selector(HomeViewController.homeTableHeadViewHeightDidChange(_:)), name: NSNotification.Name(rawValue: HomeTableHeadViewHeightDidChange), object: nil)
NotificationCenter.default.post(name: Notification.Name(rawValue: HomeTableHeadViewHeightDidChange), object: newValue)
9. Swift3.0中的逃逸闭包

如果闭包被作为参数传递到函数时,该闭包不需要立即执行而是需要等某些线程完成任务之后再执行,那么需要在该闭包前加上@escaping,否则编译器报错。如下代码所示:

    convenience init(frame: CGRect, iconClick:@escaping ((_ index: Int) -> Void)) {
        self.init(frame:frame)
        self.iconClick = iconClick
    }
10.Swift3.0循环
//正序  0...2    0 1  2       0 ..<2   0 1
  for i in 0...2 {
            let btn = UIButton()
}
//倒序
 if subviews.count>1 {//在这里需要注意subviews.count的值一定要大于1,不然会出现错误
                for i in (1...subviews.count).reversed() {
                    let subBtnView = self.subviews[i-1]
                    subBtnView.removeFromSuperview()
                }
            }
11.Swift3.0循环Block
HotView.swift
var iconClick:((_ index: Int) -> ())?   //声明并定义一个block
convenience init(frame: CGRect, iconClick:@escaping ((_ index: Int) -> Void)) {
        self.init(frame:frame)
        self.iconClick = iconClick
    }

//点击事件
 func iconClick(_ tap: UITapGestureRecognizer) {
        if iconClick != nil {
            iconClick!(tap.view!.tag)
        }
    }

//页面上添加手势
let tap = UITapGestureRecognizer(target: self, action:#selector(HotView.iconClick(_:)))
                    icon.addGestureRecognizer(tap)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//点击页面,block回调
func buildHotView() {
        weak var tmpSelf = self
        hotView = HotView(frame: CGRect.zero, iconClick: { (index) -> Void in
           if ((tmpSelf!.delegate?.tableHeadView(_:iconClick:)) != nil) {
                tmpSelf!.delegate!.tableHeadView!(tmpSelf!, iconClick: index)
            }
        })
        hotView?.backgroundColor = UIColor.white
        addSubview(hotView!)
    }
12.Swift3.0常用控件
//UIButton
 let btn = UIButton()
 btn.setTitle(buttonTitles[i], for: UIControlState())
 btn.backgroundColor = UIColor.white
 btn.layer.cornerRadius = 5
 btn.tag = i
 btn.titleLabel?.font = UIFont.systemFont(ofSize: 10)
 btn.frame = CGRect(x: 30 + CGFloat(i) * ((ScreenWidth - btnW * 3 - 60) / 2 + btnW), y: blogLabel.frame.maxY + 10, width: btnW, height: 30)
 btn.addTarget(self, action: #selector(AboltAuthorViewController.btnClick(_:)), for: UIControlEvents.touchUpInside)
btn.setTitleColor(UIColor.black, for: UIControlState())
view.addSubview(btn)

//UILabel
  let buyCountLabel = UILabel()
  buyCountLabel.isHidden = false
  buyCountLabel.text = "0"
  buyCountLabel.textColor = UIColor.black
  buyCountLabel.textAlignment = NSTextAlignment.center
  buyCountLabel.font = HomeCollectionTextFont
  return buyCountLabel

13.didSet

属性观察者,类似于触发器。用来监视属性的除初始化之外的属性值变化,当属性值发生改变时可以对此作出响应。有如下特点:

  • 1 不仅可以在属性值改变后触发didSet,也可以在属性值改变前触发willSet。
  • 2 给属性添加观察者必须要声明清楚属性类型,否则编译器报错。
  • 3 willSet可以带一个newName的参数,没有的话,该参数默认命名为newValue。
  • 4 didSet可以带一个oldName的参数,表示旧的属性,不带的话默认命名为oldValue。
  • 5 属性初始化时,willSet和didSet不会调用。只有在初始化上下文之外,当设置属性值时才会调用。
  • 6 即使是设置的值和原来值相同,willSet和didSet也会被调用
//普通属性
    var firstName:String = ""
    var lastName:String  = ""
    var nickName:String  = ""
//计算属性
    var fullName:String
    {
        get
        {
            return nickName + " " + firstName + " " + lastName
        }
    }
//带属性监视器的普通属性

    var age:Int = 0 {
     //我们需要在age属性变化前做点什么
        willSet
        {
            print("Will set an new value \(newValue) to age")
        }
        didSet {
          print("age filed changed form \(oldValue) to \(age)")
            if age<10
            {
                nickName = "Little"
            }else
            {
                nickName = "Big"
            }
        }
    }
//调用
let me = People()
me.firstName = "Li"
me.lastName  = "Lei"
me.age = 30
14.Swift3.0速查手册

https://darielchen.github.io/SwiftManual/

    原文作者:yaoyao妖妖
    原文地址: https://www.jianshu.com/p/32c0712f529f
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞