当前位置: 首页 > 编程笔记 >

Swift使用Cocoa中的数据类型教程

华星剑
2023-03-14
本文向大家介绍Swift使用Cocoa中的数据类型教程,包括了Swift使用Cocoa中的数据类型教程的使用技巧和注意事项,需要的朋友参考一下

作为对 Objective-C 互用性(互操作性)的一部分,Swift提供快捷高效的方式来处理Cocoa数据类型。

Swift 会自动将一些 Objective-C 类型转换为 Swift 类型,以及将 Swift 类型转换为 Objective-C 类型。在 Objective-C 和 Swift 中也有一些具有互用性的数据类型。那些可转换的数据类型或者具有互用性的数据类型被称为bridged数据类型。举个例子,在 Swift 中,您可以将一个Array值传递给一个要求为NSArray对象的方法。你也可以转换一个 bridged 类型和它的副本。当你使用as转换 bridged 类型或者那些由常量和变量所提供的类型时,Swift 会桥接它们的数据类型。

Swift 也提供一种简单便捷的覆盖方法来连接 Foundation 的数据类型,在后面的 Swift 语言中,你能在它的句法中感受到自然和统一。

字符串

Swift会在String类型和NSString类型中自动转换。这意味着在可以使用NSString对象的地方,您可以使用一个属于 Swift 的String类型代替它,这样做会同时拥有它们数据类型的特点,String类型的插值,基于Swift设计的APIs以及NSString类更广的适用范围。因此,您几乎不必再在你的代码中使用NSString类。事实上,当 Swift 接入 Objective-C APIs 时,它将把所有NSString类型替换为String类型。当您在您的Objective-C代码中使用 Swift 类时,接入的API会将所有String类型替换成NSString类型。

为了允许字符串转换,只需接入Foundation。举个例子,您在 Swift 的一个字符串中调用了capitalizedString--一个NSString类的方法,此后 Swift 会自动将String转换为一个NSString对象并调用方法。这个方法甚至会返回一个 Swift 的String类型,因为它在接入的时候被替换了。


import Foundation

let greeting = "hello, world!"

let capitalizedGreeting = greeting.capitalizedString

// capitalizedGreeting: String = Hello, World!

如果您确实需要用到一个NSString对象,您可以用一个 Swift 的String值并转换它。String类型总是可以从一个NSString对象转换为一个Swift的String的值,因此,再没有必要去使用一个可选的类型转换器()as?)。您也可以再一个字符串中通过定义常量和变量来创建一个NSString对象。


import Foundation

let myString: NSString = "123"

if let integerValue = (myString as String).toInt()){

    println("\(myString) is the integer \(integerValue)")

}

本地化

在Objective-C中,常用NSLocalizedString类的宏来定位一个字符串。这集合的宏包括NSLocalizedStringFromTableInBundle和NSLocalizedStringWithDefaultValue。而在Swift中,只用一个函数就可以实现跟整个NSLocalizedString集一样的功能,即NSLocalizedString(key:tableName:bundle:value:comment:)。这个NSLocalizedString函数分别为tableName,bundle和value参数提供了一个默认值。你可以用它来替换宏。

数字

Swift会自动将已确定的数字类型Int和Float转换为NSNumber。这样的转换允许你基于其中一种类型创建一个NSNumber:


let n = 42

let m: NSNumber = n 

你也能传递一个Int类型的值,比如传递给一个要求为NSNumber类型的参数。同时需要注意的是,NSNumber可以包含多种不同的类型,因此您不能把它传递给单一的一个Int值。

下面所列出的类型都会自动转换为NSNumber:

Int

UInt

Float

Double

Bool

类集合

Swift 会自动将NSArray和NSDictionary类转换为Swift里等价的类。这意味着你将受益于Swift强大的算法和得天独厚的语法来处理集合--可互相转换的 Foundation 和 Swift 集合类型。

数组

Swift 会在Array类型和NSArray类型中自动转换。当你从一个 Swift 数组转换到一个NSArray对象,转换后的数组是一个AnyObject[]类型的数组。如果某个对象是 Objective-C 或者 Swift 类的实例,或者这个对象可以转换成另一种类型,那么这个对象则属于AnyObject类型的对象。你可以将任一NSArray对象转换成一个 Swift 数组,因为所有 Objective-C 的对象都是AnyObject类型的。正因如此,Swift 的编译器会在接入 Objective-C APIs 的时候将NSArray类替换成AnyObject[]。

当你将一个NSArray对象转换成一个 Swift 数组后,你也可以将数组强制类型转换成一个特定的类型。与从NSArray类转换到AnyObject[]不同的是,从AnyObject类型的对象转换成明确的类型并不会保证成功。由于直到运行时编译器才知道AnyObject的对象能否被强制转换为特定的类型,因此,从AnyObject[]转换为SomeType[]会返回一个optional的值。举个例子,如果你知道一个Swift数组只包含UIView类的实例(或者一个UIView类的子类),你可以将AnyObject类型的数组元素强制转换为UIView对象。如果Swift数组中得元素在运行时不是UIView类型的对象,那么转换则会返回nil。


