码迷,mamicode.com
首页 > 编程语言 > 详细

NS_OPTIONS在swift中怎么实现?

时间:2015-08-18 18:47:35      阅读:370      评论:0      收藏:0      [点我收藏+]

标签:

技术分享

       今天在一个ios培训网站上看到一篇博客,讲的是在NS_OPTIONS在Swift中的实现,写得还算比较深刻全面,小编对其进行整理后,分享出来,希望对大家在iOS应用开发上有所帮助吧。

       在iOS开发中,我们常常需要定义一个枚举,以替代C语言枚举的定义方式,常用的方法就是在Objective-C中使用NS_ENUM和NS_OPTIONS。其中,NS_ENUM用于定义普通的枚举,NS_OPTIONS用于定义选项类型的枚举。

      不同于Objective-C语言,Swift中的枚举增加了更多特性,它可以包含原始类型(不再局限于整型)以及相关值。正是由于这些新增的特性,枚举在Swift中得到了更广泛的应用。在Foundation中,Objective-C中的NS_ENUM类型的枚举,都会自动转换成Swift中enum,并且更加精炼。以Collection View的滚动方向为例,在Objective-C中,其定义如下:

 

typedef NS_ENUM(NSInteger, UICollectionViewScrollDirection) {

  UICollectionViewScrollDirectionVertical,

  UICollectionViewScrollDirectionHorizontal

};

而在Swift中,其定义如下:

 

enum UICollectionViewScrollDirection : Int {

  case Vertical

  case Horizontal

}

       从上面这两段代码中,也可以看出swift中的实现确实精练了很多,在以后代码的维护上也方便。在编码中,定义枚举时,采用哪种方式,你应该清楚了吧。

不过对于Objective-C中NS_OPTIONS类型的枚举,Swift中的实现似乎就没有那么美好了。我们再来对比一下UICollectionViewScrollPosition的定义吧,在Objective-C中,其定义如下:

 

typedef NS_OPTIONS(NSUInteger, UICollectionViewScrollPosition) {

    UICollectionViewScrollPositionNone                 = 0,

 

    // The vertical positions are mutually exclusive to each other, but are bitwise or-able with the horizontal scroll positions.

    // Combining positions from the same grouping (horizontal or vertical) will result in an NSInvalidArgumentException.

    UICollectionViewScrollPositionTop                  = 1 << 0,

    UICollectionViewScrollPositionCenteredVertically   = 1 << 1,

    UICollectionViewScrollPositionBottom               = 1 << 2,

 

    // Likewise, the horizontal positions are mutually exclusive to each other.

    UICollectionViewScrollPositionLeft                 = 1 << 3,

    UICollectionViewScrollPositionCenteredHorizontally = 1 << 4,

    UICollectionViewScrollPositionRight                = 1 << 5

};

而在Swift 2.0中,其定义如下:

 

struct UICollectionViewScrollPosition : OptionSetType {

    init(rawValue: UInt)

 

    static var None: UICollectionViewScrollPosition { get }

 

    // The vertical positions are mutually exclusive to each other, but are bitwise or-able with the horizontal scroll positions.

    // Combining positions from the same grouping (horizontal or vertical) will result in an NSInvalidArgumentException.

    static var Top: UICollectionViewScrollPosition { get }

    static var CenteredVertically: UICollectionViewScrollPosition { get }

    static var Bottom: UICollectionViewScrollPosition { get }

 

    // Likewise, the horizontal positions are mutually exclusive to each other.

    static var Left: UICollectionViewScrollPosition { get }

    static var CenteredHorizontally: UICollectionViewScrollPosition { get }

    static var Right: UICollectionViewScrollPosition { get }

}

光看代码,不看实现,这也是化简为繁的节奏。

为什么要在swift中这样做呢?Mattt给我们的解释是:

由于Swift不支持C语言中枚举值的整型掩码操作的技巧,在Swift中,一个枚举可以表示一组有效选项的集合,但却没有办法支持这些选项的组合操作(“&”、”|”等)。理论上,一个枚举可以定义选项值的任意组合值,但对于n > 3这种操作,却无法有效的支持。

 

