Core Foundation框架是苹果公司提供一套概念来源于Foundation框架,编程接口面向C语言风格的API。虽然在Swift中调用这种C语言风格的API比较麻烦,但是在OS X和iOS开发过程中,有时候使用CoreFoundation框架的API是非常方便的,例如在与C语言混合编码的时候。

Core Foundation框架与Foundation框架紧密相关,他们具有与相同的接口,但是不同。Core Foundation框架是基于C语言风格的,而Foundation框架是基于Objective-C语言风格的。在OS X和iOS程序代码中经常会有多种语言风格的代码混合在一起的情况,这使得我们开发变得更加麻烦。

数据类型映射

Core Foundation框架提供了一些不透明的数据类型,这些数据类型封装了一些数据和操作,他们也可以称为“类”,他们都继承于CFType类,CFType是所用Core Foundation框架类型的根类。这些数据类型在Foundation框架中都有相应的数据类型与之对应,这些数据类型也有一些与Swift原生数据类型有对应关系。

看看Swift原生类型与Core Foundation类型之间的转换示例:

  1. import CoreFoundation
  2. import Foundation
  3. var cfstr1: CFString = "Hello,World"     //创建CFString字符串
  4. var str: String = cfstr1 as String           //将CFString字符串转换为Swift原生字符串String
  5. var cfstr2: CFString = str                   //将Swift原生字符串String转换为CFString字符串

这个转换过程中Core Foundation类型转换为Swift原生类型是需要强制类型转换的。

Swift原生数据类型、Foundation框架数据类型和Core Foundation框架数据类型之间转换过程中,虽然是大部分是可以零开销桥接,零开销并不意味着内存什么都不用管。Swift类型内存管理是采用ARC,Foundation类型和Core Foundation类型内存管理都是采用MRC或ARC,CoreFoundation类型内存管理是基于C语言风格的,它有一个对象所有权的概念。

Objective-C的MRC内存管理

Core Foundation的内存管理与Objective-C的MRC内存管理密不可分,先介绍一下Objective-C的MRC内存管理。

所有Objective-C类都继承NSObject类,每个NSObject对象都有一个内部计数器,这个计数器跟踪对象的引用次数,被称为“引用计数”(Reference Count,简称RC)。当对象被创建时候,引用计数为1。为了保证对象的存在,可以调用retain方法保持对象,retain方法会使其引用计数加1,如果不需要这个对象可以调用release或autorelease方法,release或autorelease方法使其引用计数减1。当对象的引用计数为0的时候,系统运行环境才会释放对象内存。

引用计数示例如图所示,首先在第①步调用者A中创建了一个NSObject对象,这时该对象引用计数为1。在第②步调用者B中想使用这个NSObject对象,于是使用NSObject对象引用,但是为了防止使用过程中NSObject对象被释放,可以调用retain方法使引用计数加1,这时引用计数为2。在第③步调用者A中调用release或autorelease方法,使引用计数减1,这时引用计数为1。在第④步调用者C中调用release或autorelease方法,只是获得NSObject对象引用,并没有调用retain、release或autorelease方法,因此没有引起引用计数的变化。在第⑤步调用者B中调用release或autorelease方法使引用计数减1,这时引用计数为0。这个时候NSObject对象就内存就可以释放了。

来总结一下:

1. 谁创建或拷贝对象,他也一定要负责调用NSObject对象release或autorelease方法,使引用计数减1,如图中调用者A在第①步,负责创建了NSObject对象,那么调用者A也必须是负责使引用计数减1,见第④步。

2. 谁调用retain方法使引用计数加1,它也一定要负责调用NSObject对象release或autorelease方法,使引用计数减1,如图中调用者B在第②步,调用者B调用NSObject对象retain方法使引用计数加1,那么调用者B也必须是负责使引用计数减1,见第⑤步。

对象所有权

一个对象可以有一个或多个所有者,从所有者的角度看是对这个对象具有了“所有权”,从上图中看,调用者A和调用者B是所有者,他们可能是一段程序,可能是一个对象。他们对NSObject对象具有所有权,不再使用时候他们应该负责放弃对象所有权,当对象没有所有者时,引用计数为0,它才可以被释放。

