swift基本语法

一 可选类型知识点补充

1 例一 : 强转并且制定类型
let str = "23"  //打印结果: "23"
let age : Int? = Int(str) //打印结果 :23
—-> 1.1 问题 : 该例子转化的结果为什么需要用可选类型来接收?
—-> 1.2 解答 : 因为很有可能是转化不成功的,如果此时不用可选类型来接收的话,万一转化失败,那么该值就为空(nil),如果不选择可选类型来接收,程序会崩溃.
2 例二 : 获取某个plist文件的路径
let path : String? = NSBundle.mainBundle().pathForResource("xiaofeng.plist", ofType: nil) //打印的结果为nil,因为写程序的时候并没有新建一个名字为"xiaofeng"的plist文件
if let path = path {
    NSArray(contentsOfFile: path)
}
—-> 2.1 这里同样需要用可选类型来接收,原因是很有可能找不到名字为”xiaofeng”的plist文件,如果此时不用可选类型来接收,值为nil,程序会崩溃.
—-> 2.2 在此句后面写一个判断语句更加安全的判断是否可以取成功.判断的好处如下:
—> 2.2.1 判断path是否有值,如果没有值的话,就不执行{}中的内容
—> 2.2.2 如果path有值,那么系统就会对path进行解包,并且将解包的结果赋值
3 例三 : 获取一个NSURL
let url : NSURL? = NSURL(string: "www.baidu.com") //打印结果:www.baidu.com
if let url = url {
    NSURLRequest(URL : url) //<NSURLRequest: 0x7fd050d18610> { URL: www.baidu.com }
}
—-> 3.1 如果不加判断或者将获取到的值不用可选类型来接收的话,那么当url是下面这种类型,就获取不到.不用选类型来接收是会报错的.
//url中出现了中文,并且没有用可选类型来接收值,系统会报错
//系统包的错误: cannot convert value of type 'NSURL?' to specified type 'String'
let url : String = NSURL(string: "www.baidu.com/百度")
—-> 3.2 如果用if做出了判断,此时能更加安全的对url进行操作,判断url是否获取成功,成功的话就将url解包.
4 例三 : 在保证一个可选类型一定有值的前提下,可以直接强制解包
—-> 4.1 如果此时的123.plist文件存在的话,就可以强制解包(通过按住option点击path1可以看出,path1的类型是可选类型)
let path1 = NSBundle.mainBundle().pathForResource("123.plist", ofType: nil)

二 is; as?; as!的用法

1 is : 用来判断某种类型是不是另外一种类型(用法比较简单)
let array = [12,"xiaofeng",1.89]
let arrayM = [NSObject]()//定义数组,内部的元素是NSObject类型
//判断取出的第一个元素是不是整型
if let firstObject = array.first {
    if firstObject is Int {
        print("是Int类型")    //打印结果:"是Int类型\n"
    }else{
        print("不是Int类型")
    }
}
2 as? : 转成的最终类型是一个可选类型(需要作出判断)
let dict = ["name" : "xiaofeng", "age" : 20, "height" : 1.88]
let value = dict["name"] //通过按住option点击value,可以看出类型为可选类型
//将NSObject转成String类型
if let value = value {
    //此处value as? String也有可能转失败
    let valueStr : String? = value as? String
    //判断是否能转成功
    if let valueStr = valueStr {
        let info = "my name is " + valueStr //最终结果:"my name is xiaofeng"
    }
}
—-> 2.1 简便写法判断NSObject? 转 String
if let valueStr = value as? String {
    let info = "my name is " + valueStr //打印结果 :"my name is xiaofeng"
}
3 as! : 转成的最终类型就是具体的类型(NSObject? 转成 String)
—-> 3.1 此方法的后果: 如果用这种方法转化不成功,那么程序会直接崩溃
let info = "my name is " + (value as! String) //打印结果 :"my name is xiaofeng"

三 swift中的函数

