swift的基础语法相信大家都看过很多,这里有最全的资料: swift官网 ,这里讲的是swift2.2。网上有一句很有意思的话:
选择Create Brideing Header
这里我自己用keyNote画了一个图
当然,没有demo的例子完全在耍流氓,大家稍后看一下最后一页的demo附录,可以点击下载,这里贴一下代码
在OSMOView.m中:
@implementation OSMOView
-(void) print
{
NSLog(@"testXXX");
}
在ViewController.m中:
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
XXSwiftViewController *swiftVC = [[XXSwiftViewController alloc] init];
[swiftVC printOSMOView];
}
在XXSwiftViewController中:
class XXSwiftViewController: UIViewController {
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
required init?(coder: NSCoder) {
super.init(coder: coder)
printOSMOView();
}
func printOSMOView() -> Void {
let osmoView:OSMOView = OSMOView()
osmoView.print();
}
}
在oc中:
- (instancetype)init;
- (instancetype)initWithFrame:(CGRect)frame
style:(UITableViewStyle)style;
在swift中:
init() { /* ... */ }
init(frame: CGRect, style: UITableViewStyle) { /* ... */ }
统一都是 init(
开头,然后里面加参数,更加统一化
在oc中:
UITableView *myTableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
在swift中:
let myTableView: UITableView = UITableView(frame: CGRectZero, style: .Grouped)
去掉了 alloc
和 init
,在使用工厂方法的时候,swift统一做了更好的处理,将其直接映射到了swift的初始化方法:
在oc中:
UIColor *color = [UIColor colorWithRed:0.5 green:0.0 blue:0.5 alpha:1.0];
在swift中:
let color = UIColor(red: 0.5, green: 0.0, blue: 0.5, alpha: 1.0)
在oc中:
[UIColor darkGrayColor];
textfield.text = @"test";
在swift中:
UIColor.darkGrayColor()
myTextField.text = "Hello world"
当获取或设置属性的时候,只需要写属性的名字,不需要写括号。但要注意darkGrayColor包含了一个括号。这是因为darkGrayColor是UIColor的一个类方法,不是一个属性
在oc中:
[myTableView insertSubview:mySubview atIndex:2];
在swift中:
myTableView.insertSubview(mySubview, atIndex: 2)
myTableView.layoutIfNeeded() //不带参数
属性和方法都是一个宗旨,将 ()
进行到底
Swift 包含一个叫做 AnyObject 的协议类型,它代表任何类型的对象,就像 Objective-C 中的 id 一样。还能在不进行强制类型转换的情况下调用任何 Objective-C 的方法和访问任何的属性。这包含用 @objc 属性标记的 Objective-C 兼容方法,在swift中:
var myObject: AnyObject = UITableViewCell()
myObject = NSDate()
let futureDate = myObject.dateByAddingTimeInterval(10)
let timeSinceNow = myObject.timeIntervalSinceNow
myObject.characterAtIndex(5)
// crash, myObject doesn't respond to that method
因为只有在运行时 AnyObject 类型的对象里面的具体类型才会明确,这样就很容以写出不安全的代码。另外,和 Objective-C 比起来,如果你调用了 Anyobject 中不存在的方法或属性,就会产生运行时错误。例如,如下代码不会产生编译错误,但会在运行时出现未定义的方法错误。
可用用Optional开消除错误
let myCount = myObject.count
let myChar = myObject.characterAtIndex?(5)
print("/(myCount),/(myChar)") //结果 nil,nil
可以检测这个 optional 值来决定类型转换是否成功
let userDefaults = NSUserDefaults.standardUserDefaults()
let lastRefreshDate: AnyObject? = userDefaults.objectForKey("LastRefreshDate")
if let date = lastRefreshDate as? NSDate {
print("/(date.timeIntervalSinceReferenceDate)")
}
let date = lastRefreshDate as! NSDate
as! 转换类型不对的话就crash,记住类型不确定了时候为了避免crash最好用 as?
Swift 中的 Extension Objective-C 的 Category 类似。Extension 扩展了现存的 类,结构体,枚举 的行为,包括那些在 Objective-C 中定义的。你可以在系统框架或是你自定义的类型上定义 Extension。只需要简单的导入相应的模块,并且引用你在 Objective-C 中同样的类,结构体和枚举名称.
extension UIBezierPath {
convenience init(triangleSideLength: Float, origin: CGPoint) {
self.init()
let squareRoot = Float(sqrt(3.0))
let altitude = (squareRoot * triangleSideLength) / 2
moveToPoint(origin)
addLineToPoint(CGPoint(x: CGFloat(triangleSideLength), y: origin.x))
addLineToPoint(CGPoint(x: CGFloat(triangleSideLength) / 2, y: CGFloat(altitude)))
closePath()
}
}
protocol SomeProtocol {
var mustBeSettable: Int { get set }
}
extension CGRect:SomeProtocol {
var area: CGFloat {
return width * height
}
var mustBeSettable: Int { get{ return 10} set{} }
}
func testExtern() -> Void {
let testPath:UIBezierPath = UIBezierPath.init(triangleSideLength: 1.0, origin: CGPointMake(5, 10))
print("/(testPath)")
let rect = CGRect(x: 0.0, y: 0.0, width: 10.0, height: 50.0)
let area = rect.area
print("/(area)")
}
<UIBezierPath: 0x7f9e44857b90; <MoveTo {5, 10}>,
<LineTo {1, 5}>,
<LineTo {0.5, 0.86602538824081421}>,
<Close>
500.0
函数闭包:block,在oc中:
void (^completionBlock)(NSData *, NSError *) = ^(NSData *data, NSError *error) {/* ... */}
在swift中:
func testConclusure() -> Void {
let completionBlock: (String, NSError?) -> Void = {str, error in
print("/(str)")
}
completionBlock("5", nil)
}
比如现在在swift中我们是这么写的:
@objc(Color)
enum AppColor: Int {
@objc(Red)
case KRedColor
@objc(Black)
case KBlackColor
}
@objc(GameSwfitItem)
class Apple:NSObject{
@objc(color)
var appColor: AppColor = .KRedColor
@objc(swiftName)
var name: String
@objc(initSwift:)
init(name:String){
self.name = name
}
}
在`项目工程名-swift.h`中,我们看到的是这样:
SWIFT_CLASS_NAMED("Apple")
@interface GameSwfitItem : NSObject
@property (nonatomic, copy) NSString * _Nonnull swiftName;
- (nonnull instancetype)initSwift:(NSString * _Nonnull)name OBJC_DESIGNATED_INITIALIZER;
@end
在 oc
中:
@property NSArray<NSDate *>* dates;
@property NSSet<NSString *>* words;
@property NSDictionary<KeyType: NSURL *, NSData *>* cachedData;
在 swift
中:
var dates: [NSDate]
var words: Set<String>
var cachedData: [NSURL: NSData]
import UIKit
class MyViewController: UIViewController {
let myButton = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 50))
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
let action = #selector(MyViewController.tappedButton(_:))
myButton.addTarget(self, action: action, forControlEvents: .TouchUpInside)
}
func tappedButton(sender: UIButton!) {
print("tapped button")
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
}
let string: NSString = "Hello, Cocoa!"
let selector = #selector(NSString.lowercaseStringWithLocale(_:))
let locale = NSLocale.currentLocale()
if let result = string.performSelector(selector, withObject: locale) {
print(result.takeUnretainedValue())
}
// Prints "hello, cocoa!"
如果此时没有respondsToSelector,会导致崩溃
let array: NSArray = ["delta", "alpha", "zulu"]
// Not a compile-time error because NSDictionary has this selector.
let selector = #selector(NSDictionary.allKeysForObject(_:))
if array.respondsToSelector(selector){
array.performSelector(selector)
}
class XXTableViewController: UIViewController,UITableViewDelegate,UITableViewDataSource{
lazy var tableView: UITableView! = {
var tableView = UITableView(frame: CGRectZero, style: UITableViewStyle.Grouped)
tableView.delegate = self
tableView.dataSource = self
tableView.registerClass(UITableViewCell.classForCoder(), forCellReuseIdentifier: "Cell")
return tableView
}()
//MARK: UITableViewDelegate
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
return cell
}
}
lazy:
在oc中的
@property (nonatomic, copy) NSString *testString;
// ClassA.m
- (NSString *)testString {
if (!_testString) {
_testString = @"Hello";
NSLog(@"只在首次访问输出");
}
return _testString;
}
在 swift
中:
class ClassA {
lazy var str: String = {
let str = "Hello"
print("只在首次访问输出")
return str
}()
}
更深层次理解:
let data = 1...3
let result = data.lazy.map {
(i: Int) -> Int in
print("正在处理 /(i)")
return i * 2
}
print("准备访问结果")
for i in result {
print("操作后结果为 /(i)")
}
print("操作完毕")
此时的运行结果:
// 准备访问结果
// 正在处理 1
// 操作后结果为 2
// 正在处理 2
// 操作后结果为 4
// 正在处理 3
// 操作后结果为 6
// 操作完毕
对象比较:
在纯swift中用 == 判等
class TodoItem {
let uuid: String
var title: String
init(uuid: String, title: String) {
self.uuid = uuid
self.title = title
}
}
extension TodoItem: Equatable {
}
func ==(lhs: TodoItem, rhs: TodoItem) -> Bool {
return lhs.uuid == rhs.uuid
}
//参考::http://swifter.tips/equal/
如果和oc对象做比较,还是需要重写isEqual方法
class TodoItemOC :NSObject{
let uuid: String
var title: String
init(uuid: String, title: String) {
self.uuid = uuid
self.title = title
}
override func isEqual(object: AnyObject?) -> Bool {
return true;
}
}
当你定义的 Swift 类继承自 NSObject 或者其他 Objective-C 类的时候,这个类就自动与 Objective-C 兼容。所有相关这一切的步骤都已经由 Swift 编译器帮你完成。
在 Persion.swift
中:
class Person: NSObject {
var name : String
var age : Int
// 重写了NSObject(父类)的构造方法
override init() {
name = "testname"
age = 0
}
func printName() -> Void {
print("/(name)")
}
}
在 oc
中:
//
// Squirrel.m
// XXSwiftUseOC
//
// Created by tomxiang on 7/30/16.
// Copyright © 2016 tomxiang. All rights reserved.
//
#import "Squirrel.h"
#import "XXSwiftUseOC-Swift.h"
@implementation Squirrel
-(void) print{
Person *person = [[Person alloc] init];
[person printName];
}
@end
苹果官网有一句话:
You cannot import C++ code directly into Swift. Instead, create an Objective-C or C wrapper for C++ code.
swift无法直接用c++,需要用oc或者c进行包装
//
// CFile.c
// XXSwiftUseOC
//
// Created by tomxiang on 8/4/16.
// Copyright © 2016 tomxiang. All rights reserved.
//
#include <stdio.h>
void testc()
{
printf("CFile/n");
}
.h中:
#ifndef junk_h
#define junk_h
class A
{
public:
A(int);
int getInt();
private:
int m_Int;
};
#endif /* junk_h */
.cpp中:
#include "junk.h"
A::A(int _i) : m_Int(_i) {}
int A::getInt() { return m_Int; }
extern "C" int getIntFromCPP()
{
// Create an instance of A, defined in
// the library, and call getInt() on it:
return A(1234).getInt();
}
-bridging-Header中:
#import "Squirrel.h"
void testc();
int getIntFromCPP();
一切完成后,即可顺利调用
如果是swift工程,可以这样
let format = NSLocalizedString("Hello, %@!", comment: "Hello, {given name}!")
let name = "Mei"
let greeting = String(format: format, arguments: [name])
print(greeting)
如果是非swift工程,需要用 oc
宏的转换
+(NSString*) GET_LOCALIZED_TEXT:(NSString*)inputKey COMMENT:(NSString*)comment;
+(NSString*) GET_LOCALIZED_TEXT:(NSString*)inputKey COMMENT:(NSString*)comment {
return NSLocalizedString(inputKey, comment);
}
swift中没有宏,那么在纯 swift
中:
class Constants {
static let BEZEL_COLOR = UIColor.init(red: 0, green: 0, blue: 0, alpha:0.8)
static let TEXT_COLOR = UIColor.init(red: 1, green: 1, blue: 1, alpha: 1)
static let MARGIN: CGFloat = 15.0
}
hud.bezelView.color = Constants.BEZEL_COLOR
在混用工程中:
#define ContinuousViewWidth 190
#define ContinuousViewHeight 60
@interface OSMODefineSwitch : NSObject
+(CGFloat) OSMO_ICON_WIDTH_SWIFT;
http://swifter.tips/toll-free/ ,已经写的非常完整了.
大概的意思就是除掉了CFRelease,CFRetain等,CFFundation对象已经变成ARC了.
有一点例外,那就是对于非系统的 CF API (比如你自己写的或者是第三方的),因为并没有强制机制要求它们一定遵照 Cocoa 的命名规范,所以贸然进行自动内存管理是不可行的。如果你没有明确地使用上面的标注来指明内存管理的方式的话,将这些返回 CF 对象的 API 导入 Swift 时,它们的类型会被对对应为 Unmanaged
// CFGetSomething() -> Unmanaged<Something>
// CFCreateSomething() -> Unmanaged<Something>
// 两者都没有进行标注,Create 中进行了创建
let unmanaged = CFGetSomething()
let something = unmanaged.takeUnretainedValue()
// something 的类型是 Something,直接使用就可以了
let unmanaged = CFCreateSomething()
let something = unmanaged.takeRetainedValue()
// 使用 something
// 因为在取值时 retain 了,使用完成后进行 release
unmanaged.release()
切记,这些只有在没有标注的极少数情况下才会用到,如果你只是调用系统的 CF API,而不会去写自己的 CF API 的话,是没有必要关心这些的
为了允许字符串转换,只需导入Foundation框架
class XXCocoaSwift: NSObject {
let myString: NSString = "123"
override init() {
super.init()
self.testNSString()
}
func testNSString() -> Void {
if let integerValue = Int(myString as String) {
print("/(myString) is the integer /(integerValue)")
}
}
}
//print 123 is the integer 123
Swift会自动将已确定的数值类型转换为NSNumber
Int
UInt
Float
Double
Bool
Swift 会自动将NSArray、NSSet和NSDictionary类转换为Swift里等价的类:Array、Set和Dictionary
@property NSArray<NSDate *>* dates;
- (NSArray<NSDate *> *)datesBeforeDate:(NSDate *)date;
- (void)addDatesParsedFromTimestamps:(NSArray<NSString *> *)timestamps;
在swift中:
var dates: [NSDate]
func datesBeforeDate(date: NSDate) -> [NSDate]
func addDatesParsedFromTimestamps(timestamps: [String])
@property NSSet<NSString *>* words;
- (NSSet<NSString *> *)wordsMatchingPredicate:(NSPredicate *)predicate;
- (void)removeWords:(NSSet<NSString *> *)words;
那么,转换为Swift,则是这个样子的:
var words: Set<String>
func wordsMatchingPredicate(predicate: NSPredicate) -> Set<String>
func removeWords(words: Set<String>)
@property NSDictionary<NSURL *, NSData *>* cachedData;
- (NSDictionary<NSURL *, NSNumber *> *)fileSizesForURLsWithSuffix:(NSString *)suffix;
- (void)setCacheExpirations:(NSDictionary<NSURL *, NSDate *> *)expirations;
那么,转换成swift是:
var cachedData: [NSURL: NSData]
func fileSizesForURLsWithSuffix(suffix: String) -> [NSURL: NSNumber]
func setCacheExpirations(expirations: [NSURL: NSDate])
@objc public enum CustomError: Int, ErrorType {
case A, B, C
}
如果不按照上面这么些,oc将无法应用swift的枚举
typedef SWIFT_ENUM(NSInteger, CustomError) {
CustomErrorA = 0,
CustomErrorB = 1,
CustomErrorC = 2,
};
static NSString * _Nonnull const CustomErrorDomain = @"XXSwiftUseOC.CustomError";
1.建议参考目录的2,官方文档。这里介绍的一点的 XCPlaygroundPage.currentPage.liveView
设置
//: Playground - noun: a place where people can play
import UIKit
import XCPlayground
var str = "Hello world 你好"
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
//1.图片
let image:UIImage = UIImage(named: "1.png")!
//2.uibutton
let button = UIButton(frame: CGRectMake(0,0,100,100))
button.backgroundColor = UIColor.redColor()
button.layer.cornerRadius = 10
button.layer.borderWidth = 2
//3.函数 点击editor的show display mode可以改变其查看方式
var j = 2
for i in 0 ..< 5{
j += i*j
}
//4.add color
let imageView = UIImageView(image:UIImage(named:"1.png"))
//5.view
//第二种显示方法
XCPlaygroundPage.currentPage.liveView = imageView
let customView = UIView(frame: CGRect(x: 0, y: 0, width: 400, height: 400))
customView.backgroundColor = UIColor.whiteColor()
//XCPlaygroundPage.currentPage.liveView = customView
//5.动画