swift.4.0 归档

2016-10-12 23:19:44 aa31140105 阅读数 4870

1.对用户的模型数据(自定义类:HCUserModel)进行归档和解档

1.1 需要遵循NSCoding协议

1.2 需要实现func encode(with aCoder: NSCoder){}归档方法

1.3需要实现 required init(coder aDecoder: NSCoder){}解档方法

1.4 重写init方法

2.HCUserModel的数据内容如下:

import UIKit


class HCUserModel: NSObject,NSCoding {

    

    var id:Int?

    var nickname:String?

    var phone:String?

    var account:String?

    var password:String?

    var type:Int?

    var icon:String?

    var attentionnumber:Int?

    var registertime:String?

    var qrcode:String?

    var signature:String?

    var dynamicstruts:Int?

    var score:Int?

    

    // MARK:- 处理需要归档的字段

    func encode(with aCoder:NSCoder) {

        

        aCoder.encode(id, forKey:"id")

        aCoder.encode(nickname, forKey:"nickname")

        aCoder.encode(phone, forKey:"phone")

        aCoder.encode(account, forKey:"account")

        aCoder.encode(password, forKey:"password")

        aCoder.encode(type, forKey:"type")

        aCoder.encode(icon, forKey:"icon")

        aCoder.encode(attentionnumber, forKey:"attentionnumber")

        aCoder.encode(registertime, forKey:"registertime")

        aCoder.encode(qrcode, forKey:"qrcode")

        aCoder.encode(signature, forKey:"signature")

        aCoder.encode(dynamicstruts, forKey:"dynamicstruts")

        aCoder.encode(score, forKey:"score")

    }

    

    // MARK:- 处理需要解档的字段

    requiredinit(coder aDecoder:NSCoder) {

        super.init()

        id = aDecoder.decodeObject(forKey:"id")as?Int

        nickname = aDecoder.decodeObject(forKey:"nickname")as?String

        phone = aDecoder.decodeObject(forKey:"phone")as?String

        account = aDecoder.decodeObject(forKey:"account")as?String

        password = aDecoder.decodeObject(forKey:"password")as?String

        type = aDecoder.decodeObject(forKey:"type")as?Int

        icon = aDecoder.decodeObject(forKey:"icon")as?String

        attentionnumber = aDecoder.decodeObject(forKey:"attentionnumber")as? Int

        registertime = aDecoder.decodeObject(forKey:"registertime")as?String

        qrcode = aDecoder.decodeObject(forKey:"qrcode")as?String

        signature = aDecoder.decodeObject(forKey:"signature")as?String

        dynamicstruts = aDecoder.decodeObject(forKey:"dynamicstruts")as? Int

        score = aDecoder.decodeObject(forKey:"score")as?Int

    }

    overrideinit() {

        super.init()

    }

}


3. 实现归档把模型保存到本地Document文件夹:
3.1 获取本地Document路径,一般路径都设为全局变量,方便解档直接使用:

let userAccountPath ="\(NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory,

FileManager.SearchPathDomainMask.userDomainMask,true).first!)/userAccount.data"


3.2 对获取到的模型进行归档操作,要注意模型必须是确定的类型,如果是可选类型会报发送未识别的消息的错误(切记)

NSKeyedArchiver.archiveRootObject(userModel!, toFile:userAccountPath)


4.实现解档从Document文件夹获取本地模型数据

4.1 判断Document文件夹下是否有已保存好的模型,有的话就解档取出模型

 if NSKeyedUnarchiver.unarchiveObject(withFile:userAccountPath) !=nil {

            

            userModel =NSKeyedUnarchiver.unarchiveObject(withFile:userAccountPath)as? HCUserModel

        }





2017-12-29 13:17:53 fzhlee 阅读数 558
Swift4.0入门实例视频教程—4744人已学习
课程介绍    
201712291158262922.
    Swift4.0入门视频教程,课程内容包含Swift入门知识、数据类型(元组、Dictionary、运算符)、流程控制、函数、类与对象、扩展协议、常见概念、实用进阶、案例实战。 1、119节大容量课程:包含了Swift4.0语言大部分知识点; 2、创新的教学模式:手把手教您iOS开发技术入门,一看就懂,一学就会; 3、完美贴心的操作提示:让您的眼睛始终处于操作的焦点位置,不用再满屏找光标; 4、语言简洁精练:瞄准问题的核心所在,减少对思维的干扰,并节省您宝贵的时间; 5、视频短小精悍:即方便于您的学习和记忆,也方便日后对功能的检索;
