美文网首页
小明学Swift-01-基础篇

小明学Swift-01-基础篇

作者: TYM | 来源:发表于2015-10-20 15:22 被阅读170次

简介

Swift是苹果公司推出的可用于开发Mac OS和iOS系统上的应用的专用编程语言,它相比于Objective-C(以下简称OC)语言,更加严谨,是一种强语言。


使用工具

首先,先介绍使用的工具,毕竟一个方便的工具可以大大提高效率,而这里学习Swift最快速地工具就是playground


1

playground 游乐场,可以立刻获得编译后的效果


快速入门

  • 创建对象
  • OC
      [[UIView alloc] initWithXXX:];
    
  • Swift
    UIView(xxx)
    
2
  • 调用方法
    • OC
        [UIColor redColor]
      
  • Swift
      UIColor.redColor
    
  • 枚举
    • OC
        UIButtonTypeContactAdd
      
    • Swift
        UIButtonType.ContactAdd
      

输出

  • OC NSLog(@"Hellow World");
  • Swift print("Hellow World");

常量变量

  • OC
    • 变量 int a = 20;
    • 常量 const int a = 20
  • Swift
    • 在Swift语言中,所有的类型的第一个字母均是大写,Int,Double...
    • 变量 - var
  var a1:Int = 20
  • 常量 - let
let a1:Int = 20
3
  • 快捷键: 按住option,点击,可以查看他的信息


    4
  • 数据类型

    • OC中的数据类型首字母变成大写,就是Swift中的数据类型
  • 注意点:

    • 在Swift开发中,一般情况下应该先用let,只要在需要修改数据时才改用var,使用let的好处是,避免数据被修改,可以保证数据安全性
  • 类型推断

    • Swift中如果在定义变量/常量时进行初始化, 那么数据类型可以不用写, 系统会自动根据右边的复制推导出变量/常量的类型
    • Swift开发中能不写数据类型就不写数据类型, 尽量使用编译器的自动推导
    • 只有当我们需要明确的指定数据的长度, 获取需要先定义再初始化时才明确的指定数据类型
    • 使用自动类型推导好处: 大大降低代码中的冗余代码
    • 指定类型 let num:Int = 20
    • 自动推导 let num = 20
5
  • 类型转换:
    • OC中有显示转换和隐式转换 double value = 10.1 + 9
    • Swift中只有显示转换没有隐式转换, 也就是说只有相同类型的数据才能进行赋值和计算

元组

  • 复合数据类型
  • 只要将多个相同或者不同的数据用()括起来就是元祖
  • 优点: 在以前没有元祖之前C和OC语言是通过传入指针或者返回结构体的方式来返回多个值的, 而有了元祖之后就可以实现让一个函数返回多个值
let number1:(Int,Double,CGFloat,NSInteger) = (1,1.1,1.11,2)
number1.0
number1.1
number1.2
number1.3
// 给元组的元素起名
/*
元祖的其它定义方式:指明应用元祖元素的名称
*/
let person = (name:"tym", age:18, score:100.0)
person.name
person.age
person.score
// 提取元组的数据
/*
元祖的其它定义方式:
通过指定的名称提取元祖对应的值, 会将对应位置的值 赋值给对应位置的名称
*/
let (name, age, score) = ("tym", 18, 100.0)
name
age
score
/*
如果不关心元祖中的某个值可以利用_通配符来忽略提取
*/
let (name1 , age1 , _) =  ("tym", 18, 99.8)
print(name1)
print(age1)

分支

  • Bool 类型

    • C 和OC并没真正的Bool类型,非0即真
      • OC语言的Bool类型YES/NO是typedef signed char BOOL;
    • Swift引入了真正的Bool类型
      • Swift中没有C和OC中非零即真的概念
      • Swfit中逻辑值只有两个true/false
  • if语句

    • Swift
      • 大部分用法和OC中一致
      • Swift中条件语句可以不用写()
      • OC中如果if后面只有一条语句, 那么{}可以省略, 但是Swift不行
      • OC中条件语句可以是任何数值, OC中非0即真, YES/NO
      • Swift中条件语句的取值必须Bool类型, 也就是说Swift中提供了真正的Bool类型, true/false
let number = 10
//if number = 10 // Swift有效的避免了这种问题
if number == 10
{
    print(number)
}
  • 三目运算符
    • 大部分用法和OC一样
    • 条件表达式只能是Bool值
print(age >= 18 ? "开网卡":"回家")
  • switch语句
    • 大部分用法和OC一样
    • Swift中条件语句可以不用写()
    • OCdefault可以省略, 而Swift中大部分情况不能省略,而且default只能够放在最后面的位置
    • OC中default的位置可以随便写, 而Swift不可以
    • OC中每个case后面必须加上break, 否则会出现穿透, 而Swift不会穿透, 也就是说不用写break
    • OC中要在case中间定义变量必须加上{}, 否则作用域混乱, 而Swift不用
    • Swift可以判断对象类型,区间和元祖,OC只可以判断整数
let score = 100
switch score
{
case 59:
    print("不及格")
case 100:
    print("满分")
default:
    print("Other")
}

var rank = "A"
switch rank{
    case "A": //相当于if
        print("优")
    case "B": // 相当于else if
        print("优")
    case "C": // 相当于else if
        print("优")
    default: // 相当于else
        print("没有评级")
}

/*
因为不能穿透所以不能这么写
var rank1 = "A"
switch rank1{
    case "A":
    case "B":
        print("优")
    case "C":
        print("优")
    default:
        print("没有评级")
}
*/

//只能这么写
var rank1 = "A"
switch rank1{
    case "A", "B": // 注意OC不能这样写
        print("优")
    case "C":
        print("差")
    default:
        print("没有评级")
}
  • 区间
    • 闭区间: 0...10 , 取值范围0~10,包含头包含尾
    • 半闭区间: 0..<10 , 取值范围0~9,包含头不包含尾
switch score
{
case 0..<60:  // 0 ~ 59
    print("不及格")
case 60..<80:  // 60 ~ 79
    print("良好")
case 80..<100: // 80 ~ 99
    print("优秀")
default:
    print("满分")
}
// 判断元组
let point = (100, 50)
switch point
{
case (0,0):
    print("原点")
case (50,50):
    print("中点")
case (100,100):
    print("右下角")
default:
    print("Other")
}

// 值绑定
var point = (1, 10)
switch point{
    case (var x, 10): // 会将point中X的值赋值给X
        print("x= \(x)")
    case (var x, var y): // 会将point中X,Y的值赋值给X,Y
        print("x= \(x) y= \(y)")
    case var( x, y):
        print("x= \(x) y= \(y)")
    default:
        print("Other")
}

// 根据条件绑定
var point = (100, 10)
switch point{
    // 只有where后面的条件表达式为真才赋值并执行case后的语句
    case var(x, y) where x > y: 
        print("x= \(x) y= \(y)")
    default:
        print("Other")
}

可选类型

  • 可选类型
    • 一个变量可以有值可以没有值, 我们就称之为可选类型
    • 在Swift中如果使用一个可选类型的变量/常量, 必须解包操作
      • 解包: 只需要在变量/常量后面加上 !
      • !含义: 代表告诉系统该变量/常量中一定有值, 如果强制解包一个没有值的常量/变量,那么会报错
    • 优点: 提高代码阅读性
    • 格式:
      • 修饰符 变量名称:Optional<数据类型>
      • 修饰符 变量名称: 数据类型?
    • 语法糖: 因为在Swift中可选类型用得非常非常多, 所以为了简化代码, Swift提供了一个语法糖, 可以用? 代替 Optional<数据类型>
Snip20151018_11.png
7
  • 注意:
    • 在开发中一般情况下尽量不要强制解包一个可选类型, 否则会引发错误
    • 可选绑定: 为了更安全的解析可选类型的值, 一般情况下使用可选绑定
      • 如果没有值就不会做任何操作, 如果有值返回true并将optValue的值赋值给result执行大括号中的内容
/*
// 这样不严谨
let url = NSURL(string: "http://www.hao123.com/")
print(url)
let request = NSURLRequest(URL: url!)
*/

let url = NSURL(string: "http://www.hao123.com")
print(url)
if url != nil
{
    let request = NSURLRequest(URL: url!)
}

// 可选绑定: 如果url不为nil, 系统内部就会自动将解包之后的值赋值给temp, 并且只有temp有值时才会执行{}中的代码
// Swift开发中推荐这种写法
if let temp = url
{
    let request = NSURLRequest(URL: temp)
}

循环语句

  • for循环
    • 传统的for
/*:
传统for
* 基本用法和OC一致
* for后面的()可以省略
* for后面的{}不可用省略
* Swift开发中不建议使用传统for循环
*/
for var i = 0; i < 10; i++
{
    print(i)
}
// 一直循环
//for ;;
//{
//    print("---")
//}
  • 推荐的for循环形式
// Swift开发者中推荐的for循环格式
for i in 0..<10
{
    print(i)
}
  • while 循环
    • 基本用法和OC一致
var number = 0
while number < 10
{
    print(number)
    number++
}
  • do-while 循环
    • 基本用法和OC一致
    • Swift2.0开始dowhile循环中没有do, 只有repeat, 因为do被作用异常处理
var index = 0
repeat{
    print(index)
    index++
}while index < 10

数组

  • 格式 var arr: Array<Int> / var arr: [Int]
  • 可变和不可变 var/let
// 1.遍历数组(取值)
arr[0]
for item in arr
{
    print(item)
}
// 2.添加
arr.append(3)

// 3.修改
arr[1] = 9

// 4.删除
arr.removeAtIndex(0)

// 5.合并
var arr1 = [3, 5, 7]
arr += arr1

// 6.Swift特殊
for item in arr[0..<2] // 0~1
{
    print(item)
}

//arr.removeRange(Range(start: 0, end: 2))
//arr

// 通过观察可以发现Range其实就是一个半闭区间
arr.removeRange(0..<2)
arr

arr += arr1[0..<2]

字典

  • 格式 var dict: Dictionary<String, String>
  • 注意: 将OC的{}换成了[]
  • 可变和不可变 var/let
var dictTest: Dictionary<String,String>
var dictTest2: [String: String]

var dict = ["name":"tym", "age":"18"]

// 企业开发中字典使用的最多的类型就是 [String: NSObject] 类型
var dict2 = ["name":"tym", "age":"18", "score":99.99]

// 取值
dict2["age"]

// 修改
dict2["age"] = 20
dict2

// 增加
dict2["rank"] = 10
dict2

// 删除
dict2.removeValueForKey("name")
dict2
// removeValueForKey返回一个可选类型, 如果字典中不存在需要删除的key, 那么返回nil并且不会执行任何操作, 如果存在则删除key对应的值, 并且返回被删除的值
var dict14 = ["name":"lnj", "age":30]
if let orignal = dict14.removeValueForKey("names")
{
    print(dict14)
    print(orignal)
}
print(dict14)

var dict15 = ["name":"lnj", "age":30]
dict15.removeAll(keepCapacity: true)

// 遍历
var dict17 = ["name":"lnj", "age":30]
for key in dict17.keys
{
    print("key = \(key)")
}

var dict18 = ["name":"lnj", "age":30]
for value in dict18.values
{
    print("value = \(value)")
}
// Swift写法
// 系统会自动将字典中的key赋值给元祖中的第一个遍历, 会自动将字典中的value赋值给元祖中的第二个遍历
for (key,object) in dict2
{
    print(key)
    print(object)
}

// 合并
var dict3 = ["name":"tym", "sex":"M", "height":179.9]
var dict4 = ["weight":120, "score":100.0]
for (key,value) in dict4
{
    dict3[key] = value
}
dict3

字符串

  • OC的字符串是NSString, Swift的字符串String
  • OC的字符串是一个对象, Swift字符串是一个结构体, 效率更高
  • OC中的字符串是一个\0结尾, Swift字符串不是以\0结尾
  • Swift中的字符串支持遍历
let str = "Hi, \0 Tym"

// 遍历字符串
for c in str.characters
{
    print(c)
}

// 字符串拼接
var str2 = "Hello,World!"
str2 += str

// 字符串格式化
let name = "tym"
let age = 18
let res = "name: \(name) , age: \(age)"

// 2015-10-19 13:55
let str3 = String(format: "%d-%02d-%02d %02d:%02d", arguments: [2015,10,19,13,55])

// 截取字符串
// 提示: 在Swift开发中, 我们经常需要将Swift的字符串转换为OC的字符串来操作, 并且Swift自身也意识到了这一点, 所以在OC字符串和Swift的字符串之间转换相当简单
let str4 = "ttyymm"
let str5: NSString = str4
str5.substringToIndex(4)
str5.substringWithRange(NSMakeRange(0, 1))

// 计算字符串长度
var stringValue = "abc李"
print(stringValue.lengthOfBytesUsingEncoding(NSUTF8StringEncoding))
// 打印结果6, 和C语言一样计算字节数

// as 就是把什么当做什么
(str4 as NSString).substringFromIndex(2)

函数

  • 格式
func 函数名称(形参列表) ->返回值类型
{
        代码
}```
* Void == ()

```objc
// 1.没有参数没有返回值,没有返回值时可不写返回值
func say() -> Void
{
    print("Hi!")
}
func say1() -> ()
{
    print("Hi!")
}
say1()
func say2()
{
    print("Hi!")
}
say2()

// 2.有参数没有返回值
// Swift2.0开始, 会自动将形参列表的第二个参数名称作为标签
// Swift2.0之前是没有这个特性的, 在Swift2.0之前如果需要显示标签需要在形参名称前面加上#
func sum(num1:Int, num2:Int)
{
    print(num1 + num2)
}
sum(10, num2: 20)

// 3.没有参数有返回值
func getNumber() -> Int
{
    return 998
}
getNumber()

// 4.有参数有返回值
func sum2(num1:Int, num2:Int) -> Int
{
    return num1 + num2
}
print(sum2(11, num2: 22))
  • 内部和外部参数
    • 默认情况下所有形参都是内部参数, 也就是说只能在函数内部使用
    • 从Swift2.0开始会自动将形参列表的第二个参数名称作为标签, 也就是说从第二个参数开始, 参数的名称既是内部参数又是外部参数
    • 如何指定外部参数? 在方法中的参数的前面加上外部参数名
// 这里的yy就是外部参数
func sum3(num1:Int, yy num2:Int)
{
    print("num1: \(num1), num2: \(num2)")
}
//sum3(100, num2: 200)
sum3(100, yy: 300)
  • 默认参数
    • 如果指定了默认值, 那么在调用方法的时候就可以不用传递数据, 如果不传递数据系统就会使用默认值, 如果传递了就会使用传递的值
    • 在其它语言里面, 默认值一般情况只能是最后一个参数, 但是Swift可以写在任何位置
    • 构造方法中,不能设置默认参数
func joinSting(str1: String, str2: String = "是", str3: String) -> String
{
    return str1 + str2 + str3
}
joinSting("tym", str2: "不是", str3: "帅哥")
joinSting("tym", str3: "帅哥")
  • 常量参数、变量参数以及inout参数
    • 默认情况下所有形参都是常量参数, 不能在函数中修改形参的值
    • 如果想在函数中修改形参的值, 那么必须把形参变为变量参数
    • 和OC一样, 在函数中修改形参的值不会影响到外面实参的值
    • 如果想在函数中修改形参之后影响实参, 那么必须把形参变为inout参数
//func swap(a: Int, b: Int)
//{
//    let temp = a
//    a = b      // 不能修改常量
//    b = temp
//}
//func swap(var a: Int,var b: Int)
//{
//    let temp = a
//    a = b
//    b = temp
//    print("a = \(a), b = \(b)")
//}
//var a = 23
//var b = 24
//swap(&a, &b)
//
func swap1(inout a: Int,inout b: Int)
{
    let temp = a
    a = b
    b = temp
    print("a = \(a), b = \(b)")
}
var a1 = 23
var b1 = 24
print("a = \(a1), b = \(b1)")
swap1(&a1, b: &b1)
print("a = \(a1), b = \(b1)")
  • 可变参数
    • 只要参数是可变参数, 就可以传递一个多个
    • 在其它语言中一般情况下可变参数只能是最后一个形参, 而Swift中可以写在任意位置, 但是为了提高代码的阅读性, 还是建议写在最后
func sum4(numbs:Int..., temp:Int , temp2: Int) -> Int
{
    var sum = 0
    for i in numbs
    {
        sum += i
    }
    return sum + temp + temp2
}
sum4(3, temp: 10, temp2: 20)
  • 函数嵌套
    • 将一个函数写到另外一个函数的函数体中, 外面称之为函数嵌套
      • 1.被嵌套的函数只能在父函数内部访问
      • 2.被嵌套的函数可以访问外部的变量
    • 应用场景: 两个函数之间依赖较强, 或者一个函数就只给另外一个函数使用
      • 例如: 对数组排序是一个函数, 交换变量又是一个函数, 他们就可以使用函数嵌套
let value = 23
func test(inout a:Int)
{
    let number = 10
    func demo()
    {
        print("\(number)", "\(a)", "\(value)")
    }
    demo()
}
var tes = 110
test(&tes)

构造函数

  • 当重写一个类的构造方法时,这个类会暗自帮我们调用super.init()
  • 定义属性,直接写在class里面
    • 必须给这个类中所有的属性进行初始化
    • 如果不能在创建对象时给这个类中所有的属性进行初始化,那么这些属性必须是可选的(?)
  • 注意:
    • 如果自定义一个类, 并且没有重写构造方法, 那么系统会提供默认的构造方法
    • 如果自定义一个类, 并且自定义了构造方法, 并且没有重写原始的构造方法,那么系统不会提供默认的构造方法
      • 如果还需要原来的构造方法,需要重写该构造方法(尽管里面什么都不处理)
  • Swift中要求在创建一个类时必须给这个类中所有的属性进行初始化
    • 如果不能在创建对象时给这个类中所有的属性进行初始化, 那么这些属性必须可选的
    • 如果已经在构造方法中对所有的属性进行了初始化, 那么这些属性就可以不是可选类型
    • 在给某一个类指定属性的数据类型时, 如果该属性是对象类型, 那么可以指定为可选类型
    • 如果该属性不是对象类型而是基本数据类型, 那么建议直接赋值为0
      • 如果属性是基本数据类型, 并且是可选类型, 系统不会自动分配存储空间,在KVC的时候会出现问题
var name: String?
var age: Int = 0
    
    // 重写构造方法
    override init() {
        // 注意: 在构造方法中必须先初始化本类再初始化父类
        name = "tym"
        age = 18
        // 当我们重写一个类的构造方法时, 系统内部会悄悄得帮我们调用super.init()
        super.init()
    }
    
    // 自定义构造方法
    init(name: String, age: Int) {
        self.name = name
        self.age = age
        // 以下这句代码,能不写就不写
//        super.init()
    }
    
    init(dict: [String: NSObject]) {
        // 注意:Swift中如果想在构造方法中使用KVC转换模型, 必须先调用 super.init()
        // 调用 super.init()的目的主要是为了给对象分配存储空间
        super.init()
        setValuesForKeysWithDictionary(dict)
    }
    // Swift中打印对象,会调用以下属性,重写此属性,方便测试
    override var description: String {
//        return "name:\(name), age:\(age)"
        let keys = ["name","age"]
        let dict = dictionaryWithValuesForKeys(keys)
        return "\(dict)"
    }

setter、getter方法

  • OC
    • setXXX
    • getXXX
  • Swift
    • willSet、didSet
    • get
      • 如果只是想重写一个属性的get方法,可以直接return
var name: String?
        {
            // 在Swift开发中用以下两个方法代替OC中的重写setter方法
            willSet{
                print("赋值之前的调用\(newValue)")
            }
            didSet{
                print("赋值之后的调用\(oldValue)")
            }
    }
    
    var age: Int
        {
            // 在Swift中如果只重写了get方法, 那么该属性就是一个只读属性readOnly
            // 如果一个属性只重写了get方法, 我们也称之为"计算型属性", 计算型属性是不具备存储能力的
//            get{
//                return 110
//            }
            
            // 如果只是想重写一个属性的get方法, 那么可以简写
            return 120
    }

闭包

  • OC
    • block类似于匿名函数,用于封装代码块,在特定的时候执行一些耗时操作
    • 类型格式:返回类型 (^block名字)(参数列表)
    • 值格式: ^(形参列表){
      需要执行的代码
      }

<returnType>(^<blockName>)(<parameterTypes>) = ^(<parameters>) {
<statements>
};


```objc
@implementation ViewController

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [self loadData:^{
        NSLog(@"刷新UI");
    }];
}

-(void)loadData:(void (^)())finishBlock {
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"%@",[NSThread currentThread]);
        NSLog(@"加载数据");
        
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"%@",[NSThread currentThread]);
            finishBlock();
        });
    });
}

@end
  • Swift
    • 闭包是用于定义函数(Swift中函数就是闭包,闭包是一个特殊的函数),执行一些耗时操作
    • 类型格式:(形参列表)->返回值类型
    • 值格式:
      {
      (形参列表)->返回类型
      in
      需要执行的代码
      }
class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        loadData ({ () -> () in
            print("刷新UI")
        })
    }
    
    func loadData(finish:()->()) {
        dispatch_async(dispatch_get_global_queue(0, 0)) { () -> Void in
            print(NSThread.currentThread())
            print("更新数据")
            
            dispatch_async(dispatch_get_main_queue(), { () -> Void in
                print(NSThread.currentThread())
                finish()
            })
        }
    }
}
  • 闭包的写法
    • 完整写法

loadData ({ () -> () in
print("更新UI")
})

+ 如果闭包`没有形参`, 那么in和in之前的代码都可以省略
```objc
loadData ({ 
          print("更新UI")
      })
  • 如果闭包是函数的最后一个参数, 那么闭包可以写在函数()的后面
loadData ( ){ () -> () in
          print("更新UI")
      }
  • 如果函数只有一个闭包参数, 那么函数的()可以省略
loadData {
          print("更新UI")
      }
  • 闭包的循环引用问题
    • OC
      • __weak : 如果对象释放, 会自动设置为nil
      • __unsafe_unretained: 如果对象释放, 不会自动设置为nil
    __weak typeof(self) weakSelf = self
    
    • Swift
      • 对应关系: _weak == weak , _unsafe_unretained == unowned
      weak var weakSelf = self
      loadData { () -> () in
              print("刷新UI")
              weakSelf!.view.backgroundColor = UIColor.greenColor()
          }
      
      // 不建议此方法,因为强制解包了
      loadData { [weak self] () -> () in
              print("刷新UI")
              self!.view.backgroundColor = UIColor.greenColor()
          }
      

// 因为unowned相当于_unsafe_unretained,不会设置成nil,所有不用强制解包
loadData { [unowned self] () -> () in
print("刷新UI")
self.view.backgroundColor = UIColor.greenColor()
}
```

  • 单例

    • OC
     @interface Dog : NSObject
        + (instancetype)sharedDog;
     @end
      @implemetion Dog
        +(instancetype)sharedDog {
            static Dog *_instance = nil;
            // onceToken默认等于0, 只要执行一次之后就不等于0了, 原理是通过判断onceToken是否等于0决定是否需要执行block
            static dispatch_once_t onceToken;
            NSLog(@"%ld",onceToken);
            dispatch_once(&onceToken, ^{
                _instance = [[self alloc] init];
            });
            return _instance;
      }
    
    • Swift
      • 注意:在func前添加class标记,相当于是类方法,不添加,相当于是对象方法
      // 方法一
      static var onceToken:dispatch_once_t = 0;
      static var _instance:Dog?
      class func sharedDog() -> Dog {
          print(onceToken)
          dispatch_once(&Dog.onceToken) {
              _instance = Dog()
          }
          return _instance!
      }
    
      // 方法二
      // 因为是常量,所以只能赋值一次
      static let _instance:Dog = Dog()
      class func sharedDog()->Dog {
          return _instance
      } 
    
      // 方法三,强烈推荐的方法
      // 而且苹果有统一的命名规范, 但凡是单例统一是shareInstance
      static let shareInstance:Dog = Dog()
    

懒加载

  • 延迟存储属性
    • Swift语言中所有存储属性必须有初始值, 也就是当构造完一个对象后, 对象中所有的存储属性必须有初始值, 但是也有例外, 其中延迟存储属性可以将属性的初始化推迟到该属性第一次被调用的时候
  • 懒加载应用场景:
    • 1.有可能不会用到
    • 2.依赖于其它值
  • 格式:
    • lazy var 变量: 类型 = { 创建变量代码 }()
    • 懒加载的写法本质上是定义并执行一个闭包
    lazy var demoView: UIView = { 
        let v = UIView(frame: CGRectMake(10, 10, 100, 100)) 
        v.backgroundColor = UIColor.redColor() return v
    }()

gurad

  • �苹果公司意识到Swift编写的代码,会不知不觉得多层嵌套,然后代码变得非常丑陋,所以在Swift2.0的时候,专门推出了一个条件语句guard
  • gurad 专门守护安全的
  • 格式:
guard 条件语句 else {
需要执行的语句
return
}```
- 特点:只有条件为假的时候,才会执行else中的代码,相对于if else,这个只有else
- 作用: 用于过滤数据

---

# private
- 在Swift中,添加一个属性或者方法可以在其他项目中的文件访问
- 为了封装性,可以添加private在属性或者方法或者类前,可以让该属性或者方法只能在`当前`文件中访问
- 注意:
  + 由于点击事件是由NSRunLoop发起的,并不是当前的类发起的,如果在点击方法前添加private,那么NSRunLoop无法找到该方法,会导致崩溃
  + OC是基于运行时动态派发事件的
  + Swift是编译时就已经确定了方法

---

# @objc
- 想给监听点击事件的方法加上private,并且又想让系统动态派发时找到该方法,可以在该方法前加上@objc,@objc就能让这个方法支持动态派发

```objc
@objc private func composeBtnClick()
{
}

便利构造方法

  • 在Swift开发中,如果想要快速创建一个对象,那么可以提供一个便利构造器(遍历构造方法)
  • 在普通构造方法前面加上一个convenience,那么这个构造方法就是一个便利构造方法
  • 注意:
    • 如果定义一个便利构造器,那么必须在便利构造方法中调用指定构造方法(没有convenience单词的构造方法)
// 以下方式的确可以快速创建一个对象,但是Swift不是这种风格
    
    class func createBtn(image:String, backgroundImage:String)->UIButton
    {
        let btn = UIButton(type: UIButtonType.Custom)
        btn.setImage(UIImage(named: image), forState: UIControlState.Normal)
        btn.setImage(UIImage(named: image + "_highlighted"), forState: UIControlState.Highlighted)
        btn.setBackgroundImage(UIImage(named: backgroundImage), forState: UIControlState.Normal)
        btn.setBackgroundImage(UIImage(named: backgroundImage + "_highlighted"), forState: UIControlState.Highlighted)
        
        btn.sizeToFit()
        
        return btn
    }


/*
    定义便利构造器步骤:
    1.编写一个构造方法
    2.在构造方法前面加上 convenience
    3.在构造方法中调用当前类的其他"非便利构造器"初始化对象
    */
    convenience init(imageName: String, backImageName: String)
    {
        self.init()
        
        // 1.设置背景图片
        setBackgroundImage(UIImage(named: imageName), forState: UIControlState.Normal)
        setBackgroundImage(UIImage(named: imageName + "highlighted"), forState: UIControlState.Highlighted)
        
        // 2.设置普通图片
        setImage(UIImage(named:backImageName), forState: UIControlState.Normal)
        setImage(UIImage(named: backImageName + "highlighted"), forState: UIControlState.Highlighted)
        
        sizeToFit()
    }

相关文章

网友评论

      本文标题:小明学Swift-01-基础篇

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