从OC到Swift的过渡之路

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
查看查看265 回复回复4 收藏收藏 分享淘帖 转播转播 分享分享 微信
查看: 265|回复: 4
收起左侧

从OC到Swift的过渡之路

[复制链接]
firefighter 发表于 2016-8-9 15:49:35 | 显示全部楼层 |阅读模式
快来登录
获取优质的苹果资讯内容
收藏热门的iOS等技术干货
拷贝下载Swift Demo源代码
订阅梳理好了的知识点专辑
Swift的基础语法相信大家都看过很多,这里有最全的资料:Swift官网,这里讲的是Swift2.2;而Swifthumb.com上则汇聚了最全的Swift一手资料,比如我这篇

网上有一句很有意思的话:

C,C++,Objective C,Swift 就像《葫芦娃》里面七个兄弟中的四个一样牛掰,七葫芦娃是最厉害的,但需要七个兄弟齐心协力才能收妖。




1、建立工程

从OC到Swift的过渡之路 1

从OC到Swift的过渡之路 - 敏捷大拇指 - 从OC到Swift的过渡之路 1


选择Create Brideing Header:

从OC到Swift的过渡之路 2

从OC到Swift的过渡之路 - 敏捷大拇指 - 从OC到Swift的过渡之路 2


这里我自己用keyNote画了一个图:

从OC到Swift的过渡之路 3

从OC到Swift的过渡之路 - 敏捷大拇指 - 从OC到Swift的过渡之路 3


当然,没有demo的例子完全在耍流氓,大家稍后看一下最后一页的demo附录,可以回复点击下载,这里贴一下代码。


在OSMOView.m中:

[Swift] 纯文本查看 复制代码
@implementation OSMOView

-(void) print
{
    NSLog(@"testXXX");
}



在ViewController.m中:

[Swift] 纯文本查看 复制代码
@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    XXSwiftViewController *swiftVC = [[XXSwiftViewController alloc] init];
    [swiftVC printOSMOView];
}



在XXSwiftViewController中:

[Swift] 纯文本查看 复制代码
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();
    }
    
}





2、与Objective-C的API交互



2.1、初始化

在OC中:

[Objective-C] 纯文本查看 复制代码
- (instancetype)init;
- (instancetype)initWithFrame:(CGRect)frame
                        style:(UITableViewStyle)style;


在Swift中:

[Swift] 纯文本查看 复制代码
init() { /* ... */ }
init(frame: CGRect, style: UITableViewStyle) { /* ... */ }


统一都是 init( 开头,然后里面加参数,更加统一化。



2.2、实例化对象

在OC中:

[Objective-C] 纯文本查看 复制代码
UITableView *myTableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];


在Swift中:

[Swift] 纯文本查看 复制代码
let myTableView: UITableView = UITableView(frame: CGRectZero, style: .Grouped)


去掉了alloc和init,在使用工厂方法的时候,Swift统一做了更好的处理,将其直接映射到了Swift的初始化方法:

在OC中:

[Objective-C] 纯文本查看 复制代码
UIColor *color = [UIColor colorWithRed:0.5 green:0.0 blue:0.5 alpha:1.0];


在Swift中:

[Swift] 纯文本查看 复制代码
let color = UIColor(red: 0.5, green: 0.0, blue: 0.5, alpha: 1.0)




2.3、访问属性

在OC中:

[Objective-C] 纯文本查看 复制代码
[UIColor darkGrayColor];
textfield.text = @"test";


在Swift中:

[Swift] 纯文本查看 复制代码
UIColor.darkGrayColor()
myTextField.text = "Hello world"


当获取或设置属性的时候,只需要写属性的名字,不需要写括号。但要注意darkGrayColor包含了一个括号。这是因为darkGrayColor是UIColor的一个类方法,不是一个属性。



2.4、使用方法

在OC中:

[Objective-C] 纯文本查看 复制代码
[myTableView insertSubview:mySubview atIndex:2];


在Swift中:

[Swift] 纯文本查看 复制代码
myTableView.insertSubview(mySubview, atIndex: 2)
myTableView.layoutIfNeeded() //不带参数


属性和方法都是一个宗旨,将 () 进行到底。



2.5、id兼容性


2.5.1、基本用法

Swift 包含一个叫做 AnyObject 的协议类型,它代表任何类型的对象,就像 Objective-C 中的 id 一样。还能在不进行强制类型转换的情况下调用任何 Objective-C 的方法和访问任何的属性。这包含用 @objc 属性标记的 Objective-C 兼容方法,在Swift中:

[Swift] 纯文本查看 复制代码
var myObject: AnyObject = UITableViewCell()
myObject = NSDate()

let futureDate = myObject.dateByAddingTimeInterval(10)
let timeSinceNow = myObject.timeIntervalSinceNow


注意:crash!

[Swift] 纯文本查看 复制代码
myObject.characterAtIndex(5)
// crash, myObject doesn't respond to that method


因为只有在运行时 AnyObject 类型的对象里面的具体类型才会明确,这样就很容以写出不安全的代码。另外,和 Objective-C 比起来,如果你调用了 Anyobject 中不存在的方法或属性,就会产生运行时错误。例如,如下代码不会产生编译错误,但会在运行时出现未定义的方法错误。

可以用Optional开消除错误:

[Swift] 纯文本查看 复制代码
let myCount = myObject.count
let myChar = myObject.characterAtIndex?(5)
print("\(myCount),\(myChar)") //结果 nil,nil



2.5.2、向下转型

可以检测这个 optional 值来决定类型转换是否成功。

[Swift] 纯文本查看 复制代码
let userDefaults = NSUserDefaults.standardUserDefaults()
let lastRefreshDate: AnyObject? = userDefaults.objectForKey("LastRefreshDate")
if let date = lastRefreshDate as? NSDate {
    print("\(date.timeIntervalSinceReferenceDate)")
}


注意:crash

[Swift] 纯文本查看 复制代码
let date = lastRefreshDate as! NSDate


as! 转换类型不对的话就crash,记住类型不确定了时候为了避免crash最好用 as? 。



2.6、Extension扩展

Swift 中的 Extension Objective-C 的 Category 类似。Extension 扩展了现存的类、结构体、枚举的行为,包括那些在 Objective-C 中定义的。你可以在系统框架或是你自定义的类型上定义 Extension。只需要简单的导入相应的模块,并且引用你在 Objective-C 中同样的类,结构体和枚举名称。

[Swift] 纯文本查看 复制代码
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)")
}


[XML] 纯文本查看 复制代码
<UIBezierPath: 0x7f9e44857b90; <MoveTo {5, 10}>,
 <LineTo {1, 5}>,
 <LineTo {0.5, 0.86602538824081421}>,
 <Close>
500.0




2.7、Closure

函数闭包:block,在OC中:

[Objective-C] 纯文本查看 复制代码
void (^completionBlock)(NSData *, NSError *) = ^(NSData *data, NSError *error) {/* ... */}


在Swift中:

[Swift] 纯文本查看 复制代码
func testConclusure() -> Void {
    let completionBlock: (String, NSError?) -> Void = {str, error in
        print("\(str)")
    }
    completionBlock("5", nil)
}




2.8、@objc更改暴露給oc的方法等

比如现在在Swift中我们是这么写的:

[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”中,我们看到的是这样:

[Objective-C] 纯文本查看 复制代码
SWIFT_CLASS_NAMED("Apple")
@interface GameSwfitItem : NSObject
@property (nonatomic, copy) NSString * _Nonnull swiftName;
- (nonnull instancetype)initSwift:(NSString * _Nonnull)name OBJC_DESIGNATED_INITIALIZER;
@end




2.9、轻量级范型

在OC中:

[Objective-C] 纯文本查看 复制代码
@property NSArray<NSDate *>* dates;
@property NSSet<NSString *>* words;
@property NSDictionary<KeyType: NSURL *, NSData *>* cachedData;


在Swift中:

[Swift] 纯文本查看 复制代码
var dates: [NSDate]
var words: Set<String>
var cachedData: [NSURL: NSData]




2.10、#selector


2.10.1、給对象增加“Target”

[Swift] 纯文本查看 复制代码
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)
    }
}



2.10.2、performSelector / respondsToSelector

[Swift] 纯文本查看 复制代码
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,会导致崩溃。

[Swift] 纯文本查看 复制代码
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)
}





3、使用Objective-C特性编写Swift类



3.1、协议,Class

[Swift] 纯文本查看 复制代码
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中的:

[Objective-C] 纯文本查看 复制代码
@property (nonatomic, copy) NSString *testString;

// ClassA.m
- (NSString *)testString {
     if (!_testString) {
         _testString = @"Hello";
        NSLog(@"只在首次访问输出");
     }
     return _testString;
}


在Swift中:

[Swift] 纯文本查看 复制代码
class ClassA {
    lazy var str: String = {
        let str = "Hello"
        print("只在首次访问输出")
        return str
    }()
}


更深层次理解:

[Swift] 纯文本查看 复制代码
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
// 操作完毕





