美文网首页
Swift语法从开始到放弃

Swift语法从开始到放弃

作者: 辉叔叔啊 | 来源:发表于2017-10-17 02:30 被阅读182次

            突然想到半年没写过东西了,吓得我赶紧抽了根烟,倒了杯水,再放点朱哥走的时候留下的半袋绿茶加了点枸杞(治肾亏不含糖,谁喝谁知道),开始了这篇不知道是啥的写作。

            模仿不侵权吧,这年头搞得什么都侵权,万一涉及侵权什么的联系我啊。---->  鲁迅

            先来几张基本完成版本的新浪微博截图吧,为了少占用服务器空间就随便贴几张吧(这图片为什么不能缩小显示,一排放几张的那种,严重影响美观,差评!)

    主页 微博发布 相册浏览

            数据全部来自新浪开放接口,有兴趣想玩玩数据的可以移步--->新浪微博开放平台

            自从苹果于2014年WWDC(苹果开发者大会)发布的新开发语言,就开始了它推广之路,苹果也是将Swift作为主推语言供开发者学习,OC的地位也是从前三慢慢的下降到了十几名的位置,而Swift呢,从一开始的火热,到现在的不温不火。不过不得不承认的是它这种语言确实像苹果说的,简洁易学,在每次版本更新的时候都会将一些累赘的语法删除,保留最需要,最能理解,最简洁的语法。自从接触到Swift之后,慢慢的开始写了写,它的简洁的语法确实是可以减少很多的重复工作,包括一些对其他语法的引用,你可以从它里面看到java,C++, php, javaScript等等语言的影子。关于它的介绍可以移步百度百科--->Swift介绍

            说说完成的这个程序吧。当然我在这个程序中仅仅是做了个数据的展示,至于真实环境用户的数据缓存等等一些其他的技术,就略过了,这要讨论可能一时半会也写不完。

             有关这个程序我是从Swift1.0追随到Swift4.0的,基本都是在业余时间完成的,当然其中一段时间懒的写了就放下了,每次发布新版本又心动了就开始继续完善。对于每次版本更新语法的改变,给我的感受完全可以用红楼梦开篇的一句话来形容(这TM是啥):

    满纸荒唐言,一把辛酸泪

            整个程序的备份工作以及代码的提交都是在github上的,关于github上个人代码仓库的建立,有不知道的请移步我的博客-->github上建立个人代码仓库

            为什么我项目中没有用Swift去写?

            第一:虽说Swift和OC是完全兼容的,那么也就是说项目可以混编,这个没有错,但是现有的框架如果用Swift去写,很多现成的东西有可能都得用Swift一行一行的去写,这就避免不了的需要在项目中拉入很多新的基本和OC功能一模一样的框架,这样就造成了框架的重复,本来一行代码可以实现的问题在Swift中要写很多,那么本来应该很简单的语言变成了一种负担,总给人一种不伦不类的感觉。

            第二:项目的维护,毕竟项目不是一个人在写,对于新语言理解大家也都不一样,可能在这里要用这种思维去理解突然在那里要用到另一种思维,在找问题的时候也感觉比较麻烦。

            第三:新语法的变化,我是跟随着这个语言一直写过来的,到现在基本趋于稳定,但是每次更新一些新的语法的变化实在是让人头疼,尤其是2.0到3.0的迁移工作,那真是简直了,虽说现在稳定了,但是保不齐突然又来个突发奇想什么的大改一下语法也是有可能的,说实话它的实用性还有待考证(不过我新建项目写起来确实爽)。我看见群里曾有人说他学了四门语言,哈哈,这个倒是真的,亲身体会。写Alamofire请求框架以及一些其他框架的大神也是被苹果折腾的够呛,不过折腾归折腾,每次语言变化的一些微小细节都能从里面感受出来,就在前两天发布4.0的时候一个突如其来的崩溃整的我都想删了整个项目。

           第四:项目的兼容,Swift中有很多语法基本都是从8.0开始的,有些语法还是8.0以后的,现在项目的支持程度不够。

           当然,都是我自己的想法,不喜勿喷。


            说了这么多废话,开始进入正题吧。我写这个文章的目的,是把我在从Swift1.0到Swift4.0当中更新遇到的问题,以及一些我认为比OC新颖的语法顺便做一下笔记。当然记忆力不是很好,毕竟跨度有点大,可能很多语法的变化在改完每条红杠以后都忘了,我尽量写的详细一点。写了这么多我感觉此处应该有图,那就贴两张从开始到放弃的提交图吧:

    项目开始 最后提交(放弃)

           这只是从开始到结束的一小部分的提交记录,关于这两张图大家都懂,不做过多的解释了。

            那就从项目的搭建开始吧。至于我写的是啥, 看不下去的请移步---->戳我有惊喜(广告费记得给我)。

            新浪微博登录的授权模式:采用OAuth2.0的授权方式(很多第三方登录的提供的接口都是采用这种授权方式,包括微信支付宝),关于OAuth2.0的授权自行移步百度(当然第三方个网站文档也有很详细的介绍)。

            提到登录这里提一下字符串的截取方法,这个也是从2.0到3.0变化挺大的一个地方,

    字符串截取

    OC中字符串的截取:

    NSString *string2 = [string1 substringFromIndex:i];

    NSString *string3 = [string2 substringToIndex:11];

    Swift对于字符串截取进行了一个简化,我们可以直接指定从开始到结束的范围:比如在OAuth2.0授权中用到的,从query中截取授权码:

    let code = query[query.index(query.startIndex, offsetBy: 5)..<query.endIndex];

    由于Swift是强类型推断语言,所以对于可选的值我们需要进行解包,另外它的判断条件可以是多个条件并列的,我记得在2.0中还可以添加where关键字的限制,在3.0中移除了这个操作,还是以query值作为可选为例:

    if let query = request.url?.query, query.hasPrefix("code=") {

    // 这里的query为解包后的值,真实存在的可以直接使用

    } else {

    // 异常处理

    }

    对于判断Swift还加入了新的语法guard(判断与if正好相反):

    guard let img = image else {

    print("1张图片缓存图片为空")

    }

    字符串的拼接

    OC中可以直接使用:

    1. string = [string1 stringByAppendingString:string2];

    2.string = [NSString initWithFormat:@"%@,%@", string1, string2 ];

    3.string = [string stringByAppendingFormat:@"%@,%@",string1, string2];

    Swift中虽然提供了这些方法但是使用起来比较麻烦,它给我们提供了类似JAVA中的字符串拼接方法:

    let sting = string1 + string2

    或者插值语法

    let sting = "\(string1) + \(string2)"

    代码块

    说起请求,就不得不提到网络延时的问题,在3.0中对于GCD有了更大的改进:

    我们在OC中的延时代码(用C语言的函数实现):

    // 任务放到哪个队列中执行

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

    doubledelay =3;// 延迟多少秒

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay* NSEC_PER_SEC)), queue, ^{

    // 3秒后需要执行的任务

    });

    在Swift改进中变得更加面向对象:

    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Double(1 * Int64(NSEC_PER_SEC)) / Double(NSEC_PER_SEC), execute: {

    self.close()

    })

    说起代码块 ,对于类中我们引用的对象直接可以用函数名或者变量名去引用,然而在代码块中引用就必须使用self才能调用,在2.0中写入代码块的函数都是无法提示打出来的,这一点在3.0中有了改进。

    我们在OC中所说的代码块在Swift中似乎有了新的代言,称为闭包。闭包苹果在3.0中加入了逃逸闭包和非逃逸闭包的区别。

    函数的使用:

    关于基本函数的创建使用可以移步我的博客:Swift基本函数的使用

    在函数的调用上面与OC最大的不同点在于链式函数的使用,在Swift中你可以将有因果关系的一堆函数一直用 . 链接下去,直到返回你想要的值,这样做可以最直观的感受就是可以将有关系的一组函数组合在一起,找问题也不想OC中那样跳来跳去,这种使用类似最近比较火的ReactiveCocoa

    在3.0中对于有返回值得函数可以使用"_"接收来忽略返回值,不然会报警告,当然警告也可以通过在返回的函数上面使用@discardableResult关键字来忽略警告。

    既然文件之间的函数可以相互调用,那么就存在文件函数错用的问题,Swift也为我们提供了函数范围的限制,2.0中一直是使用private、public关键字限制,不过在3.0对于private、public的定义有了新的含义,它在这两个关键字的基础上又提供了两个新的关键字:fileprivate、open

    于是在同一个文件里面不同的类定义的函数只要定义为private就不能相互引用,就连扩展也不能引用,扩展中要引用就要将属性或者函数定义为fileprivate,关于这几个关键字的细节介绍可以移步----->关键字的限制

    扩展

    不得不说这是个很好用的东西,以前我们在OC一个类里面的写的东西甚至挖空了心思想把它移出去,现在在Swift中我们可以使用extension轻松将这些东西移出去,将同类东西归类比如我们经常用到的一些代理代码:

    extension PhotoBrowserCollectionViewCell: UIScrollViewDelegate {

    func viewForZooming(in scrollView: UIScrollView) -> UIView? {

    return imageView

    }

    当然它的更强大的使用不仅仅限于此,项目中用到的就是这个地方了。

    约束(当然可视化视图就不需要考虑这些了)

    我们经常在代码中写约束用到一些框架就可以轻松实现,但是它底层苹果为我们提供的代码却相当烦躁,这个确实不太友好

    比如我们对于一个视图的约束:

    //        indicator.translatesAutoresizingMaskIntoConstraints = false

    //        contentView.addConstraint(NSLayoutConstraint(item: indicator, attribute: NSLayoutAttribute.centerX, relatedBy: NSLayoutRelation.equal, toItem: contentView, attribute: NSLayoutAttribute.centerX, multiplier: 1.0, constant: 0))

    //        contentView.addConstraint(NSLayoutConstraint(item: indicator, attribute: NSLayoutAttribute.centerY, relatedBy: NSLayoutRelation.equal, toItem: contentView, attribute: NSLayoutAttribute.centerY, multiplier: 1.0, constant: 0))

    而框架为我们提供的解决方案:

    indicator.snp.makeConstraints { (make) in

    make.centerX.centerY.equalTo(contentView)

    }

    相比较相当简单,说到约束提一下VFL(可视化格式语言):

    我们要约束一个视图可以用

    maskIconView.translatesAutoresizingMaskIntoConstraints = false

    addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[subview]-0-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["subview": maskIconView]))

    addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[subview]-(-35)-[regButton]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["subview": maskIconView, "regButton": registerButton]))

    其实这些框架的底层基本都是用这些东西实现的,不过框架开发者为我们提供了比较友好的接口而已。

    遍历

    起初在1.0的时候我们可以直接使用C语言的for循环遍历,但是在后来3.0的时候直接改掉了这个使用方法,我们可以用这样的方法遍历:

    for dict in array {

    list.append(Status(dict: dict))

    }

    for _ 0..<10 {}

    还有更简洁的语法:

    array.forEach({ (dict) in })

    (0..<10000).forEach { (i) in }

    三目运算符

    在3.0中加入的新语法中有个"??"语法,这个也是借鉴C++的语法。使用相当方便。

    比如:

    let count = status?.pictureURLs?.count ?? 0

    枚举

    不得不说这个在Swift中确实是个突破,在OC中我们只能定义用C风格,枚举值一般是4个字节的int值,在64位系统上是8个字节。

    而在Swift中打破了这个常规,比如我们可以定义string类型的枚举,而且我们在枚举中还可以使用函数:

    enum StatusCellIdentifier: String {

    case NormalCell =  "NormalCell"

    case ForwardCell = "ForwardCell"

    /// 静态函数,根据微博数据返回对应的标示符

    static func cellId(status: Status) -> String {

    return status.retweeted_status == nil ?

    StatusCellIdentifier.NormalCell.rawValue :

    StatusCellIdentifier.ForwardCell.rawValue

    }

    数据刷新

    在我们项目中通常会用到一些第三方框架去处理数据的刷新问题,不过苹果为我们提供了原生的刷新控件:UIRefreshControl,说一下原理吧,API提供给我们的方法不多也就几个。

    一般刷新采用kvo监听视图frame的变化,就像这样:

    self.addObserver(self, forKeyPath: "frame", options: NSKeyValueObservingOptions(rawValue: 0), context: nil)

    然后我们会根据frame的变化做一下我们想要的操作(这里通常我们会指定一个偏移量作为基准,然后判断和这个偏移量的大小做相应的操作):

    向下拉y值越来越小,向上推y越来越大

    从表格顶部向下拉,y是负数

    拽到一定幅度,会自动进入刷新状态

    字典转模型

    这里比较特殊的是int类型,int类型在字典转模型的时候必须为不可选的必须赋予初始值与oc不同在于数组中加入数据更加简单。

    结构体属性

    在OC中我们修改结构体属性会像这样:

    CGRect btnF = self.btn.frame;

    btnF.size.height += 40;

    self.btn.frame =  btnF;

    后来我们引入了分类可以直接修改属性,而Swift中我们可以直接修改:

    s.height = 0.6 * s.height

    导航栏

    关于导航栏这个问题吧,每次苹果发布大的版本都会把它的结构改一遍,当然每次大版本发布我都要跟着改一遍这些特殊的页面,也许有它的考虑吧,毕竟这个东西应该是越写越好的(暂时这样认为),但是我想说的是fuck your sister

    协议

    有人称这个语言为面向协议的编程语言,目前使用到的协议仅仅限于常用的协议的使用,一些高大上的用法还在学习中。。。。

    目前和其他不一样的地方能相当的就这些了,以后想到继续更新吧。。。。

    相关文章

      网友评论

          本文标题:Swift语法从开始到放弃

          本文链接:https://www.haomeiwen.com/subject/ztiluxtx.html