如上图如果按照对象所有权解释:调用者A创建或拷贝NSObject对象,这时调用者A就具有了NSObject对象的所有权,见第①步。调用者B调用NSObject对象retain方法,就获得了也NSObject对象的所有权,见第②步。调用者A调用NSObject对象release方法,放弃NSObject对象的所有权,见第③步。调用者C只是使用NSObject对象没有获得NSObject对象的所有权,见第④步。调用者B调用NSObject对象release方法,放弃NSObject对象的所有权,见第⑤步,但是调用者B使用这个NSObject对象过程中,由于其他调用者放弃所有权,导致NSObject对象被释放,那么调用者B中程序就会发生运行期错误。

======================

内存托管对象

Swift中调用CoreFoundation函数获得对象时候,对象分为:内存托管对象和内存非托管对象。

内存托管对象就是由编译器帮助管理内存,我们不需要调用CFRetain函数获得对象所有权,也不需要调用CFRelease函数放弃对象所有权。

获得这些内存托管对象的方法,是采用了CF_RETURNS_RETAINED或CF_RETURNS_NOT_RETAINED注释声明,示例代码:

  1. -(CGPathRef)makeToPath CF_RETURNS_RETAINED
  2. {
  3. UIBezierPath* triangle = [UIBezierPath bezierPath];
  4. [triangle moveToPoint:CGPointZero];
  5. [triangle addLineToPoint:CGPointMake(self.view.frame.size.width,0)];
  6. [triangle addLineToPoint:CGPointMake(0, self.view.frame.size.height)];
  7. [triangle closePath];
  8. CGPathRef theCGPath = [triangle CGPath];
  9. return CGPathCreateCopy(theCGPath);
  10. }

内存托管对象使用起来比较简单,不需要我们做额外的事情。

  1. func CFStringCreateWithCString(_ alloc: CFAllocator!,
  2. _ cStr: UnsafePointer<Int8>,
  3. _ encoding: CFStringEncoding) -> CFString!  //内存托管对象
  4. func CFHostCreateCopy(_ alloc: CFAllocator?,
  5. _ host: CFHost) -> Unmanaged<CFHost>    //内存非托管对象

内存非托管对象

内存非托管对象就是内存需要程序员自己管理。这是由于在获得对象的方法中没有使用CF_RETURNS_RETAINED或CF_RETURNS_NOT_RETAINED注释声明,编译器无法帮助管理内存。在具体使用时候我们可以上一节的方法判断是否为非内存托管对象。

内存非托管对象使用起来有些麻烦,要根据获得所有权方法,进行相应的处理。

1. 如果一个函数名中包含Create或Copy,则调用者获得这个对象的同时也获得对象所有权,返回值Unmanaged<T>需要调用takeRetainedValue()方法获得对象。调用者不再使用对象时候,Swift代码中需要调用CFRelease函数放弃对象所有权,这是因为Swift是ARC内存管理的。

2. 如果一个函数名中包含Get,则调用者获得这个对象的同时不会获得对象所有权,返回值Unmanaged<T>需要调用takeUnretainedValue()方法获得对象。

示例代码如下:

    1. let host: CFHost = CFHostCreateWithName(kCFAllocatorDefault,
    2. Ê"127.0.0.1").takeRetainedValue()
    3. let hostNames: CFArray = CFHostGetNames(host, nil)!.takeUnretainedValue()

