最近在学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来抛出错误
  • 这条就来介绍一下guardfatalError的配合使用达到断言的效果
    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]即可
文/哟_Json(简书作者)
原文链接:http://www.jianshu.com/p/b5c87824e33c
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

那些年,学swift踩过的坑的更多相关文章

  1. 项目中踩过的坑之-sessionStorage

    总想写点什么,却不知道从何写起,那就从项目中踩过的坑开始吧,希望能给可能碰到相同问题的小伙伴一点帮助. 项目情景: 有一个id,要求通过当前网页打开一个新页面(不是当前页面),并把id传给打开的新页面 ...

  2. 《C++之那些年踩过的坑(二)》

    C++之那些年踩过的坑(二) 作者:刘俊延(Alinshans) 本系列文章针对我在写C++代码的过程中,尤其是做自己的项目时,踩过的各种坑.以此作为给自己的警惕. 今天讲一个小点,虽然小,但如果没有 ...

  3. 初学spring boot踩过的坑

    一.搭建spring boot环境 maven工程 pom文件内容 <project xmlns="http://maven.apache.org/POM/4.0.0" xm ...

  4. python抓取360百科踩过的坑!

    学习python一周,学着写了一个爬虫,用来抓取360百科的词条,在这个过程中.因为一个小小的修改,程序出现一些问题,又花了几天时间研究,问了各路高手,都没解决,终于还是自己攻克了,事实上就是对lis ...

  5. web开发实战--弹出式富文本编辑器的实现思路和踩过的坑

    前言: 和弟弟合作, 一起整了个智慧屋的小web站点, 里面包含了很多经典的智力和推理题. 其实该站点从技术层面来分析的话, 也算一个信息发布站点. 因此在该网站的后台运营中, 富文本的编辑器显得尤为 ...

  6. 从0开始学Swift笔记整理(五)

    这是跟在上一篇博文后续内容: --Core Foundation框架 Core Foundation框架是苹果公司提供一套概念来源于Foundation框架,编程接口面向C语言风格的API.虽然在Sw ...

  7. 从0开始学Swift笔记整理(四)

    这是跟在上一篇博文后续内容: --重写方法 重写实例方法 在子类中重写从父类继承来的实例方法和静态方法.先介绍实例方法的重写. 下面看一个示例: class Person {        var n ...

  8. 从0开始学Swift笔记整理(三)

    这是跟在上一篇博文后续内容: --Swift中相关的属性 存储属性 Swift中的属性分为存储属性和计算属性,存储属性就是Objective-C中的数据成员,计算属性不存储数据,但可以通过计算其他属性 ...

  9. 从0开始学Swift笔记整理(二)

    这是跟在上一篇博文后续内容: --函数中参数的传递引用 类是引用类型,其他的数据类型如整型.浮点型.布尔型.字符.字符串.元组.集合.枚举和结构体全部是值类型. 有的时候就是要将一个值类型参数以引用方 ...

随机推荐

  1. Android VideoView

    这两天公司要让做一个播放视频的小Demo,于是网上学习了下VideoView的使用方法. 先看布局文件,很简单 就是一个VideoView和两个ImageView <RelativeLayout ...

  2. struts2与spring整合问题,访问struts2链接时,spring会负责创建Action

    每次访问一次链接,spring会创建一个对象,并将链接所带的参数注入到Action的变量中(如何做到的呐) 因为: struts2的action每次访问都重新创建一个对象,那spring的ioc是怎么 ...

  3. 【转】iOS6中的Auto Layout:通过代码添加约束

        最近做的项目用到了Auto Layout,于是经过了一番大量的google,这是我看到的讲用代码创建约束最清晰的一篇教程,于是想跟更多的人分享一下.原文也比较简单,可以直接过去看,如果我翻译的 ...

  4. Linux挂载U盘

    在将硬盘插到Linux系统上,打开硬盘时一直提示:unknown filesystem type 'ntfs'. 1.安装gcc,提供编辑环境 yum -y install gcc 2.下载ntfs- ...

  5. centos node卸载

    1.通过包管理工具 如果是通过包管理工具安装的话,那就和包管理工具卸载 yum remove nodejs npm -y 2.手动 如果是通过手动安装:官方下载后安装 进入到安装的路径 cd /opt ...

  6. 【转】从头到尾彻底理解KMP

    很好,讲得很清晰,值得学习. 作者:July时间:最初写于2011年12月,2014年7月21日晚10点 全部删除重写成此文,随后的半个月从早到晚不断改进. 1. 引言 本KMP原文最初写于2年多前的 ...

  7. Activiti 工作流得到最后一次批注的时间

    我们有时候在工作流开发中可能会遇到这样的需求,就是已经审批结束的流程,可能我们还是仍然需要修改业务表的结果,而且我们需要一个时间期限,比如:在5天内可以进行修改 ,这个时候我们就需要得到我们最后一步审 ...

  8. jQuery键盘控制方法,以及键值(keycode)对照表

    键盘控制应用范围非常广泛,比如快捷键控制页面的滚动:在填写表单时候,限制输入内容:或者是屏蔽复制.粘贴.退后等功能.这里说说用jQuery怎么来实现.个人觉得jQuery比原生态的JS好用,代码简单清 ...

  9. JQUERY1.9学习笔记 之内容过滤器(四) parent选择器

    描述:选择至少包含一个子节点的元素(一个标签或是文本). 例:找出所有有子元素的td标签,包含文本. <!doctype html><html lang="en" ...

  10. jQuery之异步Ajax请求使用

    $.ajax({type:'',data:'',async:''...}) 参数: 1.cache: true缓存页面 false 不缓存页面 (默认: true,dataType为script和js ...