let swiftyArray = foundationArray as AnyObject[]

if let downcastedSwiftArray = swiftArray as? UIView[] {

    // downcastedSwiftArray contains only UIView objects

}

你也可以在for循环中将NSArray对象定向地强制转换为特定类型的Swift数组:


for aView: UIView! in foundationArray {

     // aView is of type UIView

}

注意:这种转换是强制转换,如果转换不成功则会在运行时产生错误信息。

当你从 Swift 数组转换为NSArray对象时,Swift 数组里的元素必须是属于AnyObject的。例如,一个Int[]类型的 Swift 数组包含Int结构的元素。Int类型并不是一个类的实例,但由于Int类型转换成了NSNumber类,Int类型属于AnyObject类型的。因此,你可以将一个Int[]类型的Swift数组转换为NSArray对象。如果 Swift 数组里的一个元素不属于AnyObject类型,那么在运行时就会产生错误。

你也可以从 Swift 数组中创建一个NSArray对象。当你将一个常量或变量html" target="_blank">定义为一个NSArray对象并分配一个数组给它作为实例变量时,Swift 将会创建 NSArray对象,而不是 Swift 数组。


let schoolSupplies: NSArray = ["Pencil", "Eraser", "Notebkko"]

// schoolSupplies is an NSArray object containing NSString objects

上面的例子中,Swift 数组包含包含三个String字符串。由于从String类型转换为NSString类,数组字面量被转换成一个NSArray对象,并成功分配给schoolSupplies变量。

当您在 Objective-C 代码中使用 Swift 类或者协议时,接入的API会将全部所有类型的Swift数组代替为NSArray。若您将一个NSArray对象传递给Swift的API并要求数组元素为一个新的类型,运行时就会产生错误。如果 Swift API 返回一个不能被转换为NSArray类型的 Swift 数组,错误也会随之产生。

Foundation数据类型

Swift 也提供一种简单便捷的覆盖方法来连接定义在 Foundation 框架中的数据类型。在NSSize和NSPoint中使用覆盖方法,在剩下的 Swift 语言中,你能在它的句法中感受到自然和统一。比如,你可以使用如下语法创建一个NSSize类型的结构:


let size = NSSize(width: 20, height: 40)

覆盖方法也允许你以一种自然的方式调用 Foundation 的结构函数。


let rect = NSRect(x: 50, y: 50, width: 100, height: 100)

let width = rect.width // equivalent of NSWidth(rect)

let maxX = rect.maxY // equivalent of NSMaxY(rect) 

Swift可以将NSUInteger和NSInteger转换为Int类型。这些类型都会在 Foundation APIs 中变为Int类型。在 Swift 中Int常被尽可能地用以连贯性,同时当你要求一个无符号整数类型时,UInt类型总是可使用的。

Foundation函数

在 Swift 中,NSLog可在系统控制台输出信息。您可以像在 Objective-C 中使用过的语法格式那样使用此函数。


NSLog("%.7f", pi)  // Logs "3.1415927" to the console 

同时,Swift 也提供像print和println那样的输出函数。多归于 Swift 的字符插值机制才让这些函数简单,粗暴,多效。这些函数不会在系统控制台输出信息,但在需要调用的时候却是可用的。

Swift 中不再存在NSAssert函数,取而代之的是assert函数。

Core Foundation

Swift中的 Core Foundation 类型是一个成熟的类。当出现内存管理注释时,Swift 会自动地管理 Core Foundation 对象的内存,这其中包括你实例化了的 Core Foundation 对象。在 Swift 中,你可以自由变换 Fundation 和 Core Foundation 类型。如果你想先转换为桥接 Foundation 类型时,你也可以桥接一些 toll-free bridged Core Foundation 类型到 Swift 标准库类型。

重定义类型

当 Swift 导入 Core Foundation 类型时,编译器会重映射导入的类型名字。编译器会从每个类型名字的末端移除Ref,这是因为所有的 Swift 类都属于引用类型,因此后缀是多余的。

Core Foundation 中的CFTypeRef类型会对Anyobject类型重映射。所以你以前使用的CFTypeRef,现在该换成AnyObject了。

内存管理对象

在 Swift 中,从 annotated APIs 返回的 Core Foundation 对象能够自动进行内存管理--你不再需要调用自身的CFRetain,CFRelease,或者CFAutorelease函数。如果你从自身的C函数和 Objective-C 方法中返回一个 Core Foundation 对象,你需要用CF_RETURNS_RETAINED或者CF_RETURNS_NOT_RETAINED注释这个对象。当 Swift 代码中包含这些 APIs 时,编译器会在编译时自动调用内存管理。如果你只调用那些不会间接返回 Core Foundation 对象的 annotated APIs,那么现在你可以跳过本节的剩余部分了。否则,下面我们继续学习非托管的 Core Foundation 对象。