为了支持类NS_OPTIONS的枚举,Swift 2.0中定义了OptionSetType协议,它的声明如下:

 

/// Supplies convenient conformance to `SetAlgebraType` for any type

/// whose `RawValue` is a `BitwiseOperationsType`.  For example:

///

///     struct PackagingOptions : OptionSetType {

///       let rawValue: Int

///       init(rawValue: Int) { self.rawValue = rawValue }

///    

///       static let Box = PackagingOptions(rawValue: 1)

///       static let Carton = PackagingOptions(rawValue: 2)

///       static let Bag = PackagingOptions(rawValue: 4)

///       static let Satchel = PackagingOptions(rawValue: 8)

///       static let BoxOrBag: PackagingOptions = [Box, Bag]

///       static let BoxOrCartonOrBag: PackagingOptions = [Box, Carton, Bag]

///     }

///

/// In the example above, `PackagingOptions.Element` is the same type

/// as `PackagingOptions`, and instance `a` subsumes instance `b` if

/// and only if `a.rawValue & b.rawValue == b.rawValue`.

protocol OptionSetType : SetAlgebraType, RawRepresentable {

 

    /// An `OptionSet`‘s `Element` type is normally `Self`.

    typealias Element = Self

 

    /// Convert from a value of `RawValue`, succeeding unconditionally.

    init(rawValue: Self.RawValue)

}

从字面上来看,OptionSetType是选项集合类型,它定义了一些基本操作,包括集合操作(union, intersect, exclusiveOr)、成员管理(contains, insert, remove)、位操作(unionInPlace, intersectInPlace, exclusiveOrInPlace)以及其它的一些基本操作。

 

作为示例,我们来定义一个表示方向的选项集合,通常我们是定义一个实现OptionSetType协议的结构体,如下所示:

 

struct Directions: OptionSetType {

 

    var rawValue:Int

    init(rawValue: Int) {

        self.rawValue = rawValue

    }

 

    static let Up: Directions = Directions(rawValue: 1 << 0)

    static let Down: Directions = Directions(rawValue: 1 << 1)

    static let Left: Directions = Directions(rawValue: 1 << 2)

    static let Right: Directions = Directions(rawValue: 1 << 3)

}

所需要做的基本上就是这些。然后我们就可以创建Directions的实例了,如下所示:

 

let direction: Directions = Directions.Left

if direction == Directions.Left {

    // ...

}

如果想同时支持两个方向,则可以如上处理:

 

let leftUp: Directions = [Directions.Left, Directions.Up]

if leftUp.contains(Directions.Left) && leftUp.contains(Directions.Up) {

    // ...

}

如果leftUp同时包含Directions.Left和Directions.Up,则返回true。

 

这里还有另外一种方法来达到这个目的,就是我们在Directions结构体中直接声明声明Left和Up的静态常量,如下所示:

 

struct Directions: OptionSetType {

 

    // ...

    static let LeftUp: Directions = [Directions.Left, Directions.Up]

    static let RightUp: Directions = [Directions.Right, Directions.Up]

    // ...

}

这样,我们就可以以如下方式来执行上面的操作:

 

if leftUp == Directions.LeftUp {

    // ...

}

当然,如果单一选项较多,而要去组合所有的情况,这种方法就显示笨拙了,这种情况下还是推荐使用contains方法。

 

      总体来说,虽然Swift中的对选项的支持没有Objective-C中的NS_OPTIONS来得简洁方便,但相比Swift 1.2,Swift 2.0已经有了很大的改善。Swift作为一门新的iOS开发语言,其很多方面在Objective-C的基础上都有了很大的改善,且swift成为今后iOS开发主流语言是必然,所以对于NS_OPTIONS的实现,大家还是需要尝试用Swift语言,慢慢习惯就好了。

 

NS_OPTIONS在swift中怎么实现?

标签:

原文地址:http://www.cnblogs.com/maizi007/p/4739909.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!