0%

1、SiriKit

SiriKit 提供一全套从语音识别到代码处理,最后向用户展示结果的流程。Apple 加入了一套全新的框架 Intents.framework 来表示 Siri 获取并解析的结果。你的应用需要提供一些关键字表明可以接受相关输入,而 Siri 扩展只需要监听系统识别的用户意图 (intent),作出合适的响应,修改以及实际操作,最后通过 IntentsUI.framework 提供反馈。 在 iOS 10 中,我们只能用 SiriKit 来做六类事情,分别是:语音和视频通话、发送消息、发送或接收付款、搜索照片、约车、管理健身。如果你的应用恰好正在处理这些领域的问题的话,添加 Intents Extension 的支持会是很棒的选择。它将提高用户使用你的应用的可能性,也能让用户在其他像是地图这样的系统级应用中使用你的服务。

2、 iMessage App Extension

在 iOS 10 里面开发者可以给 Message.app 提供两种 App Extension,分别是可以提供一个表情包(没错,英文名就叫 Sticker Pack),和一个自定义的界面,用于表情搜索等。添加了新的贴纸包,自动转换颜文字,发送全屏效果等功能。Xcode 8 中添加了Messages Application模板。同时,模拟器甚至还开发了新的双人对话模式,以供开发者调试这类 app。

阅读全文 »

编译器

先了解一下编译器相关的LLVM和Clang:

LLVM

LLVM是构架编译器(compiler)的框架系统,以C++编写而成,可以作为多种语言编译器的后台来使用,用于优化以

阅读全文 »

UDP:User Datagram Protocol,用户数据报协议。

UDP特点

  • 不建立连接

    传输数据之前源端和终端不建立连接,发送数据时就简单地抓取来自应用程序的数据,并尽可能快地把它扔到网络上;

    在发送端,UDP传送数据的速度只受应用程序生成数据的速度、计算机的能力和传输带宽的限制;

    在接收端,UDP把每个消息段放在队列中,应用程序每次从队列中读取一个消息段;

    由于传输数据不建立连接,因此也就不需要维护连接状态,包括收发状态等,因此一台服务器可以同时向多个客户端传输相同的消息。

  • 简单:在发送端和接收端没有连接状态,每个数据报都是独立被处理的

  • 开销小:UDP的首部很短,只有8个字节,相对于TCP的20个字节额外开销很小

  • 无拥塞控制和流量控制:UDP可以尽可能快地发送报文;吞吐量只受应用程序生成数据的速率、传输带宽、源端和终端主机性能的限制。

  • UDP使用尽最大努力交付,可能丢失、可能乱序。

  • UDP是面向报文的:发送方的UDP对应用程序来的报文在添加首部后就向下交付给IP层,既不拆分,也不合并,而是保留这些报文的边界。因此,应用程序需要选择合适的报文大小。

    阅读全文 »

Swift中,基本类型(Array、Dictionary、Int、String等)都是值类型,它们都是用结构体实现的。在使用Swift时,应优先使用struct实现数据建模,只在需要的时候才使用class。

不能改变声明为常量的值类型实例的属性。

可以改变声明为常量的引用类型实例的属性。

Swift在语言层面没有提供深复制的支持,所以Swift中的复制是浅复制。

Swift对值类型的赋值行为会不会对性能产生影响?答案是取决于数据和用法。

阅读全文 »

1
2
3
var name : String? = nil
name?.append("baylee")
let nameDes = name ?? "zry"

对于可选实例name,如果name有值,将name赋值给nameDes,如果name为nil,赋值"zry"nameDes

??为nil合并运算符,左边必须是可空实例,右边必须是非可空的同类型实例。如果左边为nil,则返回右边的值,否则返回左边的值。

阅读全文 »

可空类型

可空类型指某个实例可能没有值,任何类型都可以用可空类型来说明一个实例可能是nil。可空类型让Swift这门语言更加安全。

一个可能为nil的实例应该被声明为可空类型。没有被声明为可空类型的实例不可能为nil。

  1. 声明时在类型后加?

    1
    2
    3
    4
    var errorCodeString: String?
    errorCodeString = "404"
    print(errorCodeString)
    //打印结果是Optional("404")
  2. 访问时需要强制展开,实例后加!

    阅读全文 »

可空链式调用和可空实例绑定区别:可空链式调用允许程序员把多个查询串联为一个可空实例的值。如果链式调用中的每个可空实例都包含之,那么每个调用都会成功。整个查询链会返回期望类型的可空实例。如果查询链式中的任意可空实例是nil,那么整个链式调用会返回nil。

