代码环境是Xcode6.3-Beta3.

Swift已经极大的改变了开发iOS应用的方式。本文中,我会列出Swift的几个重点,并且和Objective-C一一做出对比。

注意,本文不是Swift的入门指导。苹果发布了Swift Programming Language,强烈建议您读一读这本书。文本主要介绍Swift中比较酷炫的特性。

类型

Swift提供的第一个重大的改进是类型推断。使用了类型推断的编程语言,开发者不需要在声明中明确指定变量的类型。编译器会自动探知要赋给变量的值的类型。比如下面的例子,编译器会自动设定变量的类型为String:

// 类型推断
var str = "Hello World!"

 明确定义类型,这里可以不这样
var swift: String = "Hello Swift"

和类型推断一起带来的是类型安全。在Swift中,编译器(一般来说全部,但是在很少的情况下)知道一个类型的全部类型。这样给编译器一个选择如何编译代码的机会,因为编译器有足够的信息。

这承托出了Objective-C的一个非常动态的本质。在Objective-C中,任何类型在编译期间都是未知的。这也是为什么你可以在运行时给已经存在的类添加方法,添加一个全新的类型,甚至于改变一个对象的类型。

看看Objective-C的代码:

Person *man = [[Person alloc] init];
[man sayHello];

当编译器看到对方法sayHello的调用的时候,它就会检查类型Person类的头文件中是否有一个叫做sayHello的方法。如果没有就报错。编译器就只可以做这些。这确实可以你可能引入的最初简单的bug:如拼写错误。但是,因为动态性,编译器不可能知道sayHello方法是否会在运行改变、甚至是否存在。这可能是一个协议中得optional方法。比如(还记得那些使用respondsToSelector的检查吗)。

由于缺乏强类型, 在Objective-C中调用方法的时候编译器几乎不能做什么优化。处理代码动态分发的方法是:objc_msgSend。我确定你在很多的时候见过这个方法。在这个方法中,寻找selector并调用。你不能说这没有增加复杂度。

再回头看看Swift的实现:

var p = Person()
p.sayHello()

在Swift中,编译器在调用方法的时候知道类型的更多信息。它准确的知道sayHell方法在哪里定义的。因此,Swift可以在方法调用的时候直接调转到方法定义的地方,而无需经过任何的动态分发过程。在其他的情况下,Swift也可以使用vtable风格的分发方式,比Objective-C的动态分发花费小得多了。这也是C++的虚方法使用的分发机制。

Swift的编译器也非常的有用。可以排除细微的类型相关的bug。它也能使你的代码运行的更快。

泛型

Swift带来的另一个很大的改变是泛型。如果你对C++很熟悉的花,那么你可以把这些和C++的template做类比。因为Swift是类型严格的,你必须方法可以接受的参数的类型。但是有的时候你的方法对于不同的类型来说作用是相同的。

比如,你希望把一对值存放在一起。你可以用Swift实现存放整型数值的结构:

struct IntPair {
    let a: Int!
    let b: Int!
    
    init(a: Int,b: Int){
        self.a = a
        self.b = b
    }
    
    func equal() -> Bool {
        return a == b
    }
}