4、看OC/Swift的混用需要注意的点



4.1、对象比较

对象比较:

在纯Swift中用 == 判等:

[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
}
//参考:: [url=http://swifter.tips/equal/]http://swifter.tips/equal/[/url]


如果和OC对象做比较,还是需要重写isEqual方法:

[Swift] 纯文本查看 复制代码
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;
    }
}




4.2、类型兼容


4.2.1、是否继承NSObject或者OC的类

当你定义的 Swift 类继承自 NSObject 或者其他 Objective-C 类的时候,这个类就自动与 Objective-C 兼容。所有相关这一切的步骤都已经由 Swift 编译器帮你完成。

在Person.swift中:

[Swift] 纯文本查看 复制代码
class Person: NSObject {
    var name : String
    var age : Int
    
    // 重写了NSObject(父类)的构造方法
    override init() {
        name = "testname"
        age = 0
    }
    
    func printName() -> Void {
        print("\(name)")
    }
}


在OC中:

[Objective-C] 纯文本查看 复制代码
//
//  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




4.3、Swift/C++

苹果官网有一句话:

You cannot import C++ code directly into Swift. Instead, create an Objective-C or C wrapper for C++ code.

Swift无法直接用C++,需要用OC或者C进行包装。


4.3.1、Swift调用C

[Swift] 纯文本查看 复制代码
//
//  CFile.c
//  XXSwiftUseOC
//
//  Created by tomxiang on 8/4/16.
//  Copyright © 2016 tomxiang. All rights reserved.
//

#include <stdio.h>
void testc()
{
    printf("CFile\n");
}



4.3.2、Swift调用C++

.h中:

[Swift] 纯文本查看 复制代码
#ifndef junk_h
#define junk_h

class A
{
public:
    A(int);
    int getInt();
private:
    int m_Int;
};

#endif /* junk_h */


.cpp中:

[C++] 纯文本查看 复制代码
#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中:

[Swift] 纯文本查看 复制代码
#import "Squirrel.h"

void testc();

int getIntFromCPP();


一切完成后,即可顺利调用。



4.4、本地化

如果是Swift工程,可以这样:

[Swift] 纯文本查看 复制代码
let format = NSLocalizedString("Hello, %@!", comment: "Hello, {given name}!")
let name = "Mei"
let greeting = String(format: format, arguments: [name])
print(greeting)


如果是非Swift工程,需要用OC宏的转换:

[Objective-C] 纯文本查看 复制代码
+(NSString*) GET_LOCALIZED_TEXT:(NSString*)inputKey COMMENT:(NSString*)comment;

+(NSString*) GET_LOCALIZED_TEXT:(NSString*)inputKey COMMENT:(NSString*)comment {
    return NSLocalizedString(inputKey, comment);
}




4.5、宏

Swift中没有宏,那么在纯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


在混用工程中:

[Swift] 纯文本查看 复制代码
#define ContinuousViewWidth  190
#define ContinuousViewHeight 60

@interface OSMODefineSwitch : NSObject
+(CGFloat) OSMO_ICON_WIDTH_SWIFT;




4.6、CoreFoundation

这篇文章中已经写的非常完整了。

大概的意思就是除掉了CFRelease、CFRetain等,CFFundation对象已经变成ARC了。

有一点例外,那就是对于非系统的 CF API (比如你自己写的或者是第三方的),因为并没有强制机制要求它们一定遵照 Cocoa 的命名规范,所以贸然进行自动内存管理是不可行的。如果你没有明确地使用上面的标注来指明内存管理的方式的话,将这些返回 CF 对象的 API 导入 Swift 时,它们的类型会被对对应为 Unmanaged。

[Swift] 纯文本查看 复制代码
// 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 的话,是没有必要关心这些的。




5、数据类型



5.1、字符串

为了允许字符串转换,只需导入Foundation框架:

[Swift] 纯文本查看 复制代码
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




5.2、数值

Swift会自动将已确定的数值类型转换为NSNumber:

  • Int
  • UInt
  • Float
  • Double
  • Bool




5.3、集合类

Swift 会自动将NSArray、NSSet和NSDictionary类转换为Swift里等价的类:Array、Set和Dictionary。


5.3.1、Array

[Objective-C] 纯文本查看 复制代码
@property NSArray<NSDate *>* dates;
- (NSArray<NSDate *> *)datesBeforeDate:(NSDate *)date;
- (void)addDatesParsedFromTimestamps:(NSArray<NSString *> *)timestamps;


在Swift中:

[Swift] 纯文本查看 复制代码
var dates: [NSDate]
func datesBeforeDate(date: NSDate) -> [NSDate]
func addDatesParsedFromTimestamps(timestamps: [String])



5.3.2、Set

[Objective-C] 纯文本查看 复制代码
@property NSSet<NSString *>* words;
- (NSSet<NSString *> *)wordsMatchingPredicate:(NSPredicate *)predicate;
- (void)removeWords:(NSSet<NSString *> *)words;


那么,转换为Swift,则是这个样子的:

[Swift] 纯文本查看 复制代码
var words: Set<String>
func wordsMatchingPredicate(predicate: NSPredicate) -> Set<String>
func removeWords(words: Set<String>)



5.3.3、NSDictionary

[Objective-C] 纯文本查看 复制代码
@property NSDictionary<NSURL *, NSData *>* cachedData;
- (NSDictionary<NSURL *, NSNumber *> *)fileSizesForURLsWithSuffix:(NSString *)suffix;
- (void)setCacheExpirations:(NSDictionary<NSURL *, NSDate *> *)expirations;


那么,转换成Swift是:

[Swift] 纯文本查看 复制代码
var cachedData: [NSURL: NSData]
func fileSizesForURLsWithSuffix(suffix: String) -> [NSURL: NSNumber]
func setCacheExpirations(expirations: [NSURL: NSDate])




5.4、枚举

[Swift] 纯文本查看 复制代码
@objc public enum CustomError: Int, ErrorType {
    case A, B, C
}


如果不按照上面这么写,OC将无法应用Swift的枚举。

[Swift] 纯文本查看 复制代码
typedef SWIFT_ENUM(NSInteger, CustomError) {
  CustomErrorA = 0,
  CustomErrorB = 1,
  CustomErrorC = 2,
};
static NSString * _Nonnull const CustomErrorDomain = @"XXSwiftUseOC.CustomError";





6、playground实时显示

建议参考目录的2,官方文档。这里介绍的一点的XCPlaygroundPage.currentPage.liveView设置:

[Swift] 纯文本查看 复制代码
//: 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

//6.动画


从OC到Swift的过渡之路 5

从OC到Swift的过渡之路 - 敏捷大拇指 - 从OC到Swift的过渡之路 5





7、参考目录






8、Demo下载

回复可见:

游客,如果您要查看本帖隐藏内容请回复


更多图片 小图 大图
组图打开中,请稍候......

都看到这里了,就把这篇资料推荐给您的好朋友吧,让他们也感受一下。

回帖是一种美德,也是对楼主发帖的尊重和支持。

*声明:敏捷大拇指是全球最大的Swift开发者社区、苹果粉丝家园、智能移动门户,所载内容仅限于传递更多最新信息,并不意味赞同其观点或证实其描述;内容仅供参考,并非绝对正确的建议。本站不对上述信息的真实性、合法性、完整性做出保证;转载请注明来源并加上本站链接,敏捷大拇指将保留所有法律权益。如有疑问或建议,邮件至marketing@swifthumb.com

*联系:微信公众平台:“swifthumb” / 腾讯微博:@swifthumb / 新浪微博:@swifthumb / 官方QQ一群:343549891(满) / 官方QQ二群:245285613 ,需要报上用户名才会被同意进群,请先注册敏捷大拇指

嗯,不错!期待更多好内容,支持一把:
支持敏捷大拇指,用支付宝支付10.24元 支持敏捷大拇指,用微信支付10.24元

评分

参与人数 1金钱 +10 贡献 +10 专家分 +10 收起 理由
Anewczs + 10 + 10 + 10 32个赞!专家给力!

查看全部评分

Caesar 发表于 2016-8-9 17:25:04 | 显示全部楼层
回复看看。
swifter 发表于 2016-8-10 15:21:19 | 显示全部楼层
不错,回复看看
young 发表于 2016-8-10 15:35:49 | 显示全部楼层
这让OC保守者跃跃欲试了
代码买卖 发表于 2016-9-18 07:01:08 | 显示全部楼层
我现在都直接用Swift写App了
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

做任务,领红包。
我要发帖

分享扩散

都看到这里了,就把这资料推荐给您的好朋友吧,让他们也感受一下。
您的每一位朋友访问此永久链接后,您都将获得相应的金钱积分奖励
热门推荐

合作伙伴

Swift小苹果

  • 北京治世天下科技有限公司
  • ©2014-2016 敏捷大拇指
  • 京ICP备14029482号
  • Powered by Discuz! X3.1 Licensed
  • swifthumb Wechat Code
  •   
快速回复 返回顶部 返回列表