课程收益
    掌握Swift 4.0语言,并通过一整套实例教程,使学员掌握从生成证书、创建app、架构、开发、打包上传、提交审核等整个开发流程!
讲师介绍
    李发展更多讲师课程
    10年以上IT行业工作经验、三年以上IT行业教学经验。丰富的项目经验和授课经验,授课形式不拘一格。熟悉JAVA,iOS,Swift,平面设计、网页设计、Javascript开发等技术。代表作品:拥有百万下载量、千份五星好评的iOS应用《互动教程 for Photoshop》、《互动教程 for Xcode》、《互动教程 for Illustrator》、《互动教程 for Pages》等。
课程大纲
  第1章:入门知识
    1.iOS项目模板的介绍  6:37
    2.使用Playground学习Swift  2:55
    3.Swift语言中的常量和变量  1:53
    4.Swift的标识符和关键字  1:57
    5.Swift的表达式Expressions  1:29
    6.给Swift代码添加注释语句  2:12
    7.Swift的几个打印输出语句  1:42
    8.在控制台输出类的实例及其属性  1:42
  第2章:数据类型
    1.Swift的(Boolean)布尔类型  2:40
    2.Swift的(Int)整形类型  4:45
    3.Swift的(Float)和(Double)浮点类型  4:47
    4.字符串(String)及对字符(Characters)的遍历  2:26
    5.Swift字符串的使用详解  5:39
    6.Swift中的元组(Tuples)  2:04
    7.基本数据类型之间的互相转换  2:52
    8.一维数组(Array)的使用详解  2:57
    9.多维数组的创建和遍历  1:49
    10.数组的几种遍历方式  2:09
    11.字典(Dictionary)的使用详解  5:12
    12.Swift的一元、二元和三元运算符  2:52
    13.Swift的位运算符和防溢出运算符  2:26
    14.比较运算符和区间运算符  3:10
  第3章:流程控制
    1.使用for-in循环遍历数组  3:36
    2.使用循环语句获得序列中的最小值  2:56
    3.switch-case语句的实例解析  2:27
    4.continue、break和fallthrough的区别  3:16
    5.while和repeat-where循环语句  2:35
    6.if和if-let判断语句的使用解析  3:17
  第4章:函数
    1.函数func以及函数的参数和返回值  3:22
    2.函数的外部参数名  2:24
    3.创建拥有任意数量参数的函数  2:05
    4.函数的输入输出inout参数解析  1:54
    5.给函数的参数设置默认的取值  1:52
    6.使用函数作为另一个函数的参数  3:00
    7.函数类型的解析  2:10
    8.使用函数类型作为函数的返回类型  2:10
    9.函数可以拥有多个返回值  2:04
    10.藏在函数内部的函数  1:47
    11.递归函数的使用解析  1:58
    12.Swift那些非常实用的内部函数  4:58
  第5章:类与对象
    1.Swift的枚举(enum)类型及遍历  2:46
    2.给枚举类型添加方法  2:11
    3.Swift的结构(struct)类型及其下标(subscript)  3:11
    4.类(class)的初始化方法、属性和方法  2:46
    5.类的引用(reference)特征  2:07
    6.类和结构两个类型的比较  2:48
    7.类属性的set和get方法解析  1:53
    8.类属性的willSet和didSet方法解析  2:21
    9.类析构方法(deinit)的使用  1:29
    10.给类添加下标(subscript)  2:04
    11.类的静态方法(class func)  1:51
    12.将一个类的实例作为另一个类的属性  2:03
    13.类的继承以及方法的重写(override)  2:18
    14.父类在实例类型转化时的应用  2:02
    15.使用is语句检查实例的类型  3:44
    16.使用Any表示任意值类型  2:25
  第6章:扩展协议
    1.使用扩展(extension)扩展类型的属性  1:57
    2.使用extension对方法进行扩展  1:37
    3.使用协议(protocol)进行方法的声明  4:28
    4.问号?和感叹号!的用法解析  5:27
    5.Swift中的闭包(Closure)详解  4:29
    6.Swift语言中的泛型编程  3:18
    7.Swift的do-try-catch错误处理模式  4:48
    8.实例的引用特征和Swift的内存管理  2:19
    9.实例的交叉引用和弱引用(weak)  3:00
    10.Swift的懒加载(lazy initialization)使用解析  2:28
  第7章:常见概念
    1.范围Range、ClosedRange和NSRange的使用  2:43
    2.点CGPoint和变形CGAffineTransform的使用  2:34
    3.尺寸CGSize的使用详解  2:35
    4.范围CGRect的使用详解  3:00
    5.使用NSString对字符串进行各种操作  3:28
    6.日期Date和DateFormatter日期的格式化  4:59
    7.日历Calendar和日期组件DateComponents  1:47
    8.日历Calendar和时区TimeZone  1:54
    9.使用定时组件Timer执行定时任务  4:01
    10.使用UserDefaults和归档方式存取用户数据  6:16
    11.路径URL的使用详解  2:24
    12.使用DispatchGroup管理线程组  1:48
    13.使用UIScreen查询设备屏幕信息  2:09
    14.使用UIColor设置界面组件的颜色属性  3:11
  第8章:实用进阶
    1.Swift语言中的两种单例模式  3:05
    2.Swift语言中的三种消息传递模式  7:05
    3.闭包在定时任务、动画和线程中的使用  3:59
    4.通过protocol在两个对象中进行消息传递  8:25
    5.通过间接代理进行对象间的消息传递  6:04
    6.通过属性进行对象间的消息传递  6:25
    7.使用通知的方法进行对象间的数据传递  6:14
    8.使用performSegue在故事板页面之间进行数据传递  11:11
    9.Swift中的栈Stack和队列Queue详解  5:22
    10.Swift中的链表LinkedList详解  2:58
    11.使用Swift创建一个二叉树BinaryTreeNode  3:51
    12.冒泡排序算法的Swift实现  9:41
    13.选择排序算法的Swift实现  7:58
    14.快速排序算法的Swift实现  10:34
    15.插入排序算法的Swift实现  6:25
    16.希尔排序算法的Swift实现  6:55
    17.归并排序算法的Swift实现  8:57
    18.基数排序算法的Swift实现  8:29
    19.堆排序算法的Swift实现  9:00
  第9章:完整实例
    1.在iTunesConnect中创建产品ACTHelper  10:37
    2.在Xcode9中创建新项目ACTHelper  4:49
    3.创建开发证书和发布证书及其它文件  14:23
    4.在ACTHelper项目中使用CocoaPod管理插件  4:00
    5.创建BaseViewController作为控制器的基类  9:10
    6.创建App的欢迎页面  8:59
    7.登陆页面:创建自定义视图及相关组件  19:43
    8.登陆页面:创建自定义表单Row以及基控制器  16:27
    9.创建用户登陆页面  23:34
    10.用户注册账号信息的输入和短信验证码  31:31
    11.用户注册头像和科目信息输入页面  20:27
    12.用户注册考试成绩输入页面及相关自定义组件  24:49
    13.试题解析页面及相关自定义组件  18:28
    14.试题科目列表及答案列表等自定义组件  27:49
    15.创建试题解析列表页面和试卷选择页面  38:26
    16.创建试题详情页面和浮动菜单组件  35:53
    17.试题原文显示页面和数学公式的渲染  14:32
    18.账号设置列表页面和分享、反馈、评分功能  13:05
    19.会员个人信息设置页面和登出功能  14:03
    20.App发布前的设置以及打包、上传和提交审核  11:46
