有一点乱

by admin on 2019年10月4日

人呢,有时候真的会很懒,懒到吃饭都不想吃了…

007有很多元素,相车美女动作不死之身.
莫非现在导演都执着于继承这些并把他们载在美国式英雄的体裁上开始拍电影?
造型坳的太多了.有Sco迷人么?
唯一的亮点和最大的污点就是 邦妞长的不错和邦妞只是长的不错
还有那句经典台词 竟然成了最恶心的一句.

最近随着苹果的春季发布会到来,iOS9.3系统的更新,Swift2.2的更新也随之到来,Swift自发行以来,就伴随着很多评价,简介,方便开发,完全免费,开源,综合C,OC,Java等多门语言的优劣筛选产生的一门计算机语言。

 

 
 一直很想写一些东西,也有许多想法,但是始终不知道要怎么写出来。其实生活中有很多事情都是开始做了以后才知道行不行的。而我输在了行动。我不希望我可以通过写文章赚钱,但是我希望她能见证我的成长,鼓励我在这个陌生的城市里坚持下去,加油!

有一天 LP也会变成U2
有一天 007还不如零零狗好看

如今Swift语言从发行至今也有近两年时间,在两年里也在不断的完善,更新,而且当下也有不少软件是通过纯Swift语言来编写的,而且他有一个很大的好处就是开源,对于程序员来说这个好处绝对是最有诱惑力的,为什么git能有这么多程序员的支持,就是因为他给了一个代码平台,让大家的代码开源从别人那里学到知识。同时它既严谨又开放,有自己的原则,同时使用起来也非常的灵活。

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“”>

看看一下打印有什么区别

在这里我也是分享一下最近接触并学习Swift语言的一些知识。

<html xmlns=””>
<head>
    <script src=”Scripts/jquery-1.4.1.js”
