• 今天在OC工程里面直接引入了一个第三方的Swift包,结果OC文件里面死活找Swift对象。打开 “工程名-swift.h”文件内容似乎是空的。(正常的文件应该会有很多OC方法,对象) 后来发现工程里面并没有”工程名-...

    今天在OC工程里面直接引入了一个第三方的Swift包,结果OC文件里面死活找不到Swift对象。打开 “工程名-swift.h”文件内容似乎是空的。(正常的文件应该会有很多OC方法,对象)
    空文件
    后来发现工程里面并没有”工程名-Bridging-Header.h”文件。
    然后如果需要生成”工程名-Bridging-Header.h”文件,必须在导入Swift文件,创建一个新的Swift文件,(必须是在工程里面没有任何Swift文件时候)。当有了”工程名-Bridging-Header.h”文件以后,”工程名-swift.h”文件如下图:
    正常的"工程名-swift.h"文件

    展开全文
  • OCSwift混编后,感觉吊吊地,但某一天要发布应用时,心情就纠结了。本地AD hoc打包30.4M,发布应用到商店并且成功上线,发现APP体积为48.8M,心情非常惊讶。同事产品需求要把APP体积降到10M,一阵....。那么,APP...

    至今,推出swift已经是第三个年头了,小哥本着学习的心态,大胆地尝试在旧项目中用Swift编写。OC与Swift混编后,感觉吊吊地,但某一天要发布应用时,心情就纠结了。本地AD hoc打包30.4M,发布应用到商店并且成功上线,发现APP体积为48.8M,心情非常惊讶。同时产品需求要把APP体积降到10M,一阵….。那么,APP如何瘦身呢?

    为什么会突然多了18.4M呢?经过查看包内容,发现里面有个Frameworks文件夹,混编会产生libswiftXXX.dylib的动态库,统计一下这些swift动态库文件的大小,惊讶了:
    还在路上,稍等...

    问题提出:混编有多大影响?
    对ipa包解压,观察Frameworks文件夹,如下图:

    还在路上,稍等... 还在路上,稍等... 还在路上,稍等...

    • 除了下划线以外,如AFNetworking,SDWebImage…都是OC编写的第三方库。它们占用的空间大约100KB,而swift语言编程的第三方库,占用的空间1MB以上。
    • 值得一提的是,需要在Podfile顶部加上“use_frameworks!”。开启这个选项之后,所有以源码引入的pod都会编译成动态链接库
      还在路上,稍等...

    努力尝试瘦身的过程
    一、首先尝试删除YYKit.
    结果是:ipa包缩小1.2M(也就是说YYKit占用1.2M
    过程:
    (1)未删除之前ipa包大小是26.7M
    还在路上,稍等...
    项目中Cocoapods用到YYKit,YYKit的文件大小是个什么情况:
    还在路上,稍等...
    文件夹里面有Vendor和YYKit,其中Vendor大小是9.2M,YYKit是1.8M
    (2)移除YYKit,打包ipa包发现大小缩小至25.2M:
    还在路上,稍等...
    (3)看来YYKit是占用空间大小的重要因素。
    (4)移除了Rxcocoa,RxSwift,SwiftJson后,ipa缩小至:21.5M
    还在路上,稍等... Rxcocoa,RxSwift,SwiftJson共占用3.7M
    (5)移除Alamofire,ipa包缩小至:20.6M
    还在路上,稍等... Alamofire占用0.9M

    二、一些参考资料
    基于clang插件的一种iOS包大小瘦身方案
    图片压缩工具,(亲测不错)
    智图图片优化平台,鹅厂程序猿出

    展开全文
  • 1、概论及Swift介绍

    一、概论及Swift介绍

    iOS7刚发布多时候,苹果引入了JavaScriptCore.framework用来处理JavaScript,看到了可以接触其他编程语言的契机,使iOS程序员不用吊死在OC这一颗树上。当但iOS8发布的时候,简直Hold不住了,新的开发语言《Swift》出现了!Swift是一种新的编程语言,基于C和OC,可用于Cocoa和Cocoa Touch编程。编写代码中充满互动性和乐趣,且语法简洁而传神,可以使应用程序运行飞快。Swift是以后iOS和OS X的项目开发语言的选择之一,或在您当前的应用程序中使用,因为Swift与Objective-C可以并驾的使用,实际上Swift可以与C和OC混编。


    Xcode6下载地址:http://pan.baidu.com/s/1D3Z0i


    Swift的特点:

    1、安全性:增强了类型安全与类型推断,限制指针的直接访问,并且自动管理内存,可以轻松地创建安全,稳定的软件。

    func configureLabels(labels: UILabel[]) {
        let labelTextColor = UIColor.greenColor()
        for label in labels {
            // label inferred to be UILabel
            label.textColor = labelTextColor
        }
    }

    其中:

    func关键字是定义一个函数;

    labels: UILabel[] 的意思是labels是形参名字,UILabel[]是形参类型,表明是一个数组,数组里边元素是UILabel类型都对象;

    let labelTextColor = UIColor.greenColor() 是定义一个常量labelTextColor,以前的[UIColor greenColor] 变成了现在的UIColor.greenColor()实现方式

    for label in labels { } 这个是一个for循环,OC的实现方式是这样的  for(UILabel *label in (NSArray *)labels) {},但现在但方式更简洁了
    label.textColor = labelTextColor UILabel对象的textColor属性设置,写法上和OC没区别


    2、模块化:包括自选,泛型,元组,以及其他现代语言特性。通过Objective-C的启发并在此基础上改进,Swift 代码更容易读和写。

    let cities = ["London", "San Francisco", "Tokyo", "Barcelona", "Sydney"]
    let sortedCities = sort(cities) { $0 < $1 }
    if let indexOfLondon = find(sortedCities, "London") {
        println("London is city number \(indexOfLondon + 1) in the list")
    }

    其中:

    let cities = ["London", "San Francisco", "Tokyo", "Barcelona", "Sydney"]  这样就定义了一个常量数组,其中元素上字符串类型,OC的字符串上@"string",但Swift字符串和C字符串写法一样,如 "string",OC快捷方式定义数组可以使用@ ["London", "San Francisco", "Tokyo", "Barcelona", "Sydney"],但现在Swift数组实现相对更简洁了,和C数组写法一样。

    if let indexOfLondon = find(sortedCities, "London") { }就是查找一个数组中是否存在某元素了,如果返回但Index存在,就打印

    println()与NSLog但作用一样,只不过NSLog(@"%d")换成了了现在println("London is city number \(indexOfLondon + 1) in the list"),用 \(indexOfLondon + 1) 这种形式替换了@"%d"这种格式化输出。


    3、功能强大:利用强大的模式匹配可以编写简单且表达性好的代码。格式化字符串清晰自然。通过Swift可以直接使用Foundation和UIKit框架。

    let cities = ["London", "San Francisco", "Tokyo", "Barcelona", "Sydney"]
    let sortedCities = sort(cities) { $0 < $1 }
    if let indexOfLondon = find(sortedCities, "London") {
        println("London is city number \(indexOfLondon + 1) in the list")
    }


    4、代码互动:使用playgrounds尝试新的​​技术,分析问题,和原型用户界面。(Playgrounds make writing Swift code incredibly simple and fun. Type a line of code and the result appears immediately.


    5、更快

    以上参考  https://developer.apple.com/swift/



    二、编写HelloWorld

    一般学任何一门语言,第一个项目都会写个HelloWorld,那这里也按照规矩来一个:需要下载Xcode6,可以去官网下载https://developer.apple.com/cn/,稍后我会上传到网盘。

    下载并安装完Xcode6之后,打开Xcode,并且新建一个项目(选择Single View Application模版):注意选择Language为Swift



    打开项目后,目录结构如图:



    看到这里,我们并不陌生,和OC项目结构一样,Main.storyboard还在,只不过以前到 .h和.m文件没有了,替换成了选择到 .wift文件,但main.m文件没有了,那以前OC项目中UIApplicationMain哪去了 ?别着急,打开AppDelegate.swift



    愿开在这里,虽然写法变了,不过意并没有改变,对号OC代码,不难理解AppDelegate但定义形式,如果写过JAVA和JS代码,看到这里一定兴奋了,太熟悉了,但仅仅了解OC也没必要担心,因为很容易理解。class定义一个类,其中有成员变量和方法,成员变量用var定义,方法用func定义。遮掩一个.swift文件替代了OC的 .h和.m文件,看起来很简洁,也很容易理解。

    项目大体结构了解了,那现在向世界问好吧:

    打开ViewController.swift

    import UIKit
    class ViewController: UIViewController {                    
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }
    }

    OC代码中的#import <UIKit/UIKit.h>现在被更简洁的import UIKit替代,override func viewDidLoad() 重写父类方法。在viewDidLoad()方法中添加如下代码:

    override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
            println("HelloSwift")
        }

    然后编译和运行,控制台打印HelloSwift,发现了没有,连一句代码结束分号都可以不用写了。但这个iOS开发离不开UI,所以这个HelloSwift太简单了,添加一个UILabel到页面,然后展示HelloSwift吧:

    代码如下:

    import UIKit
    
    class ViewController: UIViewController {
                                
        override func viewDidLoad() {
            super.viewDidLoad()
            
            let label = UILabel()
            label.textColor = UIColor.blackColor();
            label.backgroundColor = UIColor.redColor();
            label.text = "HelloSwift";
            label.frame = CGRect(x:0, y:100, width:320, height:44)
            
            self.view.addSubview(label)
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }
    }

    运行效果:



    到这里,学习Swift到第一个程序算结束了!更多内容请点击这里

    欢迎加入群共同学习和进步:QQ群:170549973

    展开全文
  • OC 也好,UI 也罢,甚至于swift,几乎都会涉及self,super用法,并且通常来说太好理解,总会迷迷糊糊的,所以必须要搞清楚 补充知识:OC中全局变量和局部变量 变量显示存储空间生命周期特点 成员变量(实例...

    ---恢复内容开始---

    OC 也好,UI 也罢,甚至于swift,几乎都会涉及self,super用法,并且通常来说不太好理解,总会迷迷糊糊的用,所以必须要搞清楚

    补充知识:OC中全局变量和局部变量

    变量显示存储空间生命周期特点
    成员变量(实例变量、属性) 在类的声明中定义,在@interface CLASS ( ) 和@end 中间 创建对象时候有效,对象销毁(释放)结束 1.定义的时候不能初始化2.只能通过对象访问,不能离开类单独存在
    局部变量 函数体内或代码块中 函数体内 作用域: 从定义的那一行开始,直到大括号结束或者遇到break return为止
    全局变量 函数外部 静态区 整个文件(从定义变量的那一行直到文件结束) 程序一启动就会自动分配内存空间,直到程序释放才结束

    简言之:全局变量是放在函数体外(或者说方法外),局部变量是放在函数体内(方法内),全局变量作用域是整个文件,(这个整个文件的含义是当我写在.h文件中,在.m文件也是可以访问的,.h和.m文件是一体的,创建的时候就同时会生成)

    突然脑子死机冒出了一个问题:引入头文件的目的?还有和继承的区别?

    首先:引入头文件,一般是只引入.h文件就可以,引入头文件,引入了这个文件的类,类型,方法的声明以及实现(相当于引入了这个类,但又不是引入这个类),为什么这么说,

    加入A文件引入了B文件的头文件,不是说A文件就可以访问B文件的属性和方法了,我们知道,属性和方法只能由A文件中的类或者类对象去掉用,所以我们引入了一个文件

    要想在B 文件访问A文件属性和调用方法,只能在B文件实例化A对象,用A对象去访问和调用.

    这里又可以延伸一个东西:就是我们狭隘的理解全局变量(也说全局属性)作用域为只适用于当前.h.m文件,那么引入头文件后,是不是同样有作用,这个问题其实很简单,

    引入头文件,就是当前文件多了个文件,那么显然,多出的文件在当前文件中同样有作用,也就是说,属性和方法写到哪无所谓,只要是该文件中的类的对象,就可以访问属性,

    调用方法.

    -----------进入正题:

    1.self用法:

    1)

    谁调用了当前方法,self就指的是谁,

    self出现在对象方法,self就代表对象,self出现在类方法中,self就代表类,

    这么一说很笼统:理解后也就是:对象方法是由对象去掉用,类方法是由类去掉用,而self是出现在方法内部的,谁调用谁就替代self(也就是说self可以是类也可以是对象)

    2)

    self修饰变量,表示访问的是一个全局的实例变量(只是这么一说,肯定被读者忽略,那么为啥么要强调这一句话?)

    举例如下:

    >> 1. 声明的时候age没有下划线,导致在set方法中会出现问题

    >> 2. 在Set方法中实现的时候,因为形参跟成员变量同名,形参属于局部变量,所以导致一个结果。局部变量跟全局变量同名的时候,会暂时屏蔽全局变量的作用域。解决这个问题就引入self

    >> 3. 所以在main函数中调用时,结果是0.

    >> 4. 在set方法中加入self ->age = age, self在对象方法中就代表当前的对象,self –>age 访问的是全局的实例变量。所以问题就解决了。

    ------------------------------第一步类的声明--------------------------

    #import <Foundation/Foundation.h>
    @interface Person : NSObject
    {
        int age; //实例变量没有下划线时
    }
    //封装对实例变量的读写的方法
    -(void)setAge:(int)age;
    -(int)age;
    @end

    ------------------------------第二步类的实现--------------------------

    age = age

    局部变量 和 全局变量同名会屏蔽全局变量的作用域:

    所以等号左边的age就是指-(void)setAge:(int)age中的age,注意看:我为什么说这个age是局部变量?冒号右边有个(int)age其实也就是在方法内部定义了一个

    局部变量age,所以在方法内部age = age都是指(int)age中的age,此时,才到了self大显神通的时候了,正因为self在修饰变量的时候是访问的全局的实例变量,所以体现了

    self的价值和用处.

    #import "Person.h"
    @implementation Person
    -(void)setAge:(int)age{
        //age = 88
        //当局部变量和全局变量同名的时候,局部变量会暂时屏蔽全局变量的作用域
        age = age;
    }  //局部变量age的生命周期是到此处结束
    -(int)age{
        return age;
    }
    @end

    ------------------------------第三步main函数中--------------------------

    #import <Foundation/Foundation.h>
    #import "Person.h"
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            //创建对象
            Person *p = [Person new];
            //设置年龄
            [p setAge:88];
            //打印输出年龄
            NSLog(@"_age = %d",[p age]);
        }
        return 0;
    }

    --------------------------第四步修改的set方法实现-----------------------

    #import "Person.h"
    @implementation Person
    -(void)setAge:(int)age{
       // 此时就可以赋值了  self  == p
    self->age = age;     // self ->age 访问的是全局的实例变量} 
    -(int)age{
        return age;
    }
    @end

    2.类的继承与派生:

    子类继承父类便拥有父类所有的属性和方法(注意是拥有不是简单的引入(引入头文件),引入的还是别人的,拥有的才是自己的)

    注意:父类的私有属性是不能被子类继承的(私有属性就是写在.m文件中的属性,要和实例变量修饰符private修饰的变量区分开)

    提一下:private修饰的实例变量不是完全私有的,是可以被子类继承的,但不能被子类所使用(就像父亲给了儿子一个加了锁的宝箱,儿子虽然拥有但是打不开的)

    举个例子:就像抄别人的东西始终是别人的,只有自己想出来的,自己总结出来的才是自己的,就像我的博客是劳资一个字一个字打的,

    那就是我的.(怎么有种亲儿子和干儿子的区别)

    继承:是单继承,什么意思?就是子类只能继承一个父类,父类可以拥有多个子类(你只能有一个亲爹,但你亲爹可以生好几个儿子)

    OC 没有多继承但可以多层继承(就是子类可以继承父类,父类可以继承父父类,但是子类不能继承父父类,不要问我为什么,你爷爷能生出你么)

      派生类(其实也就是子类)的概念其实就是说:子类继承了父类,仍然可以添加自己的属性和方法,(儿子继承老子的财产,当然可以自己去创造财富)

    2.1继承的注意事项:

    只有一条:子类是不能定义和父类相同的实例变量的,例如父类声明 了一个int _age,子类就不能重复声明了(这句话的前提肯定是子类已经继承父类了)

    也就是说,属性没有重写这一说(子类继承父类,已经拥有了父类的属性,那么子类如果再定义一个相同名称的属性,就会造成变量的重复定义,会出错),

    而方法是可以重写的

    3.方法的重写:(还有后面会提到的重写构造方法)

    定义:子类重写父类的方法就是方法的重写.

    子类重写父类的方法,假如父类Dog有一个方法是 – (void)eat; 子类重写了这个方法,子类对象调用的时候会先调用子类的这个eat方法,

    子类有这个方法,就不再调用父类,但是如果想掉就在eat方法的实现中加入[super eat];即可

    衍生出方法的调用顺序:当子类对象去掉用一个方法的时候,会先从子类中找是否有这个方法,如果没有就去父类中找,依次往上,

    直到找到最顶层的NSObject为止,如果最顶层也没有就会报错.

    ------(走了会神儿...写到这里突然想到工作中的事儿,工作中做东西目的是实现功能和高效,因为老板要的是结果,所以,有些新人出去总想着

    亲力亲为,其实是过于偏执,你会写这很好,但作用不大,提升也不大,你用别人的在别人的基础上优化,既可以学习也可以提高效率,还能提升自己优化代码的能力)

    4.实例变量修饰符

    @public(公开的)在当前类和任何别的类中,都能被实例变量所属的对象访问,或者使用,(这里所指的任何别的类,是泛指通过头文件的引入,也可以用extern修饰)

    @protected(受保护的)只能在本类和子类(OC中实例变量默认是被他修饰的)

    @private(私有的)只能在本类,相对私有,能被子类继承,但不能被子类访问

    @package (包)用的很少,可以在本类和其他类中使用,但和public是有区别的,package是指当前类中,就是用package修饰的,子类继承后不能访问

    5.OC中私有属性和私有方法

    1)

    私有属性:上文已经多次提到,就是在.m文件中声明一个属性,不能被继承也不能被子类访问

    相对私有属性:是指被实例变量修饰符@private修饰的属性,可以被子类继承,但不能被子类访问

    2)

    私有方法:

    什么是私有方法?私有方法是干吗用的?我为啥呢么要用私有方法?

     私有方法就是在.m文件中声明的一个方法,在.h文件中没有提供该方法的接口.

     没有接口,我在main函数(或者别的文件)中肯定不能通过对象去调用,这就隐藏了这个方法,

    如下所示

    work方法是不能在main函数中访问的

    ---------------------------第一步在.h里面声明一个方法------------------------

    #import <Foundation/Foundation.h>
    @interface Person : NSObject
    //声明一个对象方法
    -(void)run;   //一个接口
    @end

    ---------------------------第二步在.m里面实现方法并添加一个不在.h文件中声明的方法------------------------

    #import "Person.h"
    @implementation Person 
    -(void)run{
        NSLog(@"班长在跑");
    }
    //私有方法(.m中定义的,.h中并没有声明)
    -(void)work{
        NSLog(@"班长工作,月薪28k");
    }
    @end

     

     

    那么重点来了,有吊用?

    举个例子:同样我写一个run方法,但是我的run方法写的很高级,功能很多,他一边跑还一边统计时速,油量,车胎热度等等运行中的指数,如果我都把这些指数提供接口

    ,那么代码就不好维护,可读性也不高,而且这些参数我只是希望客户能看到就可以,那么我把这些参数方法的实现写到.m文件中的run方法中,我只需要在main函数中,用

    对象去调用run方法就会得到了这些参数,这就是私有方法的运用

    6.description方法的介绍和重写:

    什么是description方法?

    description方法其实就是当我以%@方式打印对象时系统会自动调用这个方法(打印类对象调用类方法,打印对象调用对象方法)

    打印结果如下图所示:打印类结果是类名,打印对象默认会返回<类名:内存地址>(示例是重写了该方法)

    虽然字符串也是对象,但字符串在使用@%打印时情况特殊

     

    注意:如果在-description方法中使用NSLog打印self会造成死循环

    - (NSString *)description {

        // 下面代码会引发死循环

        // NSLog(@"%@",self);

        //return @"abc";

    }

    延伸:

    字符串对象的length方法:计算的是字符串的字数,而不是像strlen函数那样,计算的是字符数。如“哈ha123”length得出的结果是6,返回unsigned long类型,而strlen函数得出的结果是8,因为一个汉字占3个字节。

    提示:字数也包括空格。

    7.多态:

    多态:父类指针指向子类(肯定要有继承)

    举例:Animal 和 Dog 都有eat的方法

    Animal *anl = [Dog new];

    [anl eat];

    调用的是子类Dog的eat方法

    为什么呢? 

    对象调用方法,实际上是通过isa指针找到代码区的eat方法,而多态就像是把儿子的名字改成了他爹的名字,但方法还是儿子的方法

    8.SEL:全称Selector 表示方法的存储位置。

    Person *p=[[Person alloc] init];

    [p test];

    寻找方法的过程:

    (1)首先把test这个方法名包装成sel类型的数据;

    (2)根据SEL数据找到对应的方法地址;

    (3)根据方法地址调用相应的方法。

    (4)注意:在这个操作过程中有缓存,第一次找的时候是一个一个的找,非常耗性能,之后再用到的时候就直接使用。

    关于_cmd:每个方法的内部都有一个-cmd,代表着当前方法。

     

    注意:SEL其实是对方法的一种包装,将方法包装成一个SEL类型的数据,去寻找对应的方法地址,找到方法地址后就可以调用方法。这些都是运行时特性,发消息就是发送SEL,然后根据SEL找到地址,调用方法.

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    转载于:https://www.cnblogs.com/yiyuanchenfeng/p/5967359.html

    展开全文
  • Swift是一门类型安全的语言。出于安全考虑,默认变量为空。但编码中有一些方面必须考虑为空的情况,比如类型转换,只要可能为空,就可能带来大量的潜在崩溃风险。Swift的解决方式是声明可选型变量,以将确定因素...
    Swift是一门类型安全的语言。出于安全考虑,默认变量不为空。但编码中有一些方面必须考虑为空的情况,比如类型转换,只要可能为空,就可能带来大量的潜在崩溃风险。Swift的解决方式是声明可选型变量,以将不确定因素控制在可选型范围内。

    可选型在OC中没有类似概念,Swfit作为一门安全的编程语言,有可选型的概念。比如var age: Int?  就表明age是Int型的可选型变量(可选型是通过一个枚举实现的,有值返回值,无值返回nil)。在使用的时候,age可能返回一个Int数据,也可能返回空。在进行类型转换,强转之类的,解包,之类的,可能会因为类型不同返回空等,这时该变量可能是空,就需要可选型去声明,去填坑,防止可能的BUG
    类中可声明可选型变量,这样在后续编程时就知道该值可能为空,使用要注意。
    var  name: String?
    可选型的变量,可以不在构造器中初始化,编译器不会因此报错,否则必须在构造器中实现

    安全起见,可以把可选型转换成对应的非可选性变量,这样后续操作就不用提心吊胆是否为空了,用到的操作就是解包。

    比如,最普通的解包方式如下三种

    var age: Int?  //表明age是Int的可选型变量,不必在构造其中声明也可以通过编译
    age = Int(“12”)  //初始化了age,但此时如果打印age,输出的是Optional(12)
    Let newAge= age!  //第一种,对age进行解包,并付给newAge,此时newAge不需要声明为可选型即可通过编译

    let newAge2 = age as! Int//第二种,强制转换成Int,如果age确实不能转,会直接崩溃

    let newAge3 = age as? Int //第三种,安全转型,如果age确实不能转,会返回一个nil,但不会因为转型而失败

    上述解包方式优劣势很明显,没有容错,解包失败直接崩溃。??运算符能在一定程度上解决上述问题
    var age: Int? = Int(“12”)
    let newAge = age ?? -1   //此处??返回的结果是12,如果age可选型解包后是空,则默认后面的-1,不会直接崩溃

    相比较强制解包,Swift提供另外两种可选绑定的解包方式,更安全,分别是if-let,guard-let-else。Demo如下
    let age: String? = Int(“12”)
    If let a = age {
    Print(a) //表明age解包成a成功,
    }

    guard let a = age else {
        print(“解包失败”)
        return
    }
    print(“解包成功,a = \(a)”)

    //在此使用解包后的值


    两者区别主要是一个先处理解包正常情况,一个先处理解包异常情况,无他。

    可选链

    首先,别害怕,这不是类似于响应链之类的概念,只是个小技巧而已。

    如果说a是一个可选型,if-let就能对其安全解包。如果你关心的是a下面的可选型的变量,那就要用两个if-let嵌套调用。如果三层的话,就需要用三层if-let。这样的代码不够美观,可以用以下方式代替。

     //example返回一个可选型的类,类中age是可选型的变量,一行即可可选绑定的方式安全解包
    if let a = example(code: "xw")?.age {
                print("age == \(a)")
            }
    隐式解包

    Swift中X?表示可选型变量,使用!可对可选型进行解包。其实Swift中给还有X!这种类型,这种类型叫做隐式解包。隐式解包是一种特殊的可选型,我们工作过程中除非万不得已,不要主动创建隐式解包的类型。
    隐式解包类型可以和普通类型进行运算,编译器不会报错,此时他会被解包(如果解包失败则直接崩溃),结果返回的也是非可选的类型。

            let a: Int! = Int("12") //变量a是隐式解包类型,
            let b = a + 1           //隐式解包类型a,经过+1运算,自动进行解包成Int进行运算,b变成了非可选的类型
            let c = a               //隐式解包类型a直接赋给c,c也是隐式解包类型,
            let d = a + 1 - 1       //隐式解包类型a经过+1-1运算赋给了d,虽然+1-1数值未变化,但已经解包成了非可选型,

            let arr = [1,a]         //数组只能存放一种数据类型数据,a是隐式解包类型数据,因此arr变成了隐式解包类型的数组,此时即使是取第一个1,也是可选型数据

    Any/AnyObject
    Any/AnyObject和OC中的id概念比较接近,目前多用在Swift,OC桥接时作为参数,返回值。他俩的区别呢,主要是AnyObject只能作为class的泛型指针,如果是Int等,就不能用AnyObject,只能用Any;Any的话,范围就广了,各种变量,乃至方法等,都能用Any。简单说,AnyObject是Any的子集,

    PS:可选型放入数组再取出的问题

    无意中发现一个问题。将一个可选型数据,放入数组,再取出来,数据类型就变成了X??,也就是说可选了两次,需要解包两次才能变成非可选型,有点纳闷。后经过研究后发现,使用数组的first,last等方法取元素时,返回的是一个可选型,?,系统方法只是取出了对应元素,并把它写成可选型的变量(可选型只是个枚举嘛),并没有判断元素是否是可选型,就需要你自己处理如何解包了。也就是说,使用first等返回可选型的方法,是需要默认跟上一个解包的操作的。

    展开全文
  • 我们使用的是WKWebView,在下面方法做的一系列的操作 func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) 1、全部代码 /// 准备加载 func webView(_ webView: ...
  • Swift_Singleton

    2015-11-18 21:17:06
    OC中,单例的写法想必大家很清晰了,在这里给大家介绍下Swift中几种单例的写法: 最简单的写法 static var instance: DBHelper? = nil static func sharedInstance() -> DBHelper { if instance == nil
  • 主要是因为使用了nib文件和storyboard。但是作为程序员,我们需要挑战一下自己,如果没有nib文件和storyboard,我们怎么来构建一个应用。 (1)新建一个iOS项目,直接删除Main.storyboard文件,然后在下面选项中删除...
  • swift3.0发布以后,swift语言开始趋于稳定,因为语言设计的问题,swiftoc具有很大差异,当然,我们日常使用的很多第三方框架也发生了改变。那么今天跟各位同学介绍的就是一个很新的第三方框架管理工具--carthage。...
  • 可选值 4.1哨岗值 Sentinel Value 定义:有的函数可能返回nil 当函数...swift中Optional的本质是一个枚举(目前可以先具体思考,等以后的项目中慢慢就领悟到了)。 enum Optional&lt;Wrapped&gt; { case...
  • iOS 拨打电话三种方法

    2019-04-29 08:00:22
    A, 昨天接手项目中的一个需求就是可以拨打...1:这种方法,拨打完电话回到原来的应用,会停留在通讯录里,而且是直接拨打,弹出提示 NSMutableString* str=[[NSMutableString alloc] initWithFormat:@"tel:%@",...
  • 我理解为就是某个类的 实例或者其子类实例可以同时访问改 变量,且在内存中仅有一份,这个感觉略,我真没遇到过呀! 2.实例变量 @name 这个在OC中就是成员变量或者属性吧 一般写成 _name 或者 @pro
  • 一说支付,大多数人都会理解支付方式是下载微信和支付宝SDK进行支付,但是其实还有其他的方式,就是H5调用系统支付宝和微信进行...这里说一下,这里微信和支付宝都是使用这个方法里进行 - (BOOL) webView:(UIWebVi
  • 实现原理,判断是否是有alipays://或者alipay://,如果有,就直接调用 [[UIApplication ...OC代码: -(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navig...
  • 预告 ARC 重写:iOS 实现的 json 数据源的 O-R Mapping
  • iOS SDK开发快速入门

    2018-11-08 16:16:32
    文档使用静态库(.a)文件说明开发流程(.a应该是初学者最先接触到,且应用比较广泛的一种静态库,如果你还没有决定那种库来开发,使用a库永远不是个错误的选择); 入门案例,所以文档中包含较多(详细)截图。 ...
  • 与H5开发不同的是,它使用JS桥接技术在运行时编译成各个平台的Native代码,其使用的技术Facebook的Flux技术。 其特点是: 使用JavaScript语言,由于JS被广泛地使用,所以RN也很容易被接受。 RN依赖JS的运行时...
  • 引子:有一个段子:女人爱找程序员当朋友,因为程序员话少钱多死得早。哇咔咔,哈哈哈。其实最开始听到这个词的时候我是...一定吧,像我和我的同学,都是话很多啊。但是经历过很多事的现在,再想想,发现事实的确如
  • Realm 可以轻松地移植到您的项目当中,并且绝大部分常用的功能(比如说插入、查询等等)都可以一行简单的代码轻松完成! Realm 并不是对 Core Data 的简单封装,相反地, Realm 并是基于 Core Data ,也不是...
1 2 3 4
收藏数 71
精华内容 28