大家可以点击【查看详情】查看我的课程
2017-11-13 21:54:27 average17 阅读数 4719

本以为之前使用Codable的过程中踩的坑已经够多了,今天博主有遇到一个坑,调了一个下午才解决,问题不大,但是中文的技术文里都很少涉及这个问题。

问题描述:遵循了Codable协议的自定义类,派生出的子类JSON化与反JSON化。

简单来说,就是这儿有一个类遵循了Codable协议,其自身可以很方便地使用JSONEncoder和JSONDecoder来JSON化和反JSON化。但是子类就不是那么方便了。系统提示需要实现一个require init?(from:)的初始化方法。通过这次踩坑,博主总结出了两点在使用Codable的过程中需要注意的点。

首先我们通过一个例子来说明吧。
实现一个Person类,包含属性firstName(姓)、lastName(名)、fullName(全名)、age(年龄)和gender(性别)。gender需要使用枚举类型。包含初始化方法,并且可以使用print直接输出,并可以JSON和反JSON化。
再实现一个Student类,继承自Person,并包含自己的stuNo(学号)和department(公寓)属性。department属性需要使用枚举类型。包含初始化方法,并且可以使用print直接输出,并可以JSON和反JSON化。

看要求两个类需要实现的功能不多且相似,本以为会很简单地解决,但编程就是这么有趣。
首先来实现Person类,我们需要一个性别的枚举

