swift详解之十-------------异常处理、类型转换 ( Any and AnyObject )
异常处理、类型转换 ( Any and AnyObject )
1、错误处理 (异常处理)
swift 提供第一类错误支持 ,包括在运行时抛出 ,捕获 , 传送和控制可回收错误。在swift中 ,错误用复合 ErrorType 协议的值表示 。 Swift枚举把一系列相关的错误组合在一起。同时可以把一些相关的值和错误关联在一起 。 因此
编译器会为实现ErrorType协议的Swift枚举类型自动实现相应的合成
这里看个很简单的小例子。
enum WrongName:ErrorType{
case NoName
}
- 1
- 2
- 3
错误处理 1、抛出
在方法后面加上throws 关键字
func doSomeThing(name:String) throws ->String {
if(name.isEmpty){
throw WrongName.NoName
}
print("no error")
return name
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
当字符位空 , 我们就 throw
这个异常 。
在调用一个抛出函数的时候 需要在调用前面加上try
try doSomeThing("eat") //这里并没有出现异常 会输出 no error
- 1
try doSomeThing("") //会产生运行时错误 error caught in main()
- 1
这里抛出了错误但是没有处理 。
2、捕捉和处理错误 do-catch 语句来捕捉和处理错误
语法 :
do {
}catch parttern{
}
- 1
- 2
- 3
- 4
- 5
- 6
如果一个错误被爆出 , 这个错误会被传递到外部域 ,直到被catch捕捉处理 ,pattern 是用来匹配错误和相应的执行语句。
swift处理异常和别的语言不同的是swift不会展开调用堆栈 。 那样会带来很大的性能损耗 。 在swift中 throw 语句的性能几乎和return一样
do{
try doSomeThing("")
}catch WrongName.NoName{
print("NoName error!")
} //输出NoName error!
- 1
- 2
- 3
- 4
- 5
通过try!来调用抛出函数或者方法 来禁止错误传输 。并把调用包装在运行时断言,这样就不会抛出错误啦。如果帧抛出错误, 会触发运行时错误
func willThrowIfTru(value:Bool) throws{
if value {
throw NotTrue.BeTrue
}
}
do{
try willThrowIfTru(true)
}catch {
print("不能为true呀")
}
//这里会输出 不能为true呀 --没有疑问
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
try! willThrowIfTru(false) //这块禁止了错误传输 意思断言肯定不会有异常 , 如果有 就会报错
- 1
收尾操作
使用defer 执行的语句 不管有没有出错都回执行到 。相当于其他的finally
defer 语句和的执行顺序和它定义顺序相反 也就是说 , 第一个difer语句中的代买在第二个后执行 。
func willThrowIfTru1(value:Bool) throws{
if value {
throw NotTrue.BeTrue
}
}
do{
try willThrowIfTru1(true)
}catch {
print("不能为true呀")
}
defer{
print("我后执行")
}
defer{
print("我先执行")
}
print("我第一个执行")
结果:
不能为true呀
我第一个执行
我先执行
我后执行
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
2、类型转换
Swift 中使用is 和 as操作符实现。这两个操作符提供了一种简单达意的方式去检查值的类型或者转换它的类型
- 用类型检查操作符(is)来检查一个实例 是否属于特定子类型
class Person{
var name:String
init(name:String){
self.name=name
}
}
var p = Person(name: "wangwu")
if p is Person
{
print("yes")
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
这里输出yes , 转换这种明显的没有什么意思 。来看看下面的、
class Student: Person {
}
class Teacher: Person {
}
let list = [ Student(name: "张三") , Student(name: "李四") , Teacher(name: "王五") ]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
这里会推断出是一个[Person] 数组
var stuCount = 0
var teaCount = 0
for item in list {
if item is Student {
stuCount++
}
if item is Teacher{
teaCount++
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
print("stu :\(stuCount) , tea: \(teaCount)")
//stu :2 , tea: 1
- 1
- 2
这里利用is
推断出具体类型
- 向下转型
某类型的一个常量或变量可能在幕后实际上属于一个子类 这时候 你可以尝试向下转型 用as! 或者 as? 向下转型可能会失败 。as? 返回你试图转型的可选值 。 as! 强制转型 ,非常确定的时候再用 否则会运行时错误 。
所以上面的例子还能这么写
stuCount = 0
teaCount = 0
//这里使用了可选绑定 以前的章节有讲过
for item in list {
if let s = item as? Student {
stuCount++
}
if let t = item as? Teacher{
teaCount++
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
print("stu :\(stuCount) , tea: \(teaCount)")
//stu :2 , tea: 1
- 1
- 2
结果是一模一样的
- Any 和 AnyObject 的类型
Swift为不确定类型提供了两种特殊类型别名:
AnyObject可以代表任何class类型的实例。
Any可以表示任何类型,包括方法类型(function types)。(2.0新特性)
let student:[AnyObject] = [Student(name: "ww"),Student(name: "aa"),Student(name: "dd")]
- 1
//这里定义了一个[AnyObject] 类型的数组 ,但是确定是放得student 所以你可以强制转型
let stu = student[0] as! Student
print(stu.name) //aa
let stus = student as! [Student]
//你可以直接强制转换成一个Student数组
print(stus.count) //3
- 1
- 2
- 3
- 4
- 5
- 6
下面看下 Any类型
var things = [Any]()
things.append("str")
things.append(0.9)
things.append(stu)
things.append(stus)
for item in things {
switch item {
case let val as Double:
print("\(val) 是个数字类型")
case let val as String:
print("\(val) 是个字符串")
case let val as Student:
print("\(val) 是Student对象")
case let val as [Student]:
print("\(val) 是个[Student]数组")
default:
print("啥都不是")
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
结果 :
str 是个字符串
0.9 是个数字类型
Student 是Student对象
[Student, Student, Student] 是个[Student]数组
再不确定类型的时候才使用这两个 ,确定的时候最好使用确定类型
版权声明:本文为博主原创文章,未经博主允许不得转载。
swift详解之十-------------异常处理、类型转换 ( Any and AnyObject )的更多相关文章
- 异常处理器详解 Java多线程异常处理机制 多线程中篇(四)
在Thread中有异常处理器相关的方法 在ThreadGroup中也有相关的异常处理方法 示例 未检查异常 对于未检查异常,将会直接宕掉,主线程则继续运行,程序会继续运行 在主线程中能不能捕获呢? 我 ...
- Solon 框架详解(十)- Solon 的常用配置
Springboot min -Solon 详解系列文章: Springboot mini - Solon详解(一)- 快速入门 Springboot mini - Solon详解(二)- Solon ...
- Swift详解之NSPredicate
言:谓词在集合过滤以及CoreData中有着广泛的应用.本文以Playground上的Swift代码为例,讲解如何使用NSPredicate. 准备工作 先在Playground上建立一个数组,为后文 ...
- 【Java入门提高篇】Day34 Java容器类详解(十五)WeakHashMap详解
源码详解系列均基于JDK8进行解析 说明 在Java容器详解系列文章的最后,介绍一个相对特殊的成员:WeakHashMap,从名字可以看出它是一个 Map.它的使用上跟HashMap并没有什么区别,所 ...
- 【Java入门提高篇】Day30 Java容器类详解(十二)TreeMap详解
今天来看看Map家族的另一名大将——TreeMap.前面已经介绍过Map家族的两名大将,分别是HashMap,LinkedHashMap.HashMap可以高效查找和存储元素,LinkedHashMa ...
- Spring Boot 集成 FreeMarker 详解案例(十五)
一.Springboot 那些事 SpringBoot 很方便的集成 FreeMarker ,DAO 数据库操作层依旧用的是 Mybatis,本文将会一步一步到来如何集成 FreeMarker 以及配 ...
- Git应用详解第十讲:Git子库:submodule与subtree.md
前言 前情提要:Git应用详解第九讲:Git cherry-pick与Git rebase 一个中大型项目往往会依赖几个模块,git提供了子库的概念.可以将这些子模块存放在不同的仓库中,通过submo ...
- Redis详解(十)------ 从零开始搭建集群
在上一篇博客我们介绍了------Redis哨兵(Sentinel)模式,哨兵模式主要是解决高可用问题,在master节点宕机时,slave节点能够自动切换成为master节点 本篇博客我们来介绍Re ...
- Java源码详解系列(十)--全面分析mybatis的使用、源码和代码生成器(总计5篇博客)
简介 Mybatis 是一个持久层框架,它对 JDBC 进行了高级封装,使我们的代码中不会出现任何的 JDBC 代码,另外,它还通过 xml 或注解的方式将 sql 从 DAO/Repository ...
随机推荐
- Mac系统下的php扩展开发
通常在开发PHP的时候,一些核心代码,比如加密函数或需要高效率执行的代码,此时可以用C语言写扩展.本文主要介绍了扩展的开发流程,具体的代码实现参考生成的文件说明. 当前PHP使用的是XAMPP 5.6 ...
- E20170512-hm
implicit adj. 不言明[含蓄]的; 无疑问的, conversion n. 变换,转变; precision n. 精确度, adj. 精确的, with precision 准确地 ...
- HDU6038:Function(循环群/节+找公式)
传送门 题意 给出一个\(0\sim n-1\)的排列a,一个\(0\sim {m-1}\)的排列b,询问满足\[f(i)=b_{f(a_i)}~~(0\le i\le n-1)\]的函数的个数 分析 ...
- hihoCoder搜索二·骑士问题
#include <stdio.h> #include <string.h> #include <math.h> #include <algorithm> ...
- bzoj 1023: [SHOI2008]cactus仙人掌图【tarjan+dp+单调队列】
本来想先求出点双再一个一个处理结果写了很长发现太麻烦 设f[u]为u点向下的最长链 就是再tarjan的过程中,先照常处理,用最长儿子链和次长儿子链更新按ans,然后处理以这个点为根的环,也就是这个点 ...
- jzoj5980. 【WC2019模拟12.27】字符串游戏
首先发现双方可以有一个默契,不管谁刻意,都可以把串变为诸如\(...101010101...\)的形式 所以先手要赢的话就是要在上面的基础之上加一个字符使其变为要求的子串 那么就是要求的子串中相邻两个 ...
- java中多线程的两种创建方式
一丶继承Thread类实现多线程 第一步:继承Thread类第二步:重写run()方法第三步:创建继承了Thread类的对象 , 调用start()方法启动. //线程创建方式一 : /* 第一步:继 ...
- Luogu P2114[NOI2014]起床困难综合症 【贪心/位运算】By cellur925
题目传送门 所以NOI的题现在简单惹? 30分做法:枚举开始的权值,n²过掉. 100分做法:竟然是贪心qwq.因为我们的计算背景是二进制下,所以我们贪心地想让每一位都是1.我们现在需要解决的问题,就 ...
- pycharm 添加个人信息
2. 可以使用搜索快速找到"File and Code Templates", 右侧菜单选择"Python Script",对模板进行编辑 格式为: ${< ...
- 1051:A × B problem 大数相乘
给你两个整数,请你计算A × B. 输入 数据的第一行是整数T(1 ≤ T ≤ 20),代表测试数据的组数.接着有T组数据,每组数据只有一行,包括两个非负整数A和B.但A和B非常大,Redraimen ...