type=”text/javascript”></script>
    <title>Hello query!!</title>
    <style type=”text/css”>
        #Button2
        {
            width: 359px;
        }
        .style2
        {
            width: 32px;
        }
        .style3
        {
            width: 28px;
        }
        .style4
        {
            width: 24px;
        }
    </style>
    <script type=”text/javascript”>
        var dom = document.getElementById(“btnHide”);
        jquery = $(dom);
        $(“#btnShow”).bind(“click”, function (event) {
$(“#divMsg”).show(); });
        jquery.bind(“click”, function (event) { $(“#divMsg”).hide();
});
        $(“#btnChange”).bind(“click”, function (envent) {
$(“#divMsg”).html(“Hello World, too!”); });
        $(“#Button3”).click(function () {
$(“#divParent+input”).css(“background”, “blue”); });
//下面的按钮可以控制上面的以下所有的按钮
        $(“#alterColor”).click(function () {
$(“#Button3~[id]”).css(“background”, “red”); });
        $(“#alterTableColor”).click(function () { $(“.tab tr:first
td”).css(“background”, “green”); });
        $(“#testBT”).click(function () { $(“body
input:odd”).css(“background”, “red”); });
        $(“#testCK”).click(function () {
$(“input:checked”).css(“background”, “red”); });
        $(“#testCf”).click(function () {
$(“div:contains(‘aa’)”).css(“background”, “red”); });
        $(“#testCF”).click(function () {
$(“td:parent”).css(“background”, “red”); });

let data = 1...3let result = data.lazy.map {  -> Int in print("正在处理 \ return i * 2}printfor i in result { print("操作后结果为 \}print

先分享两个好的学习网站慕课网
极客学院

        $(“#testAF”).click(function () {
$(“div[id]”).css(“background”, “red”); });
        $(“#testAF1”).click(function () {
$(“div[id=’aadiv22′]”).css(“background”, “#EDE”); });
        $(“#testAF2”).click(function () {
$(“div[id=’aadiv22′]”).css(“background”, “#EAE”); });
        $(“#testAF3”).click(function () {
$(“input[name$=’bb’]”).css(“background”, “#EHE”); });
        $(“#testAF4”).click(function () {
$(“div[id$=’11’]”).css(“background”, “#EUE”); });
    </script>
</head>
<body>
    <div id=”divMsg”>Hello world!</div>
    <input type=”button” id=”btnShow” value=”显示” />
    <div id=”divParent”><div
id=”divChild”>ddddd</div><div
id=”div1″>ddddd</div><input type=”button” id=”btnHide”
value=”隐藏” /></div>
    <input type=”button” id=”btnChange”  value=”修改后的结果为hello
world,too!” />
    <input type=”button” id=”alterColor”  value=”改变红色颜色”/>
    <input type=”button” id=”Button3″ value=”改变为蓝色”/>
    <input type=”button” id=”alterTableColor” title=”13″
value=”改变表格的颜色”/>
    <input type=”button” id=”testBT” value=”测试基本过滤器”/>
    <input type=”checkbox” id=”ck” value=”是” 
checked=”checked”/>
    <input type=”button” id=”testCK” value=”测试ck” />
    <input type=”button” id=”Button2″ title=”13″  value=”dddd”/>
    <table class=”tab”>
        <tr>
            <td class=”style2″>
                 </td>
            <td class=”style3″>
                 </td>
            <td class=”style4″>
                 </td>
            <td>
                 </td>
        </tr>
        <tr>
            <td class=”style2″>
                 </td>
            <td class=”style3″>
               </td>
            <td class=”style4″>
                </td>
            <td>
                <div>djjjjjjjj</div></td>
        </tr>
        <tr>
            <td class=”style2″>
                 </td>
            <td class=”style3″>
                 </td>
            <td class=”style4″>
                 </td>
            <td>
                 </td>
        </tr>
        <tr>
            <td class=”style2″>
                 </td>
            <td class=”style3″>
                 </td>
            <td class=”style4″>
                 </td>
            <td>
                 </td>
        </tr>
    </table>
    <div id=”CF”>aa内容过滤器的测试</div>
    <input id=”testCf” type=”button” value=”内容过滤器测试”/>
    <input id=”testCF” type=”button” value=”内容过滤器测试2″/>
    <div id=”aadiv11″>
        <div>dddddddddd
            <div>ddddddddd</div>
            <div>ddddddddd</div>
        </div>
    </div>
    <div  id=”aadiv22″>gfffffffffff
        <div>ddddddd
            <div>ddddddddd</div>
            <div>ddddd</div>
        </div>
    </div>
    <div  id=”bbdiv22″ class=”divclass”>gfffffffffff
    <div>ddddddd
        <div>ddddddddd</div>
        <div>ddddd</div>
    </div>
    </div>
    <input id=”testAF” type=”button”
value=”属性过滤器测试含有id的变色”/>
    <input id=”testAF1″ type=”button”
value=”属性过滤器测试1id为aadiv22的变色”/>
    <input id=”testAF2″ type=”button”
value=”属性过滤器测试2id不为aa的变色”/>
    <input id=”testAF3″ type=”button”
value=”属性过滤器测试3含有以name结尾的input变色”/>
    <input id=”testAF4″ type=”button” value=”属性过滤器测试4″/>
    <input id=”testAF5″ type=”button”
value=”属性过滤器测试5选择所有含有id为div的变色”/>
    <input id=”testAF6″
value=”属性过滤器测试5选择所有含有id为div的变色” type=”button”/>
    <input id=”testButton” value=”表单选择器”
type=”button”/>        
</body>
</html>
    <script type=”text/javascript”>
        var dom = document.getElementById(“btnHide”);
        jquery = $(dom);
        $(“#btnShow”).bind(“click”, function (event) {
$(“#divMsg”).show(); });
        jquery.bind(“click”, function (event) { $(“#divMsg”).hide();
});
        $(“#btnChange”).bind(“click”, function (envent) {
$(“#divMsg”).html(“Hello World, too!”); });
        $(“#Button3”).click(function () {
$(“#divParent+input”).css(“background”, “blue”); });
//下面的按钮可以控制上面的以下所有的按钮
        $(“#alterColor”).click(function () {
$(“#Button3~[id]”).css(“background”, “red”); });
        $(“#alterTableColor”).click(function () { $(“.tab tr:first
td”).css(“background”, “green”); });
        $(“#testBT”).click(function () { $(“body
input:odd”).css(“background”, “red”); });
        $(“#testCK”).click(function () {
$(“input:checked”).css(“background”, “red”); });
        $(“#testCf”).click(function () {
$(“div:contains(‘aa’)”).css(“background”, “red”); });
        $(“#testCF”).click(function () {
$(“td:parent”).css(“background”, “red”); });

图片 1结果.png

首先说下Swift和OC的区别,在工程上OC是分为.h和.m文件的,一个声明文件,一个实现文件,而在Swift工程中只有一个文件,就是.Swift文件,声明,导入文件都在这一个文件夹里来操作的。导入
不需要再到类名 所有类名都是公开的 可以直接访问到
导入框架: 直接导入框架名 如 import UIKit
OC程序入口是main函数
swift代码是从上往下执行 @UIApplicationMain 程序的入口
class 是用来声明类的 class后面是类名 冒号后面是继承的父类
导入协议或者代理的时候直接在父类的后面加逗号和代理或协议的名字。
例如

        $(“#testAF”).click(function () {
$(“div[id]”).css(“background”, “red”); });
        $(“#testAF1”).click(function () {
$(“div[id=’aadiv22′]”).css(“background”, “#EDE”); });
        $(“#testAF2”).click(function () {
$(“div[id!=’aa’]”).css(“background”, “#EAE”); });
        $(“#testAF3”).click(function () {
$(“div[id^=’aa’]”).css(“background”, “#aaaddd”); });
        $(“#testAF4”).click(function () {
$(“div[id$=’22’]”).css(“background”, “#aaa111”); });
        $(“#testAF5”).click(function () {
$(“div[id*=’div’]”).css(“background”, “#aaa111”); });
        $(“#testAF6”).click(function () {
$(“div[class][id^=’bb’]”).css(“background”, “#aaa111”); });
        $(“#testButton”).click(function () {
$(“input”).css(“background”, “red”); });
    </script>

let data = 1...3let result = data.map {  -> Int in print("正在处理 \ return i * 2}printfor i in result { print("操作后结果为 \}print
class AppDelegate: UIResponder, UIApplicationDelegate{
}

图片 2结果.png

另外如果我们要声明一个变量,在OC里面都是类名
对象名,然后进行复制,在Swift中所有的变量都用var来定义,所有的常量都用let定义,公式为

var 名字 :数据类型 =值

值得一提的是,Swift中是支持中文编码格式的,甚至你还可以把对象名命名为表情,比如

struct Person { let name: String let age: Int}let xiaoMing = Person(name: "XiaoMing", age: 26)let r = Mirror(reflecting: xiaoMing) // r 是 MirrorTypexiaoMing.selffor child in r.children { print("属性名:\(String(describing: child.label)),值:\(child.value)")}// KVC获取值func valueFrom(_ object: Any, key: String) -> Any? { let mirror = Mirror(reflecting: object) for child in mirror.children { let (targetKey, targetMirror) = (child.label, child.value) if key == targetKey { return targetMirror } } return nil}dumpdump(valueFrom(xiaoMing, key: "name"))
    let 🐶:String = "hello world"
    print(🐶 + "可以和海绵宝宝做朋友吗")
//Swift中可以直接用+来拼接字符串

图片 3结果png

这就是说为什么这门语言很开放,但是我们如果这样写

    • “在 Objective-C 中,使用 -class
      方法就可以拿到对象的类,我们甚至可以用 NSStringFromClass
      将它转换为一个能够打印出来的字符串:

      NSString *str = [[NSString alloc] init];NSLog(@"%@",NSStringFromClass([str class]));”
      
    • “在 Swift 中,为了获取一个 NSObject
      或其子类的对象的实际类型,对这个调用其实有一个好看一些的写法,那就是
      type。”

       let date = NSDate() let name = type print // 输出: __NSDate 
      
    • “当然,在Swift中我们可以求助于 Objective-C
      的运行时,来获取类并按照原来的方式转换:

      let date = NSDate()let name: AnyClass! = object_getClassprint// 输出: __NSDate
      

    其中 object_getClass 是一个定义在 ObjectiveC 的 runtime
    中的方法,它可以接受任意的 AnyObject! 并返回它的类型 AnyClass!
    (注意这里的叹号,它表明我们甚至可以输入 nil,并期待其返回一个
    nil)。”

    let 🐶:NSString = "hello world"
    print(🐶 + "可以和海绵宝宝做朋友吗")

他就会说,🐶的类型和”内容”类型不同,不能进行拼接,你必须把它转化成String类型才能进行拼接,在Swift中类型一定要精确,否则他就会提示报错,而且,写法一定要正规,多一个空格少一个空格他都会给你莫名的报错。

另外在Swift中一段代码的结束可以不用;结尾,但是一行如果有多句代码要用;来隔开,其实加上也是不会报错的。

“KVO (Key-Value Observing) 是 Cocoa
中公认的最强大的特性之一,但是同时它也以烂到家的 API
和极其难用著称。和属性观察不同,KVO
的目的并不是为当前类的属性提供一个钩子方法,而是为了其他不同实例对当前的某个属性
(严格来说是 keypath)
进行监听时使用的。其他实例可以充当一个订阅者的角色,当被监听的属性发生变化时,订阅者将得到通知。

还有一点Swift因为现在还不算太完善,如果你在声明一个变量的时候,在后面并没有改变他的值,他会提醒你,你可以赋值为常量,但是不要管他,也不会有错误的。

这是一个很强大的属性,通过 KVO
我们可以实现很多松耦合的结构,使代码更加灵活和强大:像通过监听 model
的值来自动更新 UI 的绑定这样的工作,基本都是基于 KVO 来完成的。

在Swift中还有一点很神奇的地方就是,它可以自行推断数据类型,这在其他所有语言中都是有违背常理的,一个数据的产生必定要随之伴随着他的类型,但是在Swift中它却可以自行推断数据类型来进行判断,因为在Swift中加入了几种新的判断,例如可选数据类型,明确数据类型,判断数据类型,就是说你在定义一个数据的时候他还没有明确的去使用,也可以选择它的数据类型,所以在这点Swift还是很严谨的

在 Swift 中我们也是可以使用 KVO 的,而且在 Swift 4 中,结合
KeyPath,Apple 为我们提供了非常漂亮的一套新的 API。不过 KVO 仅限于在
NSObject 的子类中,这是可以理解的,因为 KVO 是基于 KVC (Key-Value
Coding) 以及动态派发技术实现的,而这些东西都是 Objective-C
运行时的概念。另外由于 Swift 为了效率,默认禁用了动态派发,因此想用
Swift 来实现
KVO,我们还需要做额外的工作,那就是将想要观测的对象标记为dynamic和@objc

let 字符串 = "我是字符串"
print(字符串)
let 年龄 = 12
print(年龄)

在 Swift 4 之前的版本中,为一个 NSObject 的子类实现 KVO
的最简单的例子看起来是这样的:

我们可以这样证实一下是不是确实可以自行推断数据类型

class MyClass: NSObject { @objc dynamic var date = Date()}private var myContext = 0class Class: NSObject { var myObject: MyClass! override init() { super.init() myObject = MyClass() print("初始化 MyClass,当前日期: \(myObject.date)") myObject.addObserver(self, forKeyPath: "date", options: .new, context: &myContext) delay { self.myObject.date = Date() } } override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?,context: UnsafeMutableRawPointer?) { if let change = change, context == &myContext { if let newDate = change[.newKey] as? Date { print("MyClass 日期发生变化 \") } } }}let obj = Class()/*输出应该类似于:初始化 Class,当前日期: 2017-10-26 08:50:24 +0000Class 日期发生变化 2017-10-26 08:50:27 +0000*/

如果声明变量的时候不想在声明的时候去赋值 必须填上变量的数据类型
什么都没给他 没有推断的依据 推断不出

Swift 4 中 Apple 引入了新的 KeyPath
的表达方式,不需要传Context去区分是那个变量发生了改变,监听方式改为闭包模式

然后我们说一下Swift中方法的声明和调用
就拿一个APPDelegate里面函数来说明吧

var observation: NSKeyValueObservation?observation = myObject.observe(\MyClass.date, options: [.new]) { (_, change) in if let newDate = change.newValue { print("AnotherClass 日期发生变化 \") }}// 值得注意的是:必须要用属性observation赋值 否则不会调用闭包里面的代码
swift:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
return true
}
OC:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    return YES;
}

比较一下Swift里面声明都是用func来声明,后面是方法名,接着是一个小括号,无参数就不填内容,有参数就填写参数类型,顺带提一下Swift里面打mark标记也不同,直接使用//MARK:标题内容来标记,有一点,在Swift中是没有BOOL类型的,他是纯粹的Bool类型,既,是或者非,没有1,0,YES
NO这一说,所以return得都是true或者false

无并发,不编码。而只要一说到多线程或者并发的代码,我们可能就很难绕开对于锁的讨论。简单来说,为了在不同线程中安全地访问同一个资源,我们需要这些访问顺序进行。Cocoa
和 Objective-C 中加锁的方式有很多,但是其中在日常开发中最常用的应该是
@synchronized,这个关键字可以用来修饰一个变量,并为其自动加上和解除互斥锁。这样,可以保证变量在作用范围内不会被其他线程改变。举个例子,如果我们有一个方法接受参数,需要这个方法是线程安全的话,就需要在参数上加锁:

func 方法名 (){
    print("无返回值不带餐的函数")
}


//MARK:无返回值  代餐
func 有参方法(参数名:NSString)  {
print("你好,我是有残方法")
}

//MARK:带参有返回值

func 有参有返回方法(参数名1:String , 参数名2:String) -> String {
return 参数名1 + 参数名2

}
-myMethod:anObj { @synchronized { // 在括号内持有 anObj 锁 }}

无视那些卖萌的错别字=。=虽然可以用汉语,但是并不提倡这一点,大家定义的时候尽量还是用英文命名。。逼格也高一些。。

如果没有锁的话,一旦 anObj
的内容被其他线程修改的话,这个方法的行为很可能就无法预测了。但是加锁和解锁都是要消耗一定性能的,因此我们不太可能为所有的方法都加上锁。另外其实在一个
app
中可能会涉及到多线程的部分是有限的,我们也没有必要为所有东西加上锁。过多的锁不仅没有意义,而且对于多线程编程来说,可能会产生很多像死锁这样的陷阱,也难以调试。因此在使用多线程时,我们应该尽量将保持简单作为第一要务。”“虽然这个方法很简单好用,但是很不幸的是在
Swift 中它已经 不存在了。其实 @synchronized 在幕后做的事情是调用了
objc_sync 中的 objc_sync_enter 和 objc_sync_exit
方法,并且加入了一些异常判断。因此,在 Swift
中,如果我们忽略掉那些异常的话,我们想要 lock 一个变量的话,可以这样写:

然后在程序中调用一下,调用的时候直接是方法名(参数)

func myMethod(anObj: AnyObject!) { objc_sync_enter // 在 enter 和 exit 之间持有 anObj 锁 objc_sync_exit}
    var 参数:NSString = "🐶"
    有参方法(参数)
    print(有参有返回方法("123", 参数名2:"12344" ))

“如果我们喜欢以前的那种形式,甚至可以写一个全局的方法,并接受一个闭包,来将
objc_sync_enter 和 objc_sync_exit 封装起来:

要注意的是如果你要调用其他类的方法的时候要用.来调用,比如我创建一个UIView的类,在里面写了个叫视图方法的方法,需要传一个字符串的参数进去,那么我调用的时候。

func synchronized(_ lock: AnyObject, closure: () ->  { objc_sync_enter closure() objc_sync_exit}
 //快捷创建对象
 //        创建带有frame的
 //        let view:MyView = MyView(frame:CGRectMake(123,123,123,123))
    let view:MyView = MyView()

    view.frame = CGRectMake(123, 123, 123, 123);
    view.backgroundColor = UIColor .redColor()
    print(view .视图方法("字符串参数"))

    self.view .addSubview(view)

再结合 Swift 的尾随闭包的语言特性,这样,使用起来的时候就和 Objective-C
中很像了:

还有一点,在Swift中是提倡使用区间来定义范围的,在Swift中有全闭合区间,和半闭合区间之分,全闭合即包括区间内所有元素,半闭合区间是由第一个元素到倒数第二个元素。定义的方式也不同
1 2 3 4 5
全闭合区间 1…5//三个点
1 2 3 4 (5)
半闭合区间 1..5//两个点
在Swift中是提倡使用区间来定义的

func myMethodLocked(anObj: AnyObject!) { synchronized { // 在括号内持有 anObj 锁 }}
let titles = ["标题1" , "标题2" , "标题3"]
for (var i = 0;i < titles.cout; i += 1){
            vc.title = titles[i]
    }

举一个具体的使用例子,比如我们想要为某个类实现一个线程安全的
setter,可以这样进行重写:

还有一点,Xode7.3之后 ++将在swift3中弃用 改成+=
在做数据类型转换的时候
swift 不同的数据类型 不允许计算
数据类型转换 数据类型(要转换的变量名)

// 一个实际的线程安全的 setter 例子class Obj { var _str = "123" var str: String { get { return _str } set { synchronized { _str = newValue } } // 下略 }}

在遍历的时候大家注意,这点我在学习的时候差点报警,在判断的时候,比如i
<
5,如果i和<中间有空格,则右侧也要有空格,如果没有,就都不要有,不然就会报错,写法一定要严谨,最好都加上空格,看起来也清晰,另外for循环的条件可以不用加括号,当然加上也没有错误,这点我当时真的是要报警了

暂时先写这么多,前面网站里面都会有相应的视频,老师也都很不错。在这里主要写一些容易遇到的错误等,有空再来写一下选择类型。

Swift 本身从设计上来说是一门非常安全的语言,在 Swift
的思想中,所有的引用或者变量的类型都是确定并且正确对应它们的实际类型的,你应当无法进行任意的类型转换,也不能直接通过指针做出一些出格的事情。这种安全性在日常的程序开发中对于避免不必要的
bug,以及迅速而且稳定地找出代码错误是非常有帮助的。但是凡事都有两面性,在高安全的同时,Swift
也相应地丧失了部分的灵活性。

现阶段想要完全抛弃 C 的一套东西还是相当困难的,特别是在很多上古级别的 C
API 框架还在使用 。开发者,尤其是偏向较底层的框架的开发者不得不面临着与
C API 打交道的时候,还是无法绕开指针的概念,而指针在 Swift定义了一套对 C
语言指针的访问和转换方法,那就是 UnsafePointer
和它的一系列变体。对于使用 C API
时如果遇到接受内存地址作为参数,或者返回是内存地址的情况,在 Swift
里会将它们转为 UnsafePointer<Type> 的类型,比如说如果某个 API 在 C
中是这样的话:

void method(const int *num) { printf("%d",*num);}其对应的 Swift 方法应该是:func method(_ num: UnsafePointer<CInt>) { print(num.pointee)}

我们这个 tip 所说的 UnsafePointer,就是 Swift
中专门针对指针的转换。对于其他的 C 中基础类型,在 Swift
中对应的类型都遵循统一的命名规则:在前面加上一个字母 C
并将原来的第一个字母大写:比如 int,bool 和 char
的对应类型分别是CInt,CBool 和 CChar。在上面的 C 方法中,我们接受一个
int 的指针,转换到 Swift 里所对应的就是一个 CInt 的 UnsafePointer
类型。这里原来的 C API 中已经指明了输入的 num 指针的不可变的 ,因此在
Swift 中我们与之对应的是 UnsafePointer
这个不可变版本。如果只是一个普通的可变指针的话,我们可以使用
UnsafeMutablePointer 来对应:

C API Swift API
const Type * UnsafePointer
Type * UnsafeMutablePointer

在 C 中,对某个指针进行取值使用的是 *,而在 Swift 中我们可以使用 memory
属性来读取相应内存中存储的内容。通过传入指针地址进行方法调用的时候就都比较相似了,都是在前面加上
& 符号,C 的版本和 Swift 的版本只在声明变量的时候有所区别:

// Cint a = 123;method; // 输出 123// Swiftvar a: CInt = 123method // 输出 123

遵守这些原则,使用 UnsafePointer 在 Swift 中进行 C API
的调用应该就不会有很大问题了。“另外一个重要的课题是如何在指针的内容和实际的值之间进行转换。比如我们如果由于某种原因需要涉及到直接使用
CFArray 的方法来获取数组中元素的时候,我们会用到这个方法:

func CFArrayGetValueAtIndex(theArray: CFArray!, idx: CFIndex) -> UnsafePointer<Void>

因为 CFArray
中是可以存放任意对象的,所以这里的返回是一个任意对象的指针,相当于 C
中的 void *。这显然不是我们想要的东西。Swift
中为我们提供了一个强制转换的方法
unsafeBitCast,通过下面的代码,我们可以看到应当如何使用类似这样的
API,将一个指针强制按位转成所需类型的对象:

let arr = NSArray(object: "meow")let str = unsafeBitCast(CFArrayGetValueAtIndex, to: CFString.self)// str = "meow

“unsafeBitCast
会将第一个参数的内容按照第二个参数的类型进行转换,而不去关心实际是不是可行,这也正是
UnsafePointer
的不安全所在,因为我们不必遵守类型转换的检查,而拥有了在指针层面直接操作内存的机会。

其实说了这么多,Apple 将直接的指针访问冠以 Unsafe
的前缀,就是提醒我们:这些东西不安全,亲们能不用就别用了吧 (作为
Apple,另一个重要的考虑是如果避免指针的话可以减少很多系统漏洞)!在日常开发中,我们确实不太需要经常和这些东西打交道
(除了传入 NSError 指针这个历史遗留问题以外,而且在 Swift 2.0
中也已经使用异常机制替代了
NSError)。总之,尽可能地在高抽象层级编写代码,会是高效和正确的有力保证。无数先辈已经用血淋淋“的教训告诉我们,要避免去做这样的不安全的操作,除非你确实知道你在做的是什么。”

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图