非托管对象

当 Swift 导入 unannotated 的APIs时,编译器将不会自动地对返回的 Core Foundation 对象进行内存管理托管。Swift 将这些返回的 Core Foundation 对象封闭在一个Unmanaged<T>结构中。那些间接返回 Core Foundation 的对象也是非托管的。举个例子,这里有一个 unannotated 的 C 函数:


CFStringRef StringByAddingTwoStrings(CFStringRef string1, CFStringRef string2) 

这里说明了Swift是怎么导入的:


func StringByAddingTwoStrings(CFString!, CFString!) -> Unmanaged<CFString>! 

假设您从 unannotated APIs 接收了非托管的对象,在使用它之前,你必须将它转换为能够内存管理的对象。在这方面,Swift 可以帮你进行内存管理而不用自己动手。同时,Unmanaged<T>结构也提供了两个方法来把一个非托管对象转换为一个可内存管理的对象--takeUnretainedValue()方法和takeRetainedValue()方法。这两个方法会返回原始的,非封闭的对象类型。您可以根据您实际调用的APIs返回的unretained或retained的对象,来选择哪一方法更合适。

比如,假设这里有一个 C 函数,这个函数在返回值前不会释放CFString对象。在使用这个对象前,您使用takeUnretainedValue()函数,以将它转换为一个能够内存管理托管的对象。


let memoryManagedResult = StringByAddingTwoStrings(str1, str2).takeUnretainedValue()

// memoryManagedResult is a memory managed CFString 

您也可以在一个非托管的对象中使用retain(),release()和autorelease()方法,但是这种做法并不值得推荐。

 类似资料:
  • 主要内容:1. 内置数据类型,2. 界限值,3. 类型别名,4. 类型安全,5.类型推断在使用任何编程语言进行编程时,都需要使用不同类型的变量来存储信息。 变量只是用于存储值的保留内存位置。 这意味着在创建变量时,会在内存中保留一些空间。 您可能希望存储各种数据类型的信息,如字符串,字符,宽字符,整数,浮点,布尔值等。根据变量的数据类型,操作系统分配内存并决定可以在保留内存中存储什么类型的内容。 1. 内置数据类型 Swift 4为程序员提供了丰富的内置和用户定义的数据类型。 在声明

  • 在我们使用任何程序语言编程时,需要使用各种数据类型来存储不同的信息。 变量的数据类型决定了如何将代表这些值的位存储到计算机的内存中。在声明变量时也可指定它的数据类型。 所有变量都具有数据类型,以决定能够存储哪种数据。 内置数据类型 Swift 提供了非常丰富的数据类型,以下列出了常用了几种数据类型: Int 一般来说,你不需要专门指定整数的长度。Swift 提供了一个特殊的整数类型Int,长度与当

  • 问题内容: 使用Swift 3而不是,我试图找出最有效/惯用的编码/解码方式,将各种数字类型(UInt8,Double,Float,Int64等)转换为Data对象。 有这个答案使用[UINT8] ,但它似乎是使用各种指针的API,我不能对数据找到。 我基本上想要一些类似于以下内容的自定义扩展: 我仔细阅读了许多文档,真正使我难以理解的部分是如何从任何基本结构(所有数字都是)中获得某种指针(Opa

  • 问题内容: 我真的很难弄清楚如何使用JNI从Objective-C调用Java函数。 我首先要说的是,我对Java并不了解很多,但是对Obj- C非常熟悉。我有一个带有单个方法的Java类,需要从我的应用程序包中调用它。该jar位于包中的Resources文件夹内,并且我将其设置为,它被检查并包含2个jar文件的名称(主要是一个,一个依赖)。 我正在通过调用来启动虚拟机,然后尝试使用该类来查找类,

  • 本文向大家介绍Swift教程之枚举类型详解,包括了Swift教程之枚举类型详解的使用技巧和注意事项,需要的朋友参考一下 枚举定义了一个常用的具有相关性的一组数据,并在你的代码中以一个安全的方式使用它们。 如果你熟悉C语言,你就会知道,C语言中的枚举指定相关名称为一组整数值。在Swift中枚举更为灵活,不必为枚举的每个成员提供一个值。如果一个值(被称为“原始”的值)被提供给每个枚举成员,则该值可以是

  • 本文向大家介绍使用Swift实现iOS App中解析XML格式数据的教程,包括了使用Swift实现iOS App中解析XML格式数据的教程的使用技巧和注意事项,需要的朋友参考一下 在IOS中,提供了一套解析XML数据的API。其实也很简单,就是NSXMLParser和NSXMLParserDelegate。 可以直接指定到XML的URL去实例化NSXMLParser 解析文件,返回的是一次解析的结