//性别的枚举
enum Gender: Int {
    case male    //男性
    case female  //女性
    case unknow  //未知
}

然后就可以实现Person类了。

//人类
class Person: CustomStringConvertible, Codable {
    var firstName: String  //姓
    var lastName: String  //名
    var age: Int  //年龄
    var gender: Gender  //性别

    var fullName: String {  //全名
        get {
            return firstName + lastName
        }
    }

    //构造方法
    init(firstName: String, lastName: String, age: Int, gender: Gender) {
        self.firstName = firstName
        self.lastName = lastName
        self.age = age
        self.gender = gender
    }

    //实现CustomStringConvertible协议中的计算属性,可以使用print直接输出对象内容
    var description: String {
        return "fullName: \(self.fullName), age: \(self.age), gender: \(self.gender)"
    }
}

Person类的实现非常方便,其中的fullName博主选择使用计算属性,因为它与姓和名相关。然后为了可以使用print输出,Person类遵循了CustomStringConvertible协议,读者也可以继承自NSObject去重写其中的description计算属性,看个人爱好。最后为了可以转换为JSON属性,遵循了Codable协议。编译一下代码,系统报错,说Person类没有遵循Codable协议,然后博主就纳闷儿了。尝试了半天,发现如果自定义的类中嵌套了自定义的类、结构体或枚举,使用Codable协议时,这些嵌套的类型也需要遵循Codable协议,所以,解决方法很简单,直接在Gender枚举上遵循Codable协议就好。
更改代码如下:

enum Gender: Int, Codable {
    case male    //男性
    case female  //女性
    case unknow  //未知
}

然后就是Student类了,基础的实现代码如下:

//学生类
class Student: Person {
    var stuNo: Int  //学号
    var department: Department  //公寓

    //构造方法
    init(stuNo: Int, firstName: String, lastName: String, age: Int, gender: Gender, department: Department) {
        self.stuNo = stuNo
        self.department = department
        super.init(firstName: firstName, lastName: lastName, age: age, gender: gender)
    }

    //重写父类的计算属性
    override var description: String {
        return "stuNo: \(self.stuNo), fullName: \(self.fullName), age: \(self.age), gender: \(self.gender), department: \(self.department)"
    }
}

这时我们就会发现xcode提示你需要实现一个初始化方法,我们点击fix之后自动生成代码如下:

required init(from decoder: Decoder) throws {
        fatalError("init(from:) has not been implemented")
    }

然后,年轻的博主以为问题解决了,试试将Student的实例转换为JSON数据。

//学生实例
var student = Student(stuNo: 20151101001, firstName: "李", lastName: "四", age: 19, gender: .male, department: .two)

print(student)
print()

//JSON化
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
let studentData = try encoder.encode(student)

print(String(data: studentData, encoding: .utf8)!)
print()

输出结果如下:
这里写图片描述
哎?没问题呀,别慌。我们再试试将JSON数据转换为Student实例

//反JSON化
let newStudent = try JSONDecoder().decode(Student.self, from: studentData)
print(newStudent)

很不幸,程序crash了。报错的部分截图如下:
这里写图片描述

看到红色部分的错误提示,感觉似曾相识,往上看一下代码,WC,这不跟系统自己生成的初始化方法里面的那句话,一毛一样么?
既然这里错了,我们就需要在这里改正。

到这里,博主开始CSDN、简书、知乎各种翻,没有具体的解决代码,于是只有自己试一试了。于是便在改初始化方法中敲下了decoder并用”.”来查看改参数里面有的属性或方法,万幸,不多,一个一个试,发现只有一个container(keyedBy: CodingKey.Protocol)方法可以使用。然后经历几个小时的折磨(一把辛酸泪)。终于找到了解决方法。
我们需要自定义一个遵循CodingKey协议的枚举,可以自定义其枚举值,不过博主推荐跟相应要保存的属性同名,之所以需要定义这个枚举,是decoder的container(容器)需要通过key来反JSON化对应的属性值,具体的实现代码如下:

//自定义CodingKey
enum Key: String, CodingKey {
    case stuNo
    case department
}

使用这个枚举来反序列化相应的属性

required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: Key.self)
        self.stuNo = try container.decode(Int.self, forKey: .stuNo)
        self.department = try container.decode(Department.self, forKey: .department)

        try super.init(from: decoder)
    }

到这里,博主的第六感告诉自己,应该还没完(其实吧,是运行继续崩溃)。因为我们只使用自定义的CodingKey枚举来反JSON化,而并没有使用它来JSON化。所以,我们需要重写一个方法

override func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: Key.self)
        try container.encode(stuNo, forKey: Key.stuNo)
        try container.encode(department, forKey: Key.department)

        try super.encode(to: encoder)
    }

到这里,构建、运行程序,结果如下:
这里写图片描述
其实这两个方法,在你遵循的那个类中,在编译之后,系统会将其生成在代码当中,我们只是将Person类中的这两个方法重写了而已。

所有的代码如下:

//性别的枚举
enum Gender: Int, Codable {
    case male    //男性
    case female  //女性
    case unknow  //未知
}

//公寓的枚举
enum Department: String, Codable {
    case one, two, three
}


//人类
class Person: CustomStringConvertible, Codable {
    var firstName: String  //姓
    var lastName: String  //名
    var age: Int  //年龄
    var gender: Gender  //性别

    var fullName: String {  //全名
        get {
            return firstName + lastName
        }
    }

    //构造方法
    init(firstName: String, lastName: String, age: Int, gender: Gender) {
        self.firstName = firstName
        self.lastName = lastName
        self.age = age
        self.gender = gender
    }

    //实现CustomStringConvertible协议中的计算属性,可以使用print直接输出对象内容
    var description: String {
        return "fullName: \(self.fullName), age: \(self.age), gender: \(self.gender)"
    }
}

//自定义CodingKey
enum Key: String, CodingKey {
    case stuNo
    case department
}

//学生类
class Student: Person {
    var stuNo: Int  //学号
    var department: Department  //公寓

    //构造方法
    init(stuNo: Int, firstName: String, lastName: String, age: Int, gender: Gender, department: Department) {
        self.stuNo = stuNo
        self.department = department
        super.init(firstName: firstName, lastName: lastName, age: age, gender: gender)
    }

    //编码方法
    override func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: Key.self)
        try container.encode(stuNo, forKey: Key.stuNo)
        try container.encode(department, forKey: Key.department)

        try super.encode(to: encoder)
    }

    //解码方法
    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: Key.self)
        self.stuNo = try container.decode(Int.self, forKey: .stuNo)
        self.department = try container.decode(Department.self, forKey: .department)

        try super.init(from: decoder)
    }

    //重写父类的计算属性
    override var description: String {
        return "stuNo: \(self.stuNo), fullName: \(self.fullName), age: \(self.age), gender: \(self.gender), department: \(self.department)"
    }
}

//学生实例
var student = Student(stuNo: 20151101001, firstName: "李", lastName: "四", age: 19, gender: .male, department: .two)

print(student)
print()

//JSON化
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
let studentData = try encoder.encode(student)

print(String(data: studentData, encoding: .utf8)!)
print()

//反JSON化
let newStudent = try JSONDecoder().decode(Student.self, from: studentData)
print(newStudent)

最后博主总结如下:
1、遵循了Codable协议的类,其嵌套类型也需要遵循Codable协议;
2、遵循了Codable协议的类的派生类,需要重写override func encode(to encoder: Encoder) throws方法和required init(from decoder: Decoder) throws方法。这两个方法都需要使用容器来编码和解码,容器中属性的key与自定义遵循了CodingKey协议的枚举值对应,在将子类中的属性编码和解码之后,需要调用父类的编码或解码方法。

2016-04-05 11:58:14 zww1984774346 阅读数 2281

