使用swift语言进行IOS应用开发
2017-05-09 14:11 tlnshuju 阅读(212) 评论(0) 编辑 收藏 举报在Swift中可以直接使用Objective-C语言提供的api (包含系统框架与自己的定制代码),也可以在Objective-C中使用Swift提供的类和api ,还可以在一个project中同一时候混合使用Swift 和Objective-C两种语言,两种语言之间可以互通和互用。
随意Objective-C的框架或C库(包含全部的Objective-C系统框架,比如Foundation、UIKit、SpriteKit以及系统提供的公共c库)作为模块被直接导入Swift 供Swift语言使用。
比如为了使用Foundation框架,仅仅需简单的在要使用Foundation框架的Swift文件的顶部加入一个例如以下的输入声明语句:
import Foundation
这样Foundation 框架包括的全部api包括NSDate、NSURL、NSMutableData以及全部的方法、属性和类别都能被该Swift文件直接使用。
一 、与Objective-C 语言和框架的集成
1.1 对象的实例化
为了在 Swift 中使用某个Objective-C 类,能够使用Swift语法调用它的某个初始化方法进行实例化。
UITableView *myTableView = [[UITableViewalloc]initWithFrame:CGRectZerostyle:UITableViewStyleGrouped];
以上的一个Objective-C 对象的初始化方法在Swift语言中须要这样调用。
let myTableView:UITableView =UITableView(frame:CGRectZero,style: .Grouped)
因为Swift语言自己主动处理一个实例的内存分配,因此在Swift语言中不须要使用alloc进行内存分配。Objective-C 语言中作为实例初始化方法名字指示的init或 initWith前缀在Swift的初始化语法中也不须要,而用类的名字作为实例初始化方法的名字,跟着Objective-C 语言实例初始化方法名字initWith后面的单词作为Swift的初始化方法的第一个參数使用。
在Swift语言中。实例的初始化语法中对象的类型也能够省掉(如上例的UITableView),Swift能够自己主动正确地判断其类型。例如以下所看到的:
let myTableView=UITableView(frame:CGRectZero,style: .Grouped)
为了一致和简化。Objective-C 的工厂方法在导入Swift时被自己主动映射为Swift语言的便利初始化方法。比如在Objective-C中例如以下调用一个工厂方法。
UIColor *color = [UIColorcolorWithRed:0.5green:0.0blue:0.5alpha:1.0];
在Swift语言中。应该这样调用:
let color =UIColor(red:0.5,green:0.0,blue:0.5,alpha:1.0)
1.2 属性和方法的存取
在Swift中使用点语法来存取和设置Objective-C 对象的属性和调用方法。
对于属性的存取在Swift中利用点语法直接使用属性的名字来存取该属性,如:
myTextField.textColor = UIColor.darkGrayColor()
myTextField.text = "Hello world"
对于方法。Objective-C方法名字的第一部分在Swift中直接作为方法名,其余作为Swift方法的參数包含在方法的圆括号里。比如以下的一个Objective-C 方法。
[myTableViewinsertSubview:mySubviewatIndex:2];
在Swift中例如以下调用。
myTableView.insertSubview(mySubview,atIndex:2)
在Objective-C中的id类型 在导入Swift时被映射为Swift语言的AnyObject类型。
在Objective-C中的指针在导入Swift时被映射为Swift语言的optional类型。
1.3 扩展功能
可以使用扩展为Objective-C语言中已定义的类、结构和枚举(包含系统框架中或自定义的)加入和扩展功能。
如使用扩展来加入属性(包含类和静态属性),扩展的属性必须是计算属性。例如以下所看到的使用扩展为CGRect类加入了一个计算属性area:
extension CGRect {
var area:CGFloat {
return width *height
}
}
let rect =CGRect(x:0.0,y:0.0,width:10.0,height:50.0)
let area =rect.area
// area: CGFloat = 500.0
也能使用扩展来为Objective-C语言的类加入协议的支持,假设协议是Swift定义的。你能为随意的结构或枚举类型(不管是Objective-C定义的还是Swift定义的)加入对该协议的支持。
但不能使用扩展来重写Objective-C 类型的属性或方法。
1.4 块与闭合
Objective-C中的块以Swift中的闭合方式导入Swift。
void (^completionBlock)(NSData *, NSError *) = ^(NSData *data,NSError *error) {/* ... */}
上面 Objective-C语言定义的块在导入Swift后须要这样使用(转换为闭合):
let completionBlock: (NSData,NSError) ->Void = {data,errorin/* ... */}
因为 Swift中的闭合和 Objective-C中的块是兼容的。因此你可以传递闭合(包含Swift的函数)给不论什么使用块作为參数的Objective-C方法。
1.5 对 Objective-C类的继承和使用Objective-C中的协议
在Swift 语言中,能定义一个继承自一个Objective-C类的Swift 类,也能在Swift 中直接使用Objective-C语言定义的协议。例如以下定义了一个派生自Objective-C框架UIKit中UIViewController类的一个Swift 子类。
import UIKit
class MySwiftViewController:UIViewController {
// define the class
}
例如以下定义了一个採用Objective-C中的UITableViewDelegate和UITableViewDataSource协议的Swift 类MySwiftViewController。
class MySwiftViewController:UIViewController,UITableViewDelegate,UITableViewDataSource {
// define the class
}
对于 Swift 定义的类(包含从Objective-C继承的类)总是使用Swift语言的初始化方法进行类的初始化,Swift自己主动转换Objective-C 的初始化方法为Swift中的初始化方法。
1.6 与Objective-C的兼容
当定义一个Swift类派生自NSObject或其他的Objective-C类时,Swift类自己主动与Objective-C兼容,Objective-C代码能够直接使用它。
注意在Objective-C中不能定义一个继承Swift类的子类。
假设Swift类不派生自Objective-C类,则Objective-C代码不能直接使用它,假设要使该Swift类可以被Objective-C代码使用,须要使用@objc 来标识它。
当在Objective-C代码中使用一个Swift API 时,编译器自己主动运行一个直接转换操作。Swift 的API 被转换为Objective-C的形式。
如Swift 中的一个函数func playSong(name: String)被转换为Objective-C语言的例如以下形式- (void)playSong:(NSString *)name。
Swift 的一个初始化方法init (songName: String, artist: String)被转换为Objective-C语言的例如以下形式:
- (instancetype)initWithSongName:(NSString *)songName artist:(NSString *)artist。
在 Swift中,也能使用@objc对类、属性、方法规定一个可以被Objective-C语言识别和使用的另外的名字。例如以下所看到的:
@objc(Squirrel)
class Белка {
@objc(initWithName:)
init (имя:String) {/*...*/ }
@objc(hideNuts:inTree:)
func прячьОрехи(Int,вДереве:Дерево) {/*...*/ }
}
1.7、 与Cocoa数据类型的桥接
Swift可以自己主动在一些Objective-C 和Swift类型之间相互转换。另外也有一些类型,可以在Swift和Objective-C 之间相互替换使用。
可转换或可替换的类型被称作可桥接类型。如Swift 语言中的Array类型和Objective-C 中的NSArray类,Swift 中的String类型与Objective-C 中的NSString类,Swift 的Dictionary类型与Objective-C 中的NSDictionary类,都是可桥接类型。
在Swift中。使用NSString的不论什么地方都能用String取代,并能同一时候使用两种类型提供的功能,如能够在Swift的String类型上调用NSString提供的capitalizedString方法。
为了在Swift中同意和使用桥功能,仅仅需输入Foundation框架。例如以下所看到的:
import Foundation
let greeting ="hello, world!"
let capitalizedGreeting =greeting.capitalizedString
// capitalizedGreeting: String = Hello, World!
还可以像创建String一样创建一个NSString对象,例如以下所看到的创建了一个NSString类型的对象:
import Foundation
let myString:NSString ="123"
if let integerValue = (myStringasString).toInt() {
println("\(myString) is the integer \(integerValue)")
}
Swift也自己主动在Int、Float、UInt、Double、Bool类型与NSNumber类型之间实现类型的桥接,因此能够使用Int、Float、UInt、Double、Bool类型来创建一个NSNumber对象。在须要的NSNumber类型參数的地方也能够传送一个Int、Float、UInt、Double、Bool类型的參数。
let n =42
let m:NSNumber =n
注: Cocoa 的NSNumber类型与NSUInteger类型都被桥接为Swift的Int类型。
当从一个NSArray对象桥接为一个Swift Array数组时,NSArray数组的类型须要与AnyObject兼容。结果数组的类型为AnyObject[]。
因为全部的Objective-C对象与AnyObject类型兼容,因此不论什么类型的NSArray对象都能被桥接为Swift数组。
相同,假设Swift数组中的元素与AnyObject兼容。一个Swift数组也能桥接为NSArray对象,否则将会出执行时错误。
相同也能像创建一个Swift数组一样创建一个NSArray对象。
let schoolSupplies:NSArray = ["Pencil","Eraser","Notebook"]
// schoolSupplies is an NSArray object containing NSString objects
二、与 C API的交互
2.1、 C语言基本类型
Swift提供了与C语言基本类型对等的类型。但除非特别须要。不推荐使用。
C Type Swift Type
bool CBool
char, signed char CChar
unsigned char CUnsignedChar
short CShort
unsigned short CUnsignedShort
int CInt
unsigned int CUnsignedInt
long CLong
unsigned long CUnsignedLong
long long CLongLong
unsigned long long CUnsignedLongLong
wchar_t CWideChar
char16_t CChar16
char32_t CChar32
float CFloat
double CDouble
2.2 C-style类型的枚举
在Objective-C 语言中用NS_ENUM宏标记的C-style类型的枚举或用NS_OPTIONS标记的选项在导入Swift时被自己主动转换为Swift形式的枚举。
OBJECTIVE-C
typedef NS_ENUM(NSInteger,UITableViewCellStyle) {
UITableViewCellStyleDefault,
UITableViewCellStyleValue1,
UITableViewCellStyleValue2,
UITableViewCellStyleSubtitle
};
被转换为例如以下的Swift枚举形式。
SWIFT
enumUITableViewCellStyle:Int {
caseDefault
caseValue1
caseValue2
caseSubtitle
}
2.3 指针
Swift避免直接使用指针,但是当须要时也提供了几种类型的指针供直接存取内存使用。
对于作为參数的指针,有例如以下映射关系:
C Syntax Swift Syntax
const void * CConstVoidPointer
void * CMutableVoidPointer
const Type * CConstPointer<Type>
Type * CMutablePointer<Type>
对于作为返回类型、变量和參数类型的指针,有例如以下映射关系:
C Syntax Swift Syntax
void * COpaquePointer
Type * UnsafePointer<Type>
对于类的指针。有例如以下映射关系:
C Syntax Swift Syntax
Type * const * CConstPointer<Type>
Type * __strong * CMutablePointer<Type>
Type ** AutoreleasingUnsafePointer<Type>
以上的Type是一个占位类型。能够代表随意类型。
2.4 宏定义和条件编译
C语言使用#define定义的基本常量在导入Swift时被Swift编译器自己主动转换为Swift 语言的全局变量。但复杂的宏定义不能被Swift转换。
Swift代码也支持条件编译,例如以下所看到的:
#if build configuration && !build configuration
statements
#elseif build configuration
statements
#else
statements
#endif
三、 与Interface Builder集成
在Swift也是使用@IBOutlet@IBAction来定义Outlets属性和Actions动作,用来实现代码与用户接口对象的连接。例如以下所看到的,在MyViewController类中声明了与用户接口对象连接的一个outlet属性、一个outlet属性数组、一个action动作。
class MyViewController:UIViewController {
@IBOutlet var button:UIButton
@IBOutlet var textFields:UITextField[]
@IBAction func buttonTapped(AnyObject) {
println("button tapped!")
}
}
当使用@IBOutlet来声明一个outlet时。Swift自己主动把它转换为一个弱引用隐含型的已展开选项类型,并分配它的初始值为nil。
Swift中使用@IBDesignable属性来声明一个可以在Interface Builder中使用的特定视图对象,使用@IBInspectable属性声明一个可以在Interface Builder中的inspector中进行编辑的视图属性。例如以下所看到的声明了一个视图和相关的属性:
@IBDesignable
class MyCustomView:UIView {
@IBInspectable var textColor:UIColor
@IBInspectable var iconHeight:CGFloat
/* ... */
}
四、 混合使用Swift与Objective-C语言
在一个单独的project中,还可以同一时候包括Objective-C和Swif文件。
为了使一组Objective-C文件被同样应用project中的Swif文件使用,须要使用Xcode创建一个Objective-C桥接头文件,并在桥接头文件里导入每个被Swift用到的Objective-C头文件。
桥接头文件的名字为产品名字加“-Bridging-Header.h”后缀。
OBJECTIVE-C头文件
#import "XYZCustomCell.h"
#import "XYZCustomView.h"
#import “XYZCustomViewController.h"
Objective-C桥接头文件里加入的Objective-C头文件里定义的功能将可以自己主动被同样project的Swift文件使用。
Objective-C代码须要使用同样应用project中的Swift代码时,Xcode自己主动产生一个包括同样project中全部Swift文件接口声明的Objective-C 头文件。接口文头件为产品模块名字加“-Swift.h”后缀。
然后在要使用Swift代码的Objective-C文件里採用例如以下形式导入该头文件。
#import “ProductModuleName-Swift.h”
然后该Objective-C文件将可使用同样project中的全部Swift文件里公开的功能。
为了在一个Objective-C头文件里引用一个Swift类。须要使用@class在引用前面对该类进行声明。例如以下所看到的:
OBJECTIVE-C
// MyObjcClass.h
@class MySwiftClass;
@interface MyObjcClass :NSObject
- (MySwiftClass *)return SwiftObject;
/* ... */