let intPair = IntPair(a: 1,b: 1)
println("\(intPair.a)" + \(intPair.b) equal: \(intPair,equal())")

Sort of useful. But Now you want this to work for floating point numbers as well. You Could define aFloatPairclass,but that would look awfully similar. This is where generics come in. Instead of declaring a whole new class,you Could simply do this:

有点用处,但是你也想让这个可以用于浮点数。你可以定义一个FloatPair类, 但是实在是太相似了。这个时候泛型就会发挥用处了。相对于定义一个全新的类型,你可以这样:

struct Pair<T: Equatable> {
    let a: T!
    let b: T!
    
    init(a: T,b: T){
        self.a = a
        self.b = b
    }
    
    func equal() -> Bool {
        return a == b
    }
}

let tempPair = Pair<Int>(a: 1,b: 1)
var tempA = tempPair.a
var tempB = tempPair.b
var tempEqual: Bool = tempPair.equal()

println(\(tempA) \(tempB) equal: \(tempEqual)")

let tempPair1 = Pair<Float>(a: 1.0,b: 1.0)
var tempA1 = tempPair1.a
var tempB1 = tempPair1.b
var tempEqual1: Bool = tempPair.equal()

println(\(tempA1) \(tempB1) equal: \(tempEqual1)")

请各位读者原谅我用了这么烂得命名方式啊。。。

非常有用!你可能不是很清楚你为什么需要泛型,但是相信我会有很多时候你会用到。你很快会发现在哪里可以使用这些代码。

容器

也许你觉得NSArray和NSDictionary和对应的可变类型都已经很好用了。但是你需要学习对应的Swift容器。幸运的是,他们非常相似。如:

let array = [1,2,3,4,5]
let dictionary = [dog": 1,elephant": 2]

这些对你来说已经非常熟悉了。瞅一眼就可以搞定的。在Objective-C中,数组和字典可hi包含你想要的任何类型。但是在Swift中数组和字典是强类型的。而且这些容器都是泛型类型的。

上面的两个变量可以使用类型表达式来重写(你不是必须要这么做),比如:

let array: Array<Int> = [1,5]
let dictionary: Dictionary<String,Int> = [ Notice how generics are used to define what can be stored in the container. There is also a short form for these,which is slightly more readable,but essentially boils down to the same thing: 

注意泛型是怎么定义什么可以放进容器中的。定义的方式也有简短的方式的,可读性更好。但是本质上来说是一样的:

let array: [Int] = [1,5]
let dictionary: [String,Int] = [ 注意,这个时候你无法给数组添加任何的不是Int类型的值。这看起来不好,但是非常有用。你不再需要在文档中专门指明属性返回的数组中存放的是什么类型的值。编译器会自动检测错误并优化代码的编译。 

可变性

Swift容器的一个有意思的地方是他们都是可变的(mutable)。array和dictionary没有“mutable”的对应类型了。可变和不可变都由letvar关键字控制。let就是用来声明一个常量的关键字,var是用来声明一个变量的。let就像是C、C++或者Objective-C中得const关键字一样。

The way this relates to collections is that collections declared usingletcannot change size. That is,they cannot be appended to,or removed from. If you try to,then you get an error like so:

使用let声明的集合不能再修改size,也就是不能再append或者remove。如果你这么做了,就会报错:

'[int]' only has mutating members named append'

字典也同样使用这个规则。这允许编译器推测出这一类型的集合并作出相应的优化。如果size不能修改,集合的存储实现不再需要重新分配新的空间容纳新的值。因此,经常使用let来定义不再改变的集合是一个很好的实践。

字符串

Objective-C的字符串非常难用。即使是简单的拼接字符串之类的都需要写很多的代码。比如:

Person *person = ...;
 
NSMutableString *description = [[NSMutableString alloc] init];
[description appendFormat:@"%@ is %i years old.",person.name,person.age];
if (person.employer) {
  [description appendFormat: They work for %@.else {
  [description appendString: They are unemployed."];
}

This is quite tedious and contains a lot of characters that are nothing to do with the data being manipulated. The same in Swift would look like this:

这样的写法非常的冗长,而且包含了与本次操作无关的其他字符。同样的功能在Swift里看起来是这样的:

var description = ""
description += \(person.name) is \(person.age) years old."
if person.employer {
    description +=  They work for \(person.employer)."
} else {
    description += "
}

非常的清晰。更加清晰的创建一个字符串,你可以使用字符串拼接操作符+=。不再需要可变字符串和非可变字符串。

另一个Swift字符串的变化是”字符串的比较“。你知道在Objective-C中不能使用==来比较两个字符串的相等。你得用isEqualToString方法。这是应为==是比较的指针是否相等。Swift中可以直接使用==比较两个字符串。也就是说字符串可以在switch-case表达式中。更多相关请继续收看下一节内容。

Swift的字符串的另一个好东西是本地支持Unicode。你可以使用任意的Unicode字符,即使是在变量名和函数名中。如果你愿意你可以声明一个方法

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

Swift要点:从Objective-C开发者的角度看Swift的更多相关文章

  1. ios – 声明NSDictionary并在Swift中添加键值对?

    我一直在尝试使用类类型键和值来声明一个NSDictionary,如下所示:这里,“Category”和“SubCategory”是全局类.我知道我不能将类类型用于关键字段.但是,无论如何,我应该做到这一点.有没有办法做到这一点?如何声明专门的NSDictionary或类似的东西来做到这一点?

  2. ios – 异常断点处于活动状态时,应用程序在启动时崩溃

    我刚开始继续开发一款适用于商店的传统iPad应用程序.我注意到项目中的异常断点未启用.当我启用它时,应用程序在启动时崩溃,但在输出窗口中没有给出任何信息,而在线程视图中只有相当无用的信息(见下文)我试着解决它..>将Autolayout设置为关闭.>通过编辑和重新保存故事板文件..但到目前为止没有运气.我的猜测是,故事板中的某些内容被破坏了,因为AppDelegates“确实完成了启动……”

  3. ios – Swift相当于`[NSDictionary initWithObjects:forKeys:]`

    Swift的原生字典是否与[NSDictionaryinitWithObjects:forKeys:]相当?假设我有两个带键和值的数组,并希望将它们放在字典中.在Objective-C中,我这样做:当然我可以通过两个数组迭代一个计数器,使用vardict:[String:Int]并逐步添加东西.但这似乎不是一个好的解决方案.使用zip和enumerate可能是同时迭代两者的更好方法.然而,这种方法

  4. ios – 如何使用Objective C类中的多个参数调用Swift函数?

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  5. ios – Swift 4添加手势:覆盖vs @objc

    我想在我的视图中添加一个手势,如下所示:但是,在Swift4中,我的编译器给出了以下错误:建议添加@objc以将此实例方法公开给Objective-C.实现此目的的另一个选项将覆盖touchesBegan()函数并使用它来处理点击.我试图以“Swift”的方式做到这一点,而不必带入Obj-C.有没有纯粹的Swift方式来添加这个轻击手势而不使用@objc?

  6. ios – 将视频分享到Facebook

    我正在编写一个简单的测试应用程序,用于将视频从iOS上传到Facebook.由于FacebookSDK的所有文档都在Objective-C中,因此我发现很难在线找到有关如何使用Swift执行此操作的示例/教程.到目前为止我有这个在我的UI上放置一个共享按钮,但它看起来已禁用,从我读到的这是因为没有内容设置,但我看不出这是怎么可能的.我的getVideoURL()函数返回一个NSURL,它肯定包含视

  7. ios – Objective-C中“and”关键字的含义是什么?

    我在Xcode中输入了一条评论,但忘了领先//.我注意到了这一点并且突出显示为关键字.我做了一些谷歌搜索,但我似乎无法弄清楚它做了什么.这是什么意思?解决方法它是&&的同义词.见iso646.h.

  8. ios – 以编程方式在Swift中添加联系人

    我想在Swift中以编程方式添加联系人.我发现了一些Objective-C示例,但我没有让它们工作,甚至在Objective-C中也没有.我不希望这涉及到AddressBookUI,因为我想从我自己的UI中获取值.解决方法这是在Swift中添加联系人的快速方法.我在我的iPhone5iOS7.1上验证了它,因为我发现模拟器并不总是与我的手机对AB的东西相同.您可以添加一个按钮并指向此方法:顺便说一下–它假设你已经分配了一个地址簿var,你可以通过覆盖viewDidAppear来打开视图.它也会执行安全提示

  9. ios – Objective-C中的Google用户serverAuthCode nil

    我正在尝试将GoogleSignIn框架集成到iOS应用程序中,并对服务器上的用户进行身份验证.我设法登录用户,但在–(void)signIn:(GIDSignIn*)signIndidSignInForUser:(GIDGoogleUser*)用户withError:(NSError*)错误委托方法,user.serverAuthCode为nil,我需要通过此服务器身份验证代码,嗯,验证服务器上

  10. ios – 为目标c中的方法传递未知类型的参数,可能吗?

    是否可以将未知类型的参数传递给objective-C方法?在C#中你可以写实现这一点,但我知道Objective-C没有泛型,所以有没有其他方法可以在Objective-C中实现这一点?我需要这个,因为我想创建一个方法来改变不同对象的文本颜色,如UITextField和UIButton的占位符文本.所以我的计划是创建一个名为textWhite的方法,然后在此方法中检查对象的类型,然后运行匹配的代码以使文本颜色变为白色.解决方法是的,可以传递未知类型的参数.见下面的例子.请参考使用id对象的链接作为参数Us

随机推荐

  1. Swift UITextField,UITextView,UISegmentedControl,UISwitch

    下面我们通过一个demo来简单的实现下这些控件的功能.首先,我们拖将这几个控件拖到storyboard,并关联上相应的属性和动作.如图:关联上属性和动作后,看看实现的代码:

  2. swift UISlider,UIStepper

    我们用两个label来显示slider和stepper的值.再用张图片来显示改变stepper值的效果.首先,这三个控件需要全局变量声明如下然后,我们对所有的控件做个简单的布局:最后,当slider的值改变时,我们用一个label来显示值的变化,同样,用另一个label来显示stepper值的变化,并改变图片的大小:实现效果如下:

  3. preferredFontForTextStyle字体设置之更改

    即:

  4. Swift没有异常处理,遇到功能性错误怎么办?

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  5. 字典实战和UIKit初探

    ios中数组和字典的应用Applicationschedule类别子项类别名称优先级数据包contactsentertainment接触UIKit学习用Swift调用CocoaTouchimportUIKitletcolors=[]varbackView=UIView(frame:CGRectMake(0.0,0.0,320.0,CGFloat(colors.count*50)))backView

  6. swift语言IOS8开发战记21 Core Data2

    上一话中我们简单地介绍了一些coredata的基本知识,这一话我们通过编程来实现coredata的使用。还记得我们在coredata中定义的那个Model么,上面这段代码会加载这个Model。定义完方法之后,我们对coredata的准备都已经完成了。最后强调一点,coredata并不是数据库,它只是一个框架,协助我们进行数据库操作,它并不关心我们把数据存到哪里。

  7. swift语言IOS8开发战记22 Core Data3

    上一话我们定义了与coredata有关的变量和方法,做足了准备工作,这一话我们来试试能不能成功。首先打开上一话中生成的Info类,在其中引用头文件的地方添加一个@objc,不然后面会报错,我也不知道为什么。

  8. swift实战小程序1天气预报

    在有一定swift基础的情况下,让我们来做一些小程序练练手,今天来试试做一个简单地天气预报。然后在btnpressed方法中依旧增加loadWeather方法.在loadWeather方法中加上信息的显示语句:运行一下看看效果,如图:虽然显示出来了,但是我们的text是可编辑状态的,在storyboard中勾选Editable,再次运行:大功告成,而且现在每次单击按钮,就会重新请求天气情况,大家也来试试吧。

  9. 【iOS学习01】swift ? and !  的学习

    如果不初始化就会报错。

  10. swift语言IOS8开发战记23 Core Data4

    接着我们需要把我们的Rest类变成一个被coredata管理的类,点开Rest类,作如下修改:关键字@NSManaged的作用是与实体中对应的属性通信,BinaryData对应的类型是NSData,CoreData没有布尔属性,只能用0和1来区分。进行如下操作,输入类名:建立好之后因为我们之前写的代码有些地方并不适用于coredata,所以编译器会报错,现在来一一解决。

返回
顶部