那些年,学swift踩过的坑
最近在学swift,本以为多是语法与oc不同,而且都是使用相同的cocoa框架,相同的API,但是或多或少还是有些坑在里,为了避免以后再踩,在这里记下了,以后发现新的坑,也会慢慢在这里加上
[TOC]
1.main文件去哪儿了?
- OC中main.m中的代码, 通过@UIApplicationMain标记自动生成
- 可以注掉AppDelegate里的@UIApplicationMain,自己实现Main,不过一般没人这样做
- 实现下面代码就是OC中的main文件的函数
UIApplicationMain(Process.argc, Process.unsafeArgv, nil, NSStringFromClass(AppDelegate))
2.如何通过字符串创建类对象?
- 在swift中打印对象时,会发现在类型前面总会有
命名空间 .
+类名
- 在swift中用字符串生成类对象就需要拼接成这样的格式,才能成功生成类
- 注意,命名空间不要加特殊符号,不然依然无法获取控制器类
//获取命名空间,在info.plist文件里就是Executable file
let nameSpace = NSBundle.mainBundle().infoDictionary!["CFBundleExecutable"] as! String
//拼接成固定格式
let controller:AnyClass = NSClassFromString(nameSpace + "." + controllerName)!
//创建对象
let viewController = (controller as! UIViewController.Type).init()
3.Swift中的Any,AnyObject,AnyClass分别代表是什么?
- AnyObject: 相当于OC中的id, 表示所有class类型的数据, 所有继承与NSObject的类都隐式实现了protocol AnyObject协议, 所以他可以表示所有的class类型
Any:所有基本数据类型和enum/ struct都可以用Any来表示
注意: 有的时候你会发现将基本数据类型或者enum/ struct通过AnyObject来保存也不会报错, 这是因为Swift中很多数据类型可以和OC中的数据类型进行自动转换, 系统内部已经将他们转换为了OC的对象类型
AnyClass: 用来表示任意类的类类型(元类型)
typealias AnyClass = AnyObject.Type
.Type用于获取类的元类型, 例如Person.Type就代表着获取Person的元类型
.self如果通过类名调用, 那么可以获取该类的类型, 说白了就是获取自己
4.在Swife中如何抓取异常?
- 在Swift中抓取异常需要do,catch,try这三个关键字
- 这里举个json序列化的例子
do{
let path = /..路径../
let data =/..转data../
//编译器会要求你实行异常检测,于是在序列化前面添加try字段
//外部包裹do,catch,显而易见出错自然会走catch
let dicArr = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers)
}catch
{
// 如果抛出异常就会来到catch
}
5.在swift中如何定义全局打印方法
- 由于swift没有宏,我们不能像oc那样去定义
- 直接在AppDelegate中写,反正哪里都可以用
- 用泛型传参
- 如何判断调试与发布状态呢?
- 在Build settings里找到Swift Compiler-custom Flags
- 在other swift flags 的Debug里添加两个字段
- "-D"
- "DEBUG"
- 代码中直接判断就行
func HJSLog<T>(message: T)
{
#if DEBUG
print("\(message)")
#endif
}
6.在swift中,单例怎么写?
- 在swift中,单例有两种写法
- 一种是按照OC的思维去写
static var onceToken: dispatch_once_t = 0
static var instance: NetworkTools?
class func shareNetworkTools() -> NetworkTools
{
dispatch_once(&onceToken) { () -> Void in
print("我被调用了")
instance = NetworkTools()
}
return instance!
}
- 另一种就是swift的纯正写法
- 在swift中,let本身就只会创建一次,可以运用这个特性
- let是线程安全的
static let instance: NetworkTools = NetworkTools()
class func shareNetworkTools() -> NetworkTools
{
return instance
}
7.在swift中如何私有化点击事件方法
- 一般我们不公开方法会在前面添加
private
- 但是例如按钮点击方法,光是添加
private
是不够的 - 因为swift的方法调用是在编译时就决定了
- 而点击事件方法由于是来自于runloop中
- 编译器不会它一起编译进来,只有在运行时呼叫,这属于OC的调用方式
- 所以我们还需要再在方法前面加上
@objc
//按钮点击handle
@objc private func composeClick(){
}`
8.在swift中如何懒加载
- 在swift中对懒加载有专门的关键字
///懒加载一个imageView
private lazy var icon:UIImageView = {
let imageV = UIImageView(image: UIImage(named: "visitordiscover_feed_image_smallicon"))
return imageV
}()
9.在swift中的协议(protocol)
- 在swift中定义协议也很简单
- 只需要在类前定义就行
@objc
protocol VisitorViewDelegate:NSObjectProtocol
{
//点击注册按钮
optional func visitorViewDidRegisterBtnClick(visitView: VisitorView)
//点击登录按钮
optional func visitorViewDidLoginBtnClick(visitView:VisitorView)
} - 代理属性需要设定为weak,防止循环引用
weak var delegate:VisitorViewDelegate?
- 在调用代理方法时,代理作为可选属性,已经帮我们预防代理不存在的可能
- 我们还需要借助可选属性来预防方法未实现
- 当然在确定实现的前提下可以解包
///注册handle
@objc private func registerClick(){
delegate?.visitorViewDidRegisterBtnClick!(self)
}
///登录handle
@objc private func loginClick(){ delegate?.visitorViewDidLoginBtnClick?(self)
}
10.在swift中如何写分类
- 我刚从oc转过来就遇到了如何在swift中写分类的问题
- swift中写分类很简单
extension
就是swift中的分类- 例如给UIBarbuttonItem添加分类
- 新建一个UIBarButtonItem+Extension.swift文件
import UIKit
extension UIBarButtonItem
{
convenience init(target:AnyObject?,action:Selector,image:String) {
let btn = UIButton(type: UIButtonType.Custom)
btn.setImage(UIImage(named: image), forState: UIControlState.Normal)
btn.setImage(UIImage(named: image + "_highlighted"), forState: UIControlState.Highlighted)
btn.addTarget(target, action: action, forControlEvents: UIControlEvents.TouchUpInside)
self.init(customView:btn)
}
}
11.为何经常被强制实现init(coder: NSCoder)
- 因为Objective-C 和 Swift 中都没有直接的这样的抽象函数语法支持
- 然而有些时候我们却有不想让别人调用某个方法,但又不得不将其暴露出来的时候。
- 一般满足这种需求的就是抽象类型或者抽象函数
- 在面对这种情况时,为了确保子类实现这些方法,而父类中的方法不被错误地调用,我们就可以利用 fatalError 来在父类中强制抛出错误,以保证使用这些代码的开发者留意到他们必须在自己的子类中实现相关方法:
class MyClass {
func methodMustBeImplementedInSubclass() {
fatalError("这个方法必须在子类中被重写")
}
}
class YourClass: MyClass {
override func methodMustBeImplementedInSubclass() {
print("YourClass 实现了该方法")
}
}
class TheirClass: MyClass {
func someOtherMethod() {
}
}
YourClass().methodMustBeImplementedInSubclass()
// YourClass 实现了该方法
TheirClass().methodMustBeImplementedInSubclass()
// 这个方法必须在子类中被重写
- 不仅仅是对于类似抽象函数的使用中可以选择 fatalError,对于其他一切我们不希望别人随意调用,但是又不得不去实现的方法,我们都应该使用 fatalError 来避免任何可能的误会。比如父类标明了某个 init 方法是 required 的,但是你的子类永远不会使用这个方法来初始化时,就可以采用类似的方式, 被广泛使用 (以及被广泛讨厌的) init(coder: NSCoder) 就是一个例子。在子类中,我们往往会写
required init(coder: NSCoder) {
fatalError("NSCoding not supported")
}
12.在swift中使用guard与fatalError配合抛出异常
- 在严谨的开发中会经常用到断言
- 前面一条介绍了
fatalError
来抛出错误 - 这条就来介绍一下
guard
与fatalError
的配合使用达到断言的效果guard let safeValue = criticalValue else {
fatalError("criticalValue cannot be nil here")
}
someNecessaryOperation(safeValue) - 本来我认为
if
也可以达到这样的效果if let safeValue = criticalValue {
someNecessaryOperation(safeValue)
} else {
fatalError("criticalValue cannot be nil here")
} - 或者
if criticalValue == nil {
fatalError("criticalValue cannot be nil here")
}
someNecessaryOperation(criticalValue!) 但是看到有些博客这么说:
这个flatten code以其他方式进入一个if let 代码块,并且在靠近相关的环境中过早地退出了,而不是进入else代码块。甚 至当你没有捕获一个值(guard let),这个模式在编译期间也会强制过早退出。在第二个if的例子里,尽管代码flattend得像guard一样,但是一个毁灭性的错误或者其他返回 一些无法退出的进程(或者基于确切实例的非法态)将会导致crash。一个过早的退出发生时,guard声明将会及时发现错误,并将其从else block中移除。(这博主翻译得真烂)
所以,还是用guard比较好
13.在swift中,互斥锁变成什么样了?
- 在swift中,互斥锁如何写
- oc中的互斥锁:
@synchronized(self) {
//需要执行的代码块
}
- swift中的互斥锁
objc_sync_enter(self)
//需要执行的代码块
objc_sync_exit(self)
- 至于其他多线程的API和以前的一样,只是少了perform这一类的API,苹果已经去掉了
14.在swift中,引用self时,如何避免循环引用
- 在oc中,我们需要在代码块用到self时,可以直接把self付给其他变量,然后在块中使用完毕后制空,或者像下面弱引用self来避免循环引用:
__weak typeof(self) weakSelf = self;
- 那么在swift中我们怎么办到这点呢?
- 很简单,看下面代码
//这里用gcd举例不好,毕竟系统的块不会造成循环引用,这里就勉强的学一下怎么改吧
dispatch_async(dispatch_get_global_queue(0, 0)) {[unowned self] () -> Void in
self.view
//添加自己的代码
} - 只需要在闭包里加入
[unowned self]
即可
原文链接:http://www.jianshu.com/p/b5c87824e33c
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
那些年,学swift踩过的坑的更多相关文章
- 项目中踩过的坑之-sessionStorage
总想写点什么,却不知道从何写起,那就从项目中踩过的坑开始吧,希望能给可能碰到相同问题的小伙伴一点帮助. 项目情景: 有一个id,要求通过当前网页打开一个新页面(不是当前页面),并把id传给打开的新页面 ...
- 《C++之那些年踩过的坑(二)》
C++之那些年踩过的坑(二) 作者:刘俊延(Alinshans) 本系列文章针对我在写C++代码的过程中,尤其是做自己的项目时,踩过的各种坑.以此作为给自己的警惕. 今天讲一个小点,虽然小,但如果没有 ...
- 初学spring boot踩过的坑
一.搭建spring boot环境 maven工程 pom文件内容 <project xmlns="http://maven.apache.org/POM/4.0.0" xm ...
- python抓取360百科踩过的坑!
学习python一周,学着写了一个爬虫,用来抓取360百科的词条,在这个过程中.因为一个小小的修改,程序出现一些问题,又花了几天时间研究,问了各路高手,都没解决,终于还是自己攻克了,事实上就是对lis ...
- web开发实战--弹出式富文本编辑器的实现思路和踩过的坑
前言: 和弟弟合作, 一起整了个智慧屋的小web站点, 里面包含了很多经典的智力和推理题. 其实该站点从技术层面来分析的话, 也算一个信息发布站点. 因此在该网站的后台运营中, 富文本的编辑器显得尤为 ...
- 从0开始学Swift笔记整理(五)
这是跟在上一篇博文后续内容: --Core Foundation框架 Core Foundation框架是苹果公司提供一套概念来源于Foundation框架,编程接口面向C语言风格的API.虽然在Sw ...
- 从0开始学Swift笔记整理(四)
这是跟在上一篇博文后续内容: --重写方法 重写实例方法 在子类中重写从父类继承来的实例方法和静态方法.先介绍实例方法的重写. 下面看一个示例: class Person { var n ...
- 从0开始学Swift笔记整理(三)
这是跟在上一篇博文后续内容: --Swift中相关的属性 存储属性 Swift中的属性分为存储属性和计算属性,存储属性就是Objective-C中的数据成员,计算属性不存储数据,但可以通过计算其他属性 ...
- 从0开始学Swift笔记整理(二)
这是跟在上一篇博文后续内容: --函数中参数的传递引用 类是引用类型,其他的数据类型如整型.浮点型.布尔型.字符.字符串.元组.集合.枚举和结构体全部是值类型. 有的时候就是要将一个值类型参数以引用方 ...
随机推荐
- 浏览器中 for in 反射 对象成员 的差异
http://www.cnblogs.com/_franky/archive/2010/05/08/1730437.html 下面是例子 function test(url, obj) { if($( ...
- dota监测
漫漫长假一个人无聊得很,整日DOTA,打的腰酸背痛腿抽筋的.就想着写一个脚本记录自己每天打游戏的时间,于是就产生了下面的这个东西... 运行环境:win7 32位. python版本:3.4.1 由于 ...
- cmakelists 语法学习
1.项目最外层cmake编写:----------用于kdevelop编译器 project(filtering) cmake_minimum_required(VERSION 2.8) ————必须 ...
- 跟我一起学CMake
如今CMake使用的人数越来越多,包括我项目组里,很多大牛们在写Qt程序的时候都不用自带的qmake,貌似会出现很多问题,他们往往都用自己写的CMake来编译系统,今天我也和大家一起来学学这个高大上的 ...
- js中的 window.location、document.location、document.URL 对像的区别(转载)
原文:http://www.cr173.com/html/18417_1.html 当我们需要对html网页进行转向的时候或是读取当前网页的时候可以用到下面三个对像: window.location. ...
- JQUERY1.9学习笔记 之基本过滤器(八) 最后元素选择器
最后元素选择器 jQuery( ":last" ) 描述:选择与之匹配的最后元素. 例:选择表格的最后一行. <!DOCTYPE html><html lang= ...
- wamp虚拟机配置
1.找到httpd.conf 里面:找到 # Virtual hosts 开启虚拟机Include conf/extra/httpd-vhosts.conf 2 编辑httpd-vhosts.con ...
- 【行为型】TemplateMethod模式
模板方法意图是为算法定义好骨架结构,并且其中的某些步骤延迟到子类实现.该模式算是较为简单的一种设计模式.在实际中,应用也较为频繁.模式的类关系图参考如下: 模式的编码结构参考如下: namespace ...
- jquery实现DIV层拖动
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- android.os.NetworkOnMainThreadException 在4.0之后谷歌强制要求连接网络不能在主线程进行访问
谷歌在4.0系统以后就禁止在主线程中进行网络访问了,原因是: 主线程是负责UI的响应,如果在主线程进行网络访问,超过5秒的话就会引发强制关闭, 所以这种耗时的操作不能放在主线程里.放在子线程里,而子线 ...