示例:如果遇到404错误,就用自定义错误码及展示给用户的错误描述代替

1
2
3
4
5
6
7
var errorCodeString : String!
errorCodeString = "404"
var errorDescription: String?
if let theError = errorCodeString, let errorCodeInteger = Int(theError), errorCodeInteger == 404 {
errorDescription = "\(errorCodeInteger + 200): resource was not found"
}
var upcaseDescription = errorDescription?.uppercased()

重点在于最后一句代码!!!

阅读全文 »

TCP特点

  • 点对点:一个发送方,一个接收方
  • 可靠的、按顺序的字节流:没有报文边界
  • 管道化(流水线):TCP拥塞控制和流量控制设置窗口大小(GBN和SR)
  • 发送和接收缓存
  • 全双工数据:在同一连接中数据双向流动
  • 面向连接:在数据交换之前,通过握手(交换控制报文)初始化发送方、接收方的状态变量
  • 有拥塞控制:发送方不会淹没接收方

TCP报文结构

  • 序号:报文段首字节在字节流的编号
  • 确认号:期望从另一方收到的下一个字节的序号,是个累计确认(ACK n表示确认n-1及以前的字节)
  • 序号和确认号都是以字节为单位的,用来实现可靠数据传输服务
  • 接收窗口:表示愿意接收的字节数量,用于流量控制
  • 可选与边长的选项字段:用于发送方和接收方协商最大报文长度MSS
  • 标志字段:
    • ACK:表示该报文段包含一个对已被成功接收报文段的确认
    • RST、SYN、FIN用于连接的建立和拆除
  • 接收方如何处理乱序的报文段是没有规定的

关于序号和确认号:

TCP把数据看成是一个无结构的、有序的字节流。所以TCP的序号和确认号都是建立在传送的字节流之上,而不是建立在传送的报文段的序号之上。

TCP的三次握手和四次挥手

三次握手

  1. 客户端TCP向服务器TCP发送一个建立连接的请求,将自己的初始序号(随机选择的,不一定是从0开始的)发送给对方;
    • 客户端的TCP会向服务器端发送一个特殊的TCP报文段。这个报文段不包含应用层数据。
    • 该报文段的首部中的一个标志位SYN被置为1,这个报文因此被称为SYN报文段
    • 客户端会随机选择一个初始序号放置于该SYN报文段的序号字段中
    • 该报文段会被封装在一个IP数据报中发送给服务器
  2. 服务端TCP向客户端TCP发送一个建立连接的确认,并把自己的初始序号发送给客户端TCP;
    • 服务器接收到IP数据报后,从数据包中提取 出SYN报文段,为该TCP连接分配TCP缓存和变量,并向该客户端TCP发送允许连接的报文段
    • 报文段包含内容:
      • SYN被置为1
      • 报文段首部的确认序号字段为接收到的序号+1
      • 服务端选择自己的的初始序号,并放到报文段首部的序号字段中
  3. 客户端向服务端发送对服务端的初始序号的确认
    • 客户端收到SYN+ACK报文段后,客户端也要给该连接分配缓存和变量。并向服务器发送对服务器允许连接的报文段进行确认的报文段(可以携带数据)。
    • 此时连接建立完成,SYN比特被置为0

客户和服务器主机可以开始互相发送包含数据的报文段了,以后每一个报文段中,SYN比特都将被置为0。

阅读全文 »

默认初始化方法

  1. 类没有成员初始化方法;
  2. 类拥有空初始化方法条件:类的所有属性都有默认值 && 没有自定义初始化方法。

自定义初始化方法

  1. 指定初始化方法

    • 指定初始化方法用关键字init表示;
    • 如果有父类,则子类的指定初始化方法必须调用父类的指定初始化方法。
    • 子类在初始化方法的最后调用父类的初始化方法。因为子类的初始化方法负责为自己引入的所有属性赋值,子类属性赋值后,再调用父类的初始化方法,以便父类初始化自己的属性。
      阅读全文 »

[obj autorelease];的实质是:

向autoreleasepool中添加obj,即 [pool addObject:obj];

autoreleasepool在被废弃的时候会向pool中所有发送过autorelease的对象发送release消息,对象的引用计数减1。(并不一定就会被释放,可能引用计数减1后仍然>0)

对于每一个Runloop, 系统会隐式创建一个Autorelease pool,这样所有的release pool会构成一个象CallStack一样的一个栈式结构,在每一个Runloop结束时,当前栈顶的Autorelease pool会被销毁,这样这个pool里的每个Object会被release。

阅读全文 »