Swift中对象进行归档写入文件时需要对对象属性进行归档操和解归档操作
,对象方法中需重写以下两个方法

 //从nsobject解析回来
    init(coder aDecoder:NSCoder!){
        self.name=aDecoder.decodeObjectForKey("name") as! String
        self.phone=aDecoder.decodeObjectForKey("age") as! String
    }

    //编码成object
    func encodeWithCoder(aCoder:NSCoder!){
        aCoder.encodeObject(name,forKey:"name")
        aCoder.encodeObject(phone,forKey:"age")
    }

归档,解归档需要使用到NSKeyedArchiver和NSKeyedUnarchiver来实现。

       //保存数据
       let data = NSMutableData()
       let archiver = NSKeyedArchiver(forWritingWithMutableData: data)
       archiver.encodeObject(userData,forKey: "userlist")
       archiver.finishEncoding()
       //数据写入
        data.writeToFile(dataFilePath, atomically: true)

       //读取数据
         //获取本地数据文件地址
         let path = self.dataFilePath()
            //读取文件数据
            let data = NSData(contentsOfFile: path)
            //解码器
            let unarchiver = NSKeyedUnarchiver(forReadingWithData: data!)
            userList = unarchiver.decodeObjectForKey("userdata") as! Array
            //结束解码
            unarchiver.finishDecoding()
2017-12-25 14:26:42 fzhlee 阅读数 2539

免费下载地址:https://itunes.apple.com/cn/app/id1320746678

◈ 不看视频不看书,手把手带您学习Swift语言
◈ 利用手指来互动式学习Swift 4.0
◈ 无痛上手,比观看视频、阅读书籍更加有趣、更加有效的学习方式 
◈ 变被动学习为主动学习,真正的Swift语言一点通,是您学习Swift语言的最佳方式


【Swift4互动教程是什么】
Swift4互动教程是一款简单、有趣、互动式的学习Swift的新工具。是第一款互动式学习Swift的工具。此应用将向您展示基于Swift 4.0的绝大部分功能点。
就像有一名专业的教师手把手地教您最新、最实用的Swift编程技巧。您将学会怎么使用Xcode来快速、直接地表达您的想法与创意。
另外,本应用119节课都包含互动模式,同时也支持观赏模式,当您在互动式学习中肢体疲劳时,可以切换至此模式,这样意味着您同时也拥有了119节教学影片。 

【Swift4互动教程主要包括哪些内容】
包含常量与变量、基本数据类型,以及Swift语言中的新数据类型—元组型和可选型的内容。同时还讲解了运算符和表达式、流程控制语句、字符和字符串、集合类型、函数和闭包。此外,Swift面向对象的枚举、结构体、类,以及内存管理、协议与抽象类型、错误处理、链式编程、iOS开发中的常见概念等内容也有所涉及。在第八章我们使用Swift语言实现了栈、队列、二叉树等数据结构,还实现了常见的8种排序算法。最后一章则包含了证书的创建、项目的架构、开发、打包、上传和发布一整套流程,供您学以致用。 部分内容如下:
- 使用Playground学习Swift
- Swift语言中的常量和变量
- Swift的标识符和关键字
- Swift的表达式Expressions
- 给Swift代码添加注释语句
- Swift的几个打印输出语句
- 在控制台输出类的实例及其属性

- Swift的(Boolean)布尔类型
- Swift的(Int)整形类型
- Swift的(Float)和(Double)浮点类型
- 字符串(String)及对字符(Characters)的遍历
- Swift字符串的使用详解
- Swift中的元组(Tuples)
- 基本数据类型之间的互相转换
- 一维数组(Array)的使用详解
- 多维数组的创建和遍历
- 数组的几种遍历方式
- 字典(Dictionary)的使用详解

- Swift的一元、二元和三元运算符
- Swift的位运算符和防溢出运算符
- 比较运算符和区间运算符
- 使用for-in循环遍历数组
- 使用循环语句获得序列中的最小值
- switch-case语句的实例解析
- continue、break和fallthrough的区别
- while和repeat-where循环语句
- if和if-let判断语句的使用解析

- 函数的参数和返回值
- 函数的外部参数名
- 创建拥有任意数量参数的函数
- 函数的输入输出inout参数解析
- 给函数的参数设置默认的取值
- 使用函数作为另一个函数的参数
- 函数类型的解析
- 使用函数类型作为函数的返回类型
- 函数可以拥有多个返回值
- 藏在函数内部的函数
- 递归函数的使用解析
- Swift那些非常实用的内部函数

- Swift的枚举(enum)类型及遍历
- 给枚举类型添加方法
- Swift的结构(struct)类型及其下标(subscript)
- 类(class)的初始化方法、属性和方法
- 类的引用(reference)特征
- 类和结构两个类型的比较
- 类属性的set和get方法解析
- 类属性的willSet和didSet方法解析
- 类析构方法(deinit)的使用
- 给类添加下标(subscript)
- 类的静态方法(class func)
- 将一个类的实例作为另一个类的属性
- 类的继承以及方法的重写(override)
- 父类在实例类型转化时的应用
- 使用is语句检查实例的类型
- 使用Any表示任意值类型

- 使用扩展(extension)扩展类型的属性
- 使用extension对方法进行扩展
- 使用协议(protocol)进行方法的声明
- 问号?和感叹号!的用法解析
- Swift中的闭包(Closure)详解
- Swift语言中的泛型编程
- Swift的do-try-catch错误处理模式
- 实例的引用特征和Swift的内存管理
- 实例的交叉引用和弱引用(weak)
- Swift的懒加载(lazy initialization)使用解析

- 范围Range、ClosedRange和NSRange的使用
- 点CGPoint和变形CGAffineTransform的使用
- 尺寸CGSize的使用详解
- 范围CGRect的使用详解
- 使用NSString对字符串进行各种操作
- 日期Date和DateFormatter日期的格式化
- 日历Calendar和日期组件DateComponents
- 日历Calendar和时区TimeZone
- 使用定时组件Timer执行定时任务
- 使用UserDefaults和归档方式存取用户数据
- 路径URL的使用详解
- 使用DispatchGroup管理线程组
- 使用UIScreen查询设备屏幕信息
- 使用UIColor设置界面组件的颜色属性

- Swift语言中的两种单例模式
- Swift语言中的三种消息传递模式
- 闭包在定时任务、动画和线程中的使用
- 通过protocol在两个对象中进行消息传递
- 通过间接代理进行对象间的消息传递
- 通过属性进行对象间的消息传递
- 使用通知的方法进行对象间的数据传递
- 使用performSegue在故事板页面之间进行数据传递
- Swift中的栈Stack和队列Queue详解
- Swift中的链表LinkedList详解
- 使用Swift创建一个二叉树BinaryTreeNode
- 冒泡排序算法的Swift实现
- 选择排序算法的Swift实现
- 快速排序算法的Swift实现
- 插入排序算法的Swift实现
- 希尔排序算法的Swift实现
- 归并排序算法的Swift实现
- 基数排序算法的Swift实现
- 堆排序算法的Swift实现

- 在iTunesConnect中创建产品ACTHelper
- 在Xcode9中创建新项目ACTHelper
- 创建开发证书和发布证书及其它文件
- 在ACTHelper项目中使用CocoaPod管理插件
- 创建BaseViewController作为控制器的基类
- 创建App的欢迎页面
- 登陆页面:创建自定义视图及相关组件
- 登陆页面:创建自定义表单Row以及基控制器
- 创建用户登陆页面
- 用户注册账号信息的输入和短信验证码
- 用户注册头像和科目信息输入页面
- 用户注册考试成绩输入页面及相关自定义组件
- 试题解析页面及相关自定义组件
- 试题科目列表及答案列表等自定义组件
- 创建试题解析列表页面和试卷选择页面
- 创建试题详情页面和浮动菜单组件
- 试题原文显示页面和数学公式的渲染
- 账号设置列表页面和分享、反馈、评分功能
- 会员个人信息设置页面和登出功能
- App发布前的设置以及打包、上传和提交审核
- 更多内容等待您的探索!!!










【相关互动教程】
Xcode9.0互动教程
https://itunes.apple.com/cn/app/id1063100471

iOS开发中的神兵利器
https://itunes.apple.com/cn/app/id1209739676

Excel2016互动教程
https://itunes.apple.com/cn/app/id1090726089

Photoshop CC互动教程精装版
https://itunes.apple.com/cn/app/id822431555

Illustrator CC互动教程
https://itunes.apple.com/cn/app/id1005557436

Photoshop CS5互动教程完全版:
https://itunes.apple.com/cn/app/id976566883

Photoshop脚本互动教程
https://itunes.apple.com/cn/app/id926846601