oc使用swift中的枚举_swift 枚举与oc枚举的区别 - CSDN
  • ENUM-枚举

    最近在github上看见一篇<<招聘一个靠谱的iOS>>,看了看里面的试题,都是些很基础又很底层的东西,当然现在还再学习中,能从微博@iOS程序犭袁 所提供的答案中学习到很多之前不知道的知识。现在才察觉到,原来自己的所需要学习的还有很多很多,和这些大牛相比,更是渣渣都不是啊!而且出这套题的”孙源” ,就职于百度,而且还是90后,想想自己一个80后,真的很差,好了,不多说这些,从现在努力向前就好了!

    其中第一道题就是有枚举(ENUM)规范写法的问题,正巧今天又在枚举上碰上问题,所以就简单总结了下枚举相关的简单东西。

    当然,下面的问题,我就只总结关于枚举。

    enter image description here

    修改完的代码:

    修改方法有很多种,现给出一种做示例:

    // .h文件
    // 修改完的代码,这是第一种修改方法,后面会给出第二种修改方法
    
        typedef NS_ENUM(NSInteger, CYLSex) {
            CYLSexMan,
            CYLSexWoman
        };
    
        @interface CYLUser : NSObject<NSCopying>
    
        @property (nonatomic, readonly, copy) NSString *name;
        @property (nonatomic, readonly, assign) NSUInteger age;
        @property (nonatomic, readonly, assign) CYLSex sex;
    
        - (instancetype)initWithName:(NSString *)name age:(NSUInteger)age sex:(CYLSex)sex;
        + (instancetype)userWithName:(NSString *)name age:(NSUInteger)age sex:(CYLSex)sex;
    
        @end

    enum建议使用 NS_ENUMNS_OPTIONS 宏来定义枚举类型,参见官方的 Adopting Modern Objective-C 一文:

    // 定义性别的枚举 这样可能就比较严谨
    typedef NS_ENUM(NSInteger, CYLUserGender) {
        CYLUserGenderUnknown,
        CYLUserGenderMale,
        CYLUserGenderFemale,
        CYLUserGenderNeuter
    };

    提供问题答案大神微博 http://weibo.com/luohanchenyilong/
    提供问题答案大神的github https://github.com/ChenYilong

    • 常见枚举类型定义
    typedef enum
    {
        East,
        South,
        West,
        North
    }Direction;
    • 在iOS6和Mac OS 10.8以后Apple引入了两个宏来重新定义这两个枚举类型,实际上是将enum定义和typedef合二为一,并且采用不同的宏来从代码角度来区分。
    • 从枚举定义来看,NS_ENUM和NS_OPTIONS本质是一样的,仅仅从字面上来区分其用途。NS_ENUM是通用情况,NS_OPTIONS一般用来定义具有位移操作或特点的情况(bitmask)。
    typedef NS_ENUM(NSInteger, UIViewAnimationTransition) {  
            UIViewAnimationTransitionNone,//默认从0开始  
            UIViewAnimationTransitionFlipFromLeft,  
            UIViewAnimationTransitionFlipFromRight,  
            UIViewAnimationTransitionCurlUp,  
            UIViewAnimationTransitionCurlDown,  
        };  
    
    typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {  
            UIViewAutoresizingNone                 = 0,  
            UIViewAutoresizingFlexibleLeftMargin   = 1 << 0,  
            UIViewAutoresizingFlexibleWidth        = 1 << 1,  
            UIViewAutoresizingFlexibleRightMargin  = 1 << 2,  
            UIViewAutoresizingFlexibleTopMargin    = 1 << 3,  
            UIViewAutoresizingFlexibleHeight       = 1 << 4,  
            UIViewAutoresizingFlexibleBottomMargin = 1 << 5  
        }; 
    

    这两个宏的定义在Foundation.framework的NSObjCRuntime.h中

    #if (__cplusplus && __cplusplus >= 201103L && (__has_extension(cxx_strong_enums) || __has_feature(objc_fixed_enum))) || (!__cplusplus && __has_feature(objc_fixed_enum))  
    #define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type  
    #if (__cplusplus)  
    #define NS_OPTIONS(_type, _name) _type _name; enum : _type  
    #else  
    #define NS_OPTIONS(_type, _name) enum _name : _type _name; enum _name : _type  
    #endif  
    #else  
    #define NS_ENUM(_type, _name) _type _name; enum  
    #define NS_OPTIONS(_type, _name) _type _name; enum  
    #endif  

    Swift中的枚举相对于C语言变化还是很大的

    写到这里发觉自己的功底还是不行,然后又去看了大牛的几篇文章,感觉自己再怎么总结,也没有人家的深度与广度,还不如趁这个时间去多学习学习呢!

    // Swift 中简单使用枚举 
    enum RequsetMethod: String {
        case GET = "GET"
        case POST = "POST"
    }

    Swift中枚举的使用,这个不算转载吧!参考此篇文章学习吧!

    C中枚举使用,这篇博文我感觉就很详细了!参考此篇博文学习吧!

    展开全文
  • 前言14年Swift刚出的时候开始学习的Swift,后来...这个系列不是讲解Swift基础,主要是讲解OC(以下OC均指的是Objective C)转过来的同学有些习惯要改变了,才能更好的使用Swift的很多优秀特性。枚举通常,你在Objecti

    前言

    14年Swift刚出的时候开始学习的Swift,后来由于项目需要,一直写App还是用的OC。最近打算把Swift重新捡起来,这个Objective C转Swfit系列就当成是我的复习笔记,顺便写成博客记录下来吧。

    这个系列不是讲解Swift基础,主要是讲解OC(以下OC均指的是Objective C)转过来的同学有些习惯要改变了,才能更好的使用Swift的很多优秀特性。

    枚举

    通常,你在Objective C中,用枚举NS_ENUM来定义有限的状态,比如,假如我们要表示一个登录的结果

    typedef NS_ENUM(NSInteger,LHLoginResult){
        LHLoginResultSucceess, //成功
        LHLoginResultFailure, //失败
        LHLoginResultError, //出错了
    };

    其实,OC中,枚举更像一个加强版的整型

    假如,把这个简单的转为Swift,那么看起来是这样子的。

    enum LoginResult {
        case Success
        case Failure
        case Error
    }

    如果是这么写枚举,你真的是暴殄天物了

    Swift枚举是first-class types,它有很多Swift class具有的特性

    • Associated Values 关联值
    • 计算属性
    • 实例方法
    • 构造函数
    • 遵循协议
    • 支持extensions

    好了,那么Swift中,这样的一个“登录结果”应该如何用枚举来表示呢?

    通常,失败的时候,我们希望知道失败的原因是啥,出错的时候,我们希望知道错误的原因是啥。

    利用Associated Values 关联值,来实现这一点

    于是,这个枚举变成了酱紫

    enum LHLoginResult {
        case Success
        case Failure(message:String)
        case Error(error:NSError)
    }
    

    等等,现在是三种结果,要是能提供一个接口,只返回给我一个Bool,告诉我登陆成功还是失败就更好了

    利用Extension和计算属性,我们添加一个方便的接口

    extension LoginResult{
        var isSuccess:Bool{
            switch self {
            case .Success:
                return true
            default:
                return false
            }
        }
    }
    

    通常,App需要Log出一些信息,我们继续完善这个枚举,让它支持Log

    用extension,让这个枚举遵循协议CustomStringConvertible(Swift中的一个log相关的协议)

    extension LoginResult:CustomStringConvertible{
        var description: String {
            switch self {
            case .Success:
                return "Success"
            case let .Failure(message):
                return message
            case let .Error(error):
                return error.localizedDescription
            }
        }
    }

    除此之外,Swift的枚举还支持RawValues

    enum ASCIIControlCharacter: Character {
        case Tab = "\t"
        case LineFeed = "\n"
        case CarriageReturn = "\r"
    }

    再深入一点,我们来看看Swift中一些默认使用枚举来定义的类型

    Optional

    public enum Optional<Wrapped> : _Reflectable, NilLiteralConvertible {
        case None
        case Some(Wrapped)
        /// Construct a `nil` instance.
        public init()
        /// Construct a non-`nil` instance that stores `some`.
        public init(_ some: Wrapped)
        /// If `self == nil`, returns `nil`.  Otherwise, returns `f(self!)`.
        @warn_unused_result
        public func map<U>(@noescape f: (Wrapped) throws -> U) rethrows -> U?
        /// Returns `nil` if `self` is `nil`, `f(self!)` otherwise.
        @warn_unused_result
        public func flatMap<U>(@noescape f: (Wrapped) throws -> U?) rethrows -> U?
        /// Create an instance initialized with `nil`.
        public init(nilLiteral: ())
    }
    

    可见,Optional本身就是一个枚举,包含了两种可能性:None(nil),Some(Wrapped)(这里利用了Swift范型)。


    结构体

    除了枚举之外,结构体也是Objective C转过来的同学比较容易忽略的一个数据结构。

    Swift的结构体和C的结构体有很大区别,它有很多Class相关的特性

    • 定义属性来存储值
    • 定义方法来提供功能
    • 定义subscripts,来实现用下标访问[]
    • 定义构造函数,来初始化
    • 遵循某一个协议
    • 支持extenstion

    当然,有一些特性是它不具有的

    • 继承
    • 类型转换和runtime类型检查
    • deinit方法,来进行销毁时候的资源释放
    • 引用计数,让多个引用指向同一个实例。

    比如,在OC中,你通常这样写一个Model

    //头文件
    @interface LHPerson : NSObject<NSCopying,NSCoding>
    
    @property (copy,nonatomic)NSString * name;
    
    @property (assign,nonatomic)NSUInteger age;
    
    - (instancetype)initWithName:(NSString *)name age:(NSUInteger)age;
    
    + (instancetype)personWithName:(NSString *)name age:(NSUInteger)age;
    
    @end
    
    //.m文件
    @implementation LHPerson
    - (instancetype)initWithName:(NSString *)name age:(NSUInteger)age{
        if (self = [super init]) {
            _name = name;
            _age = age;
        }
        return self;
    }
    + (instancetype)personWithName:(NSString *)name age:(NSUInteger)age{
        return [[self alloc] initWithName:name age:age];
    }
    #pragma mark - NSCoding
    - (instancetype)initWithCoder:(NSCoder *)aDecoder{
        if (self = [super init]) {
            _name = [aDecoder decodeObjectForKey:@"name"];
            _age = [aDecoder decodeIntegerForKey:@"age"];
        }
        return self;
    }
    - (void)encodeWithCoder:(NSCoder *)aCoder{
        if (_name != nil) [aCoder encodeObject:_name forKey:@"name"];
        [aCoder encodeInteger:_age forKey:@"age"];
    }
    #pragma mark - NSCopying
    - (instancetype)copyWithZone:(NSZone *)zone{
        LHPerson * copyed = [[self.class allocWithZone:zone] init];
        copyed->_age = self.age;
        copyed->_name = self.name;
        return copyed;
    }
    @end
    

    难么,同样的Model,在Swift应该怎么写呢?

    上面的Model更适合结构体来存储

    通常,你可以这么写

    struct Person{
        var name:String
        var age:Int
        init(name:String,age:Int){
            self.name = name
            self.age = age
        }
    }

    为了自定义Log,我们可以让结构体实现CustomStringConvertible协议

    struct Person:CustomStringConvertible{
        var name:String
        var age:Int
        init(name:String,age:Int){
            self.name = name
            self.age = age
        }
        var description: String{
            return "Name:\(name) Age:\(age)"
        }
    }
    

    结构体相对于Class的优势在于

    • Struct是值类型,每次传递的时候,都会进行一次拷贝,也就是说,在多线程的环境下,它是线程安全的,当你把一个Struct作为参数传递给一个Class的时候,你不需要担心这个Class会修改我原始的Struct
    • Struct不需要考虑内存泄漏

    通常,当以下一条或者多条满足的时候,你可以优先考虑使用结构体

    • 这个数据结构主要目的是用来封装一系列相关的值的时候
    • 当传递值的时候,希望传递的是拷贝的时候
    • 这个数据结构本身存储的数据也是值类型,也就是说传递的时候是值传递
    • 这个数据结构不需要从其他地方继承。

    Array,Dictionary本质上都是结构体

    public struct Array<Element> : CollectionType, MutableCollectionType, _DestructorSafeContainer {
        public var startIndex: Int { get }
        public var endIndex: Int { get }
        public subscript (index: Int) -> Element
        public subscript (subRange: Range<Int>) -> ArraySlice<Element>
    }
    
    //省略掉Array的Exetensions ...
    

    Extensions

    Swift的Extensions可以给class,struct,enum,protocol添加功能性的方法/属性/subscripts。这和Objective C的Category很像。但是Swift Extension更加强力,并且不像Category,它不需要名字。

    通过Extensions,你可以

    • 增加计算属性,或者计算类型的属性
    • 定义实例方法和类型方法
    • 提供新的构造函数
    • 定义和使用嵌套类型
    • 定义subscripts
    • 让一个类型遵循一个协议

    红色的部分是个人觉得比较容易忽略的。

    协议扩展

    协议扩展是OC转过来的最容易忽略的,Swift是一个很适合《面相协议编程的语言》,很多基本的类型。比如AnyObject和Any都是协议类型(事实上,在Swift的时候,不知不觉你已经面相协议编程了)。

    @objc public protocol AnyObject {
    }
    public typealias Any = protocol<>

    其中,协议扩展最灵活的地方是,支持where语句条件扩展

    比如,这是我写Swift代码的一个自定义操作符SetUp,用协议来定义的。

    public protocol SetUp {}
    extension SetUp where Self: AnyObject {
        //Add @noescape to make sure that closure is sync and can not be stored
        public func SetUp(@noescape closure: Self -> Void) -> Self {
            closure(self)
            return self
        }
    }
    extension NSObject: SetUp {}

    然后,我只是希望,当AnyObject遵循这个协议的时候具有具有SetUp.接着,用第二次协议扩展,来让NSObject遵循这个协议。于是,任何NSObject的子类,你都可以这么调用

    let textfield = UITextField().SetUp {
         $0.frame = CGRectMake(0, 0,200, 30)
         $0.textAlignment = .Center
         $0.font = UIFont.systemFontOfSize(14)
         $0.center = view.center
         $0.placeholder = "Input some text"
         $0.borderStyle = UITextBorderStyle.RoundedRect
     }

    extensions也可以用来设计接口

    系统的SequenceType是Array遵循的协议,于是你可以这样调用

    let array = [1,2,3,4,5]
    let array2 = array.filter({$0 > 1}).map({$0 * 2})//4 6 8 10

    其中,这个map的定义如下

    public func map<T>(@noescape transform: (Self.Generator.Element) throws -> T) rethrows -> [T]
    

    我们可以自定义myMap来定义个自己的映射方法。

    extension SequenceType{
        public func myMap<T>(@noescape transform: (Self.Generator.Element) throws -> T) rethrows -> [T]{
            print("Map begin")
            var result = [T]()
            try self.forEach { (e) in
                do{
                    let item = try transform(e)
                    result.append(item)
                }catch let error{
                    throw error
                }
            }
            print("Map end")
            return result
        }
    }
    
    let arr = [1,2,3]
    let mapped = arr.myMap({"\($0)"})
    
    print(mapped)

    会发现Log

    Map begin
    Map end
    ["1", "2", "3"]

    知名的Swift函数响应式编程开源库RxSwift,就是利用了Extensions,来让你定义自己的操作符

    extensions的常用用途

    分离代码逻辑

    把部分逻辑放倒extensions中,能够让代码更易于维护可扩展

    class  TableviewController: UITableViewController {
    
    }
    extension TableviewController{
        override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            //
        }
        override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    
        }
        override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    
        }
    }

    再看看系统Array

    public struct Array<Element> : CollectionType, MutableCollectionType, _DestructorSafeContainer {
       //...
    }
    
    extension Array : ArrayLiteralConvertible {
           //...
    }
    
    extension Array : _ArrayType {
        //...
     }

    通过extension,把代码逻辑分离开.从而实现:《对扩展开放,对修改封闭》

    扩展没有源代码(不易修改源代码)的类

    比如,你在OC中,的工具方法,可以这么写

    Tips:这里可以不写前缀lh_

    extension UIScreen{
        class var lh_width:CGFloat{
            get{
                return UIScreen.mainScreen().bounds.size.width
            }
        }
        class var lh_height:CGFloat{
            get{
    
                return  UIScreen.mainScreen().bounds.size.width
            }
        }
        class var lh_bounds:CGRect{
            get{
                return UIScreen.mainScreen().bounds
            }
        }
    }
    

    总结

    并不是什么高深的东西,写出来加深下印象,也分享给觉得有用的人。

    展开全文
  • swift enum 和OC兼容

    2015-07-09 16:25:22
    虽然说swift是基于OC的,但是swiftOC还是有很多去别的,今天我们来说一下枚举变量 下面是某个免费短信验证码的验证方法的返回状态 enum SMS_ResponseState { SMS_ResponseStateFail = 0, SMS_...

    虽然说swift是基于OC的,但是swift和OC还是有很多去别的,今天我们来说一下枚举变量

    下面是某个免费短信验证码的验证方法的返回状态

    enum SMS_ResponseState
    {
        SMS_ResponseStateFail = 0,
        SMS_ResponseStateSuccess=1
    };
    这是一个正常的OC枚举写法,但是如果你在swift里面调用这个写在OC里面的枚举想进行操作的话,那么对不起,你会收到各种错误提示

    比如你不能这样

    if verifyState == SMS_ResponseState.Success

    会报下面的错误(这个绝不是.Success调用错的愿意)

    'SMS_ResponseState.Type' does not have a member named 'Success'
    你也不能这样

    <span style="font-size:12px;">if verifyState == 1</span>
    会报下面的错误

    Binary operator '==' cannot be applied to operands of type 'SMS_ResponseState' and 'Int'
    但是下面的方法可以进行调用,但是我没有找到下一步进行操作的方法,有人研究出来还望不吝指教

    let state = SMS_ResponseState(1)
    同时你也不能这样去写

    let state1 = SMS_ResponseState(0)
    let state2 = SMS_ResponseState(1)
    if state1 == state2 {
    }

    具体为什么会这样,我也不知道原因,如果哪位大神研究出来了,希望能分享一下,最终我的解决方法是只能修改枚举的写法,比如下面的写法

    typedef NS_OPTIONS(NSUInteger, SMS_ResponseState){swift
        SMS_ResponseStateFail = 0,
        SMS_ResponseStateSuccess=1
    };



    展开全文
  • OC枚举Swift 枚举

    2016-07-31 08:56:30
    OC枚举Swift 枚举介绍

    OC枚举和Swift 枚举


    下面介绍一下 OC 枚举和 Swift 枚举的写法!

    OC枚举:


             


    Swift 枚举:

                


     以上,希望对大家会有所帮助,谢谢!










    展开全文
  • 今天介绍一下在OC文件声明了一个枚举类型,如何在Swift文件调用该枚举类型的值。 1.项目工程构建的时候选的是Swift语言,项目名称TestProject。 2.建立一个Swift文件SwiftTestFile.swift 和一个OC的文件 ...
  • Swift 调用OC枚举

    2019-09-17 14:35:00
    OC中 typedef NS_ENUM (NSUInteger, EVDeviceType) { EVDeviceAudioCapture = 0, EVDeviceAudioPlayback = 1, EVDeviceVideoCapture = 2 }; Swift EVDeviceType.audioCapture
  • 二十二 Swift3.0之 枚举

    2017-04-08 17:01:41
    Swift枚举: Swift的枚举比OC中的枚举强大, 因为Swift的枚举是一等类型, 它可以像类和结构体一样增加属性和方法 格式: enum Method{ case 枚举值 } */enum Method{ // case Add // case Sub // case Mul // case...
  • Swift上调用OC封装好的一个model,里面有个枚举类型: typedef enum {  kCOManageCreater = 1, //创始人  kCOManageManager, //管理员  kCOManageNormal,  //普通用户 }kCOManagerType; 然后再s
  • Swift中的枚举比OC中的枚举强大得多, 因为Swift中的枚举是一等类型,它除了可以定义枚举值外,还可以在枚举中像类一样定义属性和方法 1. 简单枚举定义和使用 //定义枚举,使用enum关键字 enum Method{ case Add ...
  • 1. Swift枚举基本概念 Swift的枚举比OC中的枚举强大, 因为Swift的枚举是一等类型, 它可以像类和结构体一样增加属性和方法 格式: enum Method{ case 枚举值 }enum Method{ case Add case Sub case Mul case...
  • Swift 枚举(七)

    2014-06-20 16:09:14
    用enum并把定义放在大括号内,枚举中被定义的值是枚举的成员,case关键字表示新定义的一个成员 enum SomeEnumeration {  // enumeration definition goes here } enum CompassPoint {  case North  case ...
  • 枚举我们大家都不太陌生了,我们在C或者OC中经常使用到,在这里简单记录下Swift中枚举使用方法. 枚举的定义 “在 Swift 枚举类型是一等(first-class)类型。它们采用了很多在传统上只被类(class)所支持的特性...
  • Swift中枚举

    2016-10-11 16:24:59
    相比OC中枚举而言,Swift中枚举功能更强大,也新增了很多特性,今天就简单的罗列一下。 枚举使用case关键字来定义新的成员,可以一行写但是要以逗号分开也可以多行写。 在Swift中枚举类型有个关联值,对于枚举...
  • Swift 枚举

    2015-08-25 19:14:59
    枚举是一种常见的数据类型,他的主要功能就是将某...使用枚举可以防止用户使用无效值,同时该变量可以使代码更加清晰。 //1 枚举的声明 //我们直接看示例,一般有两种方式,一个一个写,还有可以写一行 enum O
  • OC里面我们经常遇到一些枚举值可以多选的,需要用或运算来把这些枚举值链接起来,这样的我们称为位移枚举,但是在swift里面却不能这么做,下面来讲解一下如何在swift里面使用 OC的位移枚举的区分//位移枚举 ...
  • Objective-C 枚举 typedef NS_ENUM(NSInteger,LineDirection){ LineDirectionTop = 1 &lt;&lt; 0, LineDirectionBottom = 1 &lt;&lt; 1, LineDirectionLeft = 1 &lt;&lt; 2, ...
  • Swift中枚举enum。在C语言,甚至OC等其他高级语言,都是把enum枚举的值当作是一个int整数来替代。而在Swift中,它的case就是它的值本身,无需刻意地定义一个值来代表它。
  • OC: 相同点:都可以将多个数据封装为一个整体。 不同点: 1. 结构体只能封装数据,而类还可以封装行为。 2. 赋值 :结构体是(拷贝),对象之间是(地址) 3. 结构体变量分配在栈空间(如果是一个局部变量的...
  • 概述 Swift的设计的初衷就是摆脱...随着Swift的改进及Swift开源项目剧增,越来越多的Objective-C工程开始使用Swift混编,不管是在基于Swift工程或者Objective-C工程Swift和Objective-C文件都可以无缝结合。本文
  • SwiftOC 互相调用

    2018-07-20 16:19:07
    Swift 调用 OC 分为两种常见情况,一种是直接在 Application 的 project 中使用;另一种情况是,在 framework 开发中使用。 对于互相调用的原理,如下图所示,更详细的内容可以参考 《Using Swif with Cocoa and ...
1 2 3 4 5 ... 20
收藏数 2,206
精华内容 882
关键字:

oc使用swift中的枚举