Swift—Core Foundation框架-备的更多相关文章

  1. 《从零开始学Swift》学习笔记(Day 61)——Core Foundation框架之内存管理

    原创文章,欢迎转载.转载请注明:关东升的博客 在Swift原生数据类型.Foundation框架数据类型和Core Foundation框架数据类型之间转换过程中,虽然是大部分是可以零开销桥接,零开销 ...

  2. 《从零开始学Swift》学习笔记(Day60)——Core Foundation框架

    原创文章,欢迎转载.转载请注明:关东升的博客 Core Foundation框架是苹果公司提供一套概念来源于Foundation框架,编程接口面向C语言风格的API.虽然在Swift中调用这种C语言风 ...

  3. 《从零開始学Swift》学习笔记(Day 61)——Core Foundation框架之内存管理

    原创文章,欢迎转载. 转载请注明:关东升的博客 在Swift原生数据类型.Foundation框架数据类型和Core Foundation框架数据类型之间转换过程中,尽管是大部分是能够零开销桥接,零开 ...

  4. 《从零開始学Swift》学习笔记(Day60)——Core Foundation框架

    创文章,欢迎转载.转载请注明:关东升的博客   Core Foundation框架是苹果公司提供一套概念来源于Foundation框架,编程接口面向C语言风格的API.尽管在Swift中调用这样的C语 ...

  5. Core Foundation框架

    转载自:http://blog.csdn.net/weiwangchao_/article/details/7744972 Core Foundation框架 (CoreFoundation.fram ...

  6. IOS之Core Foundation框架和Cocoa Foundation框架的区别

    Core Foundation框架 (CoreFoundation.framework) 是一组C语言接口,它们为iOS应用程序提供基本数据管理和服务功能.下面列举该框架支持进行管理的数据以及可提供的 ...

  7. Core Foundation框架介绍

    Core Foundation框架介绍 **参考网址: ARC下OC对象和CF对象之间的桥接 Core Foundation框架介绍 Core Foundation框架 Core Foundation ...

  8. Core Foundation 框架

    Core Foundation框架 (CoreFoundation.framework) 是一组C语言接口,它们为iOS应用程序提供基本数据管理和服务功能.下面列举该框架支持进行管理的数据以及可提供的 ...

  9. IOS之Core Foundation框架和Cocoa Foundation框架的区别(转)

    Core Foundation框架 (CoreFoundation.framework) 是一组C语言接口,它们为iOS应用程序提供基本数据管理和服务功能.下面列举该框架支持进行管理的数据以及可提供的 ...

随机推荐

  1. Number of 1 Bits——LeetCode

    Write a function that takes an unsigned integer and returns the number of ’1' bits it has (also know ...

  2. [Java Concurrent] 并发访问共享资源的简单案例

    EvenGenerator 是一个偶数生成器,每调用一个 next() 就会加 2 并返回叠加后结果.在本案例中,充当被共享的资源. EvenChecker 实现了 Runnable 接口,可以启动新 ...

  3. K - Rochambeau - poj2912(类似食物链)

    一群小孩玩一个简单石头布布游戏,这些小孩会分成三组(组内可能没有人)+一个自由人(比翻译成裁判合理多了),同一组的小孩只会出同一种手势(不会变的),不过裁判可以出任意的手势,这些小孩能就会相互猜拳玩, ...

  4. sublime 生成网页头文件

    1.普通HTML 输入html:xt然后按tab键即可生成如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional// ...

  5. Oracle执行计划——all_rows和first_rows(n) 优化器模式

    0. 环境创建 SQL> create usertest identified by test 2 default tablespace users 3 temporary tablespace ...

  6. spring配置文件中id与name

    1.id属性命名必须满足XML的命名规范,因为id其实是XML中就做了限定的. 2.name属性则没有这些限定,你可以使用几乎任何的名称 3.配置文件中不允许出现两个id相同的<bean> ...

  7. python_Opencv_滑动条用法

    前言: 创建一个简单的程序来说明滑动条用法:通过调节滑动条来设定画板颜色. 我们要创建一个窗口来显示显色,还有三个滑动条来设置B,G,R 的颜色. 当我们滑动滚动条是窗口的颜色也会发生相应改变. 默认 ...

  8. 如何给DropDownList控件设置样式(ASP.NET MVC)

    前话: 应学校领导要求,要给后台管理系统添加一个搜索功能,提供可选择选项.我选择使用DropDownList去实现,熟悉.net控件的都知道,DropDownList的样子非常丑,不论是边框长宽还是里 ...

  9. JS~js里实现队列与堆栈

    在面向对象的程序设计里,一般都提供了实现队列(queue)和堆栈(stack)的方法,而对于JS来说,我们可以实现数组的相关操作,来实现队列和堆栈的功能,看下面的相关介绍. 一 看一下它们的性质,这种 ...

  10. base64编码问题 需要对每个参数URL编码

    - (NSString *)encodeToPercentEscapeString: (NSString *) input { // Encode all the reserved character ...