1 oc中的方法
有参数有返回值
- (CGFloat)sum:(CGFloat)num1 num2:(CGFloat)num2;
有参数没有返回值
- (void)sum1:(CGFloat)num1 num2:(CGFloat)num2;
没有参数有返回值
- (CGFloat)sum2;
没有参数没有返回值
- (void)sum3;
2 swift中的函数相当于oc中的方法(格式如下)
func 函数名(参数列表) -> 返回值类型 {
    代码块
    return 返回值
}
—-> 2.1 func是关键字,多个参数列表之间可以用逗号(,)分隔,也可以没有参数
—-> 2.2 使用箭头“->”指向返回值类型
—-> 2.3 如果函数没有返回值,返回值为Void.并且“-> 返回值类型”部分可以省略
3 常见的函数类型
—-> 3.1 有参数有返回值
func sum (num1 : Int , num2 : Int) ->Int {
    return num1 + num2
}
let result = sum(10, num2: 10)
print("计算的结果是:\(result)")  //打印结果 : "计算的结果是:20\n"
—-> 3.2 有参数没有返回值
func minus (num1 : Double , num2 : Double) {
    print(num1 - num2)   //打印出来的结果 : "2.0\n"
}
minus(22.1, num2: 20.1)
—-> 3.3 没有参数有返回值
func multiply() ->Int {
    return 10   //返回结果 : 10
}
multiply()
—-> 3.4 没有参数没有返回值
func divide() {
}
divide()
—-> 3.5 有参数有多个返回值(元组)
—-3.5.1 计算一个数组中奇数和偶数的个数?
* 普通写法:
let array = [11,22,44,33,66,88]
var oddCount = 0 //奇数
var evenCount = 0 //偶数
for num in array {
    if num % 2 == 0 {
        evenCount++  //打印结果 : 4
    } else {
        oddCount++  //打印结果 : 2
    }
}
* 利用元组特性作为多个返回值
let nums = [11,22,33,44,55,7,77,88]

func getCount (nums : [Int]) ->(Int,Int) {
    var evenCount = 0 //偶数
    var oddCount = 0 //奇数
    for num in nums {
        if num % 2 == 0 {
            evenCount++    //打印结果 : 3
        }else {
            oddCount++    //打印结果 : 5
        }
    }
    return (evenCount,oddCount)
}
let count = getCount(nums)
print("偶数的个数是:\(count.0),奇数的个数是:\(count.1)")
4 内部参数和外部参数
—-> 4.1 含义: 内部参数: 在函数内部可以看到的参数,就是内部参数;外部参数: 在函数外面可以看到的参数,就是外部参数
func sum (num1 : Int , num2 : Int , num3 : Int) ->Int {
    print(num1)
    print(num2)
    print(num3)
    return num1 + num2 + num3   //返回结果 : 30
}
//调用
sum(10, num2: 10, num3: 10)
—-> 4.2 为什么上面代码在调用的时候,num1并没有显示出来,而是从num2开始显示的?
—-> 4.3 解答 : 默认情况下,从第二个参数开始,参数名称既是内部参数也是外部参数
—-> 4.4 如何让第一个参数也是外部参数?
—-> 4.5 解答 : 可以在第一个标识符前加上和该标识符同名的标识符
func multiply (num1 num1 : Int , num2 : Int , num3 : Int) ->Int {
    return num1 * num2 * num3  //返回结果 : 1000
}
multiply(num1: 10, num2: 10, num3: 10)
—-> 4.6 如何让外部参数不显示?
—-> 4.7 可以在参数名称前加下划线(_)
func subtraction (num1 : Int , _ num2 : Int , _ num3 : Int) ->Int {
    return num1 - num2 - num3   //返回结果 : 50
}
subtraction(100, 20, 30)
5 默认参数
—-> 5.1 含义 : 某些情况,如果没有传入具体的参数,可以使用默认参数(“蓝山”)
—-> 5.2 需求 : 刚进入公司作为新员工,老员工需要你帮他们泡咖啡,他们说了各自的咖啡需求,但是有一些人没有说,只说了随便,此时要你设计一个函数求出咖啡的种类?
func makeCoffee(coffeeName : String = "蓝山") ->String {
    return "制作了一杯:\(coffeeName)咖啡"
}
makeCoffee("拿铁")  //通过传入咖啡的名称,返回制作好的咖啡
makeCoffee()       //此时的调用函数,返回的结果是默认设置的"蓝山"咖啡
6 可变参数
—-> 6.1 含义与条件
—–> 6.1.1 swift中函数的参数个数可以变化,它可以接受不确定数量的输入类型参数
—–> 6.1.2 它们必须具有相同的类型
—–> 6.1.3 我们可以通过在参数类型名后面加入(…)的方式来指示这是可变参数
—-> 6.2 需求 : 第一天 老板要你通过函数计算两个数的相加;第二天 老板要你通过函数计算三个数的相加; 第三天 老板要你通过函数计算四个数的相加
//此时需要些三个方法来计算
func sum(num1 : Int , num2 : Int) ->Int {
    return num1 + num2
}
func sum(num1 : Int , num2 : Int , num3 : Int) ->Int {
    return num1 + num2 + num3
}
func sum(num1 : Int , num2 : Int , num3 : Int , num4 : Int) ->Int {
    return num1 + num2 + num3 + num4
}
sum(10, num2: 20, num3: 30, num4: 40)
—-> 6.3 使用可变参数进行改进
//计算参数为数组中的各个元素的和(方法一)
func arrayCount(nums : [Int]) ->Int {
    var result = 0
    for num in nums {
        result += num
    }
    return result
}
arrayCount([10,20,30,40])  //传入一个数组   打印结果是 : 100
//计算参数为数组中的各个元素的和(方法二)
func sunNums(nums : Int...) ->Int {
    var result = 0
    for num in nums {
        result += num
    }
    return result
}
sunNums(10,20,30,40)
7 引用类型(指针的传递)
—-> 7.1 默认情况下,函数的参数是值传递.如果想改变外面的变量,则需要传递变量的地址
—-> 7.2 必须是变量,因为需要在内部改变其值
—-> 7.3 Swift提供的inout关键字就可以实现
—-> 7.4 需求 : 用函数交换两个数的值
—–> 7.4.1 错误写法 :
var m = 20
var n = 30
func exchangeNum(var num1 : Int , var num2 : Int) {
    let tempNum = num1
    num1 = num2
    num2 = tempNum
}
exchangeNum(m, num2: n)
print("m :\(m), n: \(n)")    //打印出结果 : "m :20, n: 30\n"
—–> 7.4.2 正确写法 一: 运用指针进行交换(swift提供的关键字: inout)
var a = 20
var b = 30
func exchangeNum(inout num1 : Int , inout num2 : Int) {
    let tempNum = num1
    num1 = num2
    num2 = tempNum
}
exchangeNum(&a, num2: &b)
print("a : \(a) , b : \(b)")     //打印结果 : "a : 30 , b : 20\n"
—–> 7.4.3 特别写法 :
var c = 20
var d = 30
func exchangeNum( num1 : Int , num2 : Int) -> (Int , Int) {
    return (num2 ,num1)
}
let num = exchangeNum(c, num2: d)
c = num.0     //打印结果 : 30
d = num.1     //打印结果 : 20
8 函数的嵌套使用
—-> 8.1 在swift中函数是可以嵌套使用的(不推荐)
func test() {
    func demo() {
        print("demo")
    }
    demo()    //先打印:demo
    print("test")  //再打印:test
//    demo()    //如果在此处调用   先打印:test  再打印:demo
}
test()
9 函数的类型
—-> 9.1 定义两个函数
func add(a : Int , b : Int) ->Int {
    return a + b
}
func mul(a : Int , b : Int) ->Int {
    return a * b
}
—-> 9.2 写出函数的类型 (函数相当于一个值)
var a = add    //打印出函数的类型 : (Int, Int) -> Int
var a : (Int, Int) -> Int = add
a(20,30)    //打印结果 : 50
a = mul     //打印结果 : (Int, Int) -> Int
a(30,60)    //打印结果 : 1800
—-> 9.3 函数作为方法的参数
—–> 9.3.1 定义一个函数
var m : Int = 20
func test(num : Int) ->Int {
    return num
}
test(m)   //打印结果 : 20
test(30)  //打印结果 : 30
—–> 9.3.2 用第一个函数作为第二个函数的参数
func demo(funcName : (Int) ->Int) {
    funcName(20)
}
demo(test)
—–> 9.3.3 函数作为方法的返回值
func add(a : Int , b : Int) ->Int {
    return a + b
}
func demo1() ->((Int, Int) ->Int) {//返回值的类型必须是和返回函数同种类型
    return add
}
let tempFunc = demo1()
tempFunc(20,30)

四 枚举

1 OC中的枚举 : 指定相关名称为一组整型值
typedef enum {
    SexMan,  //默认为0
    SexWoMan //1
}Sex
2 swift中的枚举 : Swift 中的枚举更加灵活,不必给每一个枚举成员提供一个值.也可以提供一个值是字符串,一个字符,或是一个整型值或浮点值.
3 swift枚举的语法
enum SomeEnumeration {
// 属性(enumeration definition goes here)
}
4 定义swift中的枚举(并没有规定Man,WoMan的数值)
//单个值一行
enum Sex {
    case Man
    case WoMan
}
//多个值一行
enum Direction {
    case East,West,South,North
}
5 创建枚举具体类型
var sex = Sex.Man
sex = .WoMan
6 给枚举类型赋具体值
enum Planet : Int {
    case Mercury = 0, venus, Earth, Mars
}
enum Sex1 : Int {
    case Man = 0
    case WoMan = 1
}
enum Sex2 : String {
    case Man = "男"
    case WoMan = "女"
}
7 通过下面的方法来取出枚举中的属性(rawValue:)
let sex1 = Sex1(rawValue: 0)  //打印出结果 : Man
let sex2 = Sex1(rawValue: 1)  //打印出结果 : WoMan
let sex4 = Sex2(rawValue: "男")   //打印出结果 : Man
let sex5 = Sex2(rawValue: "女")   //打印出结果 : WoMan

五 结构体

1 结构体的具体使用
—-> 1.1 需求 : 判断两个点之间的距离是否大于某个数字?
—-> 1.2 传统做法
//1.定义中心点
let centerX : Double = 100
let centerY : Double = 100
//获取比较的点
let x : Double = 60
let y : Double = 50
let x1 : Double = 200
let y1 : Double = 150
//定义方法,用来比较两个点
func inRange(x : Double, y : Double) ->Bool {
    //获取两个点之间的距离
    let disX = x - centerX
    let disY = y - centerY
    //计算第三边的距离
    //pow(disX, 2)代表了disX的2次方;sqrt代表开方根
    let distance = sqrt(pow(disX, 2) + pow(disY, 2))
    //判断是否小于200
    return distance < 200    //打印结果 : true
}
inRange(60, y: 50)
—-> 1.3 使用结构体进行该进(优点) : 看上去比较直观,一眼就知道代表了点
//结构体定义
struct Location {
    var x : Double
    var y : Double
}
//通过结构体创建对应的点
let center = Location(x: 100, y: 100)
//需要判断的点
let testLocation = Location(x: 50, y: 40)
//定义函数
func inRang(location : Location) ->Bool {
    let disX = location.x - center.x
    let disY = location.y - center.y

    let distance = sqrt(pow(disX, 2) + pow(disY, 2))
    return distance < 200
}
//方法的调用
inRang(testLocation)
2 结构体扩充构造函数
—-> 2.1 swift规范 : 在实例化任何一个类或者结构体时,必须保证类/结构体所有(存储)属性,都必须被初始化.
—-> 2.2 如果自定义了构造函数,那么会覆盖系统提供的构造函数.如果希望保留原来的构造函数,那么必须明确的将系统提供的构造函数进行重写
struct Location {
    var x : Double = 0
    var y : Double = 0
    var z : Double = 0
    //init()是系统的构造方法
    init() {
    }
    //自定义构造方法
    init(x : Double, y : Double, z : Double) {
        self.x = x
        self.y = y
        self.z = z
    }
}
—-> 2.3 注意一 :如果没有自定义构造方法,是可以敲出下面的方法来
Location()
—-> 2.4 注意二 : 自定义了构造方法,同时重写了系统的构造方法是可以同时敲出下面的方法
Location()  //如果init()构造方法没有被重写,是无法敲出来的
//创建Location实例
let location = Location(x: 100, y: 100, z: 100)
—-> 2.5 注意三 : 系统的结构体除了可以通过make方法创建外,也可以直接结构体名称后面跟上()来创建
let point = CGPoint(x: 100, y: 100)
let size = CGSize(width: 100, height: 100)
let rect = CGRect(origin: point, size: size)
var rect1 = CGRect().origin.x
rect1 = 100
let rect2 = CGRect(x: 0, y: 0, width: 100, height: 100)
let range = NSRange(location: 3, length: 9)
3 结构体扩充函数
—-> 3.1 给结构体扩充方法,必须在func前加上Mutating
—-> 3.2 给自定义的结构体扩充函数
struct Location {
    var x : Double
    var y : Double
    //mutating少了是会报错的
    mutating func moveH(dis : Double) {
        x += dis
    }
    mutating func moveV(dis : Double) {
        y += dis
    }
}
var location = Location(x: 50, y: 60)
location.moveH(-100)
location.moveV(100)
print(location)   //打印出结果 : "Location(x: -50.0, y: 160.0)\n"
—-> 3.3 给系统的结构体扩充方法
extension CGPoint {
    mutating func moveH(dis : CGFloat) {
        x += dis
    }
    mutating func moveV(dis : CGFloat) {
        y += dis
    }
}
var point = CGPoint(x: 100, y: 100)
point.moveH(100)
print(point)   //打印出结果 : "(200.0, 100.0)\n"
—-> 3.4 给系统的类扩充方法(必须使用系统给的关键字:extension)
extension UIButton {
    func getTitle() ->String? {
        return titleLabel?.text
    }
}
let btn = UIButton()
btn.setTitle("按钮", forState: .Normal)
print(btn.getTitle())  //打印出结果 : "Optional("按钮")\n"

六 类

1 定义类
—-> 1.1 类的定义
class 类名 : SuperClass {
    // 定义属性和方法
}
—-> 1.2 注意 : (1)定义的类,可以没有父类.那么该类是rootClass (2)通常情况下,定义类时.继承自NSObject(非OC的NSObject)
2 类的属性
—-> 2.1 类的属性种类
—–> 2.1.1 存储属性:存储实例的常量和变量
—–> 2.1.2 计算属性:通过某种方式计算出来的属性
—–> 2.1.3 类属性:与整个类自身相关的属性
3 存储属性
class Person: NSObject {
    var name = ""
    var age = 0
    var mathScore = 0.0
    var chineseScroe = 0.0
}
//创建Person对象
let p = Person()
//给存储属性赋值
p.name = "xiaofeng"
p.age = 19
p.mathScore = 90
p.chineseScroe = 100
4 计算属性(本质是一个方法)
1> 计算属性并不存储实际的值,而是提供一个getter和一个可选的setter来间接获取和设置其它属性
2> 计算属性一般只提供getter方法
3> 如果只提供getter,而不提供setter,则该计算属性为只读属性,并且可以省略get{}
—-> 4.1 需求:计算一个学生的两门课程的平均成绩
class Person: NSObject {
    var name = ""
    var age = 0
    var mathScore = 0.0
    var chineseScroe = 0.0
    //计算属性(本质是一个方法)
    func getAverageScore() ->Double {
        return (mathScore + chineseScroe) * 0.5
    }
}
//创建Person对象
let p = Person()
//给存储属性赋值
p.name = "xiaofeng"
p.age = 19
p.mathScore = 90
p.chineseScroe = 100;
//调用方法
print(p.getAverageScore())  //打印结果 : "95.0\n"
—-> 4.2 计算属性的完整写法
 var averageScore : Double {
        get {
            return (mathScore + chineseScroe) * 0.5
        }
        set (newScore){
            chineseScroe = 2 * newScore - mathScore
        }
    }
—-> 4.3 计算属性常见写法
 var averageScore : Double {
        return (mathScore + chineseScroe) * 0.5
    }
5 类属性
—-> 5.1 类属性是与类相关联的,而不是与类的实例相关联
—-> 5.2 所有的类和实例都共有一份类属性.因此在某一处修改之后,该类属性就会被修改
—-> 5.3 类属性的设置和修改,需要通过类来完成
static var courseCount = 0
//设置课程个数
Person.courseCount = 3
//取出类属性的是
print(Person.courseCount)
6 类的构造函数
—-> 6.1 默认情况下,系统会给类提供一个最简单的构造函数 init()
—-> 6.2 创建出来一个对象,必须保证该对象内部所有的属性都有初始化值
—-> 6.3 如果自定义构造函数init(),会覆盖系统默认提供的init()构造函数,如果不希望覆盖,那么必须明确的实现init()构造函数
class Person {
    var name : String = ""
    var age : Int = 0
    //系统的构造函数
    init() {
    }
    //添加构造函数
    init(name : String, age : Int) {
        self.name = name
        self.age = age
    }
    //用字典添加
    init(dict : [String : NSObject]) {
        if let name = dict["name"] as? String {
            self.name = name
        }

        if let age = dict["age"] as? Int {
            self.age = age
        }
    }
}
—-> 6.4 创建对象
//2.创建类对象
let p = Person()//通过普通方法创建
//通过扩充的方法创建
let p1 = Person(dict: ["name" : "xiaofeng", "age" : 19])
7 类的字典转模型(KVC)
—-> 7.1 利用KVC字典转模型会更加方便
—-> 7.2 注意:
—–> 7.2.1 KVC并不能保证会给所有的属性赋值
—–> 7.2.2 因此属性需要有默认值
class Person : NSObject{
    var name : String = ""
    var age : Int = 0
    init(dict :[String : NSObject]) {
        //必须先初始化对象
        super.init()
        setValuesForKeysWithDictionary(dict)
    }
    //如果使用KVC的时候,发现模型属性值并不能一一对应,此时使用kvc是会报错的,但是重写下面这个方法可以避免系统报错
    override func setValue(value: AnyObject?, forUndefinedKey key: String) {
    }
}
let p = Person(dict: ["name" : "xiaofeng", "age" : 18])
print(p.name)    //打印结果 : "xiaofeng\n"
print(p.age)     //打印结果 : "18\n"
8 析构函数
—-> 8.1 Swift 会自动释放不再需要的实例以释放资源,类似于delloc
—-> 8.2 Swift 通过自动引用计数(ARC)处理实例的内存管理
—-> 8.3 当引用计数为0时,系统会自动调用析构函数(不可以手动调用)
—-> 8.4 通常在析构函数中释放一些资源(如移除通知等操作)
–> 1 析构函数写法
deinit {
    // 执行析构过程
}
–> 2 具体代码
class Person : NSObject {
    var name = ""
    var age = 0
    //用来释放一些没用的资源,类似于delloc
    deinit {
        print("Person -----deinit")    //打印结果 : "Person -----deinit\n"
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }
}

var p : Person? = Person()
p = nil      //此时将p赋值为nil,析构函数中的print会打印Person -----deinit
9 属性监听
—-> 9.1 在OC中我们可以重写set方法来监听属性的改变
—-> 9.2 Swift中可以通过属性观察者来监听和响应属性值的变化
—-> 9.3 通常是监听存储属性和类属性的改变.(对于计算属性,我们不需要定义属性观察者,因为我们可以在计算属性的setter中直接观察并响应这种值的变化)
—-> 9.4我们通过设置以下观察方法来定义观察者
—–> 9.4.1 willSet:在属性值被存储之前设置。此时新属性值作为一个常量参数被传入。该参数名默认为newValue,我们可以自己定义该参数名
—–> 9.4.2 didSet:在新属性值被存储后立即调用。与willSet相同,此时传入的是属性的旧值,默认参数名为oldValue
—–> 9.4.3 willSet与didSet只有在属性第一次被设置时才会调用,在初始化时,不会去调用这些监听方法
class Person: NSObject {
    //属性监听器name
    var name : String = "" {
        //监听属性即将发生改变
        willSet (new) {
        //在该方法中有一个默认的系统属性newValue,用于存储新值
            print(name)    //打印结果 : "\n"
            print(new)     //打印结果 : "xiaofeng\n"
        }
        //监听属性已经发生改变
        didSet (old){
        //在该方法中有一个默认的系统属性oldValue,用于存储旧值
            print(name)     //打印结果 : "xiaofeng\n"
            print(old)      //打印结果 : "\n"
        }
    }
    //属性监听器age
    var age : Int = 0 {
        //在willSet中有newValue,用于保存新值
        willSet (newAge) {
            print(age)
            print(newAge)
        }
        //在didSet中有oldSet,用于保存旧值
        didSet (oldAge) {
            print(age)
            print(oldAge)
        }
    }
}

//创建对象
let p = Person()
p.name = "xiaofeng"
p.age = 20

七 总结

1 该部分接上一篇swift基本语法部分,详细的讲解了函数,自定义构造方法,类部分的相关知识,里面写的并不是很全面,我已经尽可能的完善了,希望能帮到大家.
2 最后,我还会陆续的更新swift的相关知识,希望看到我博客的开发者,如果觉得我写的还行的话,麻烦大家支持我的博客,关注我的官方博客,谢谢!!!!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值