和结构体一样,swift中的枚举也是值类型。除了定义一个或多个case成员,还可以做以下事情:
和结构体的唯一区别就是枚举不能定义存储属性
1. 枚举的语法:
enum TextAlignment{
case left
case right
case center
}
//或者 写在一行
enum TextAlignment{
case left, right, center
}
2. 遵守协议&遍历枚举值
例如:系统自带的CaseIterable协议,allCases属性列出所有的枚举成员,也可以通过手动添加计算属性或方法达到同样的目的,对于没有关联值的枚举,编译器会自动为其实现allCases(成员顺序和声明时候一致)
extension TextAlignment:CaseIterable{}
TextAlignment.allCases // left right center
// 或者 手动添加计算属性
extension TextAlignment {
static var allCases: [TextAlignment] {
[.left,.right,.center]
}
}
3. 原始值、隐式赋值
C或Objective-C中的枚举,是可以通过0 1 2 3...来初始化和使用。Swift枚举默认不会为每个成员分配0 1 2 3...也不能通过整数初始化枚举。要想获得这种特性,必须添加原始值。语法如下
enum TextAlignment:Int {}
原始值可以是字符串、字符或任何整数或浮点数类型。但是每个值对应的原始值必须是唯一的。
enum TextAlignment:String {
case left = "0"
case right = "1"
case center = "2"
}
通过rawValue创建的枚举值是可选的?
var aligent = TextAlignment(rawValue:"1")
// Optional(TextAlignment. right)
RawRepresentable协议
实现
RawRepresentable协议的类型会获得两个新的 API:一个 rawValue 属性和一个可失败的初始化方法 (init?(rawValue:)),编译器自动为具有原始值的枚举实现这个协议。
编译器会通过递增前一个成员的原始值来给下一个枚举成员赋值。
enum TextAlignment:Int{
case left
case right
case center
}
// 系统会自动分配 0 ,1,2给成员
var alignment : TextAlignment = .center
alignment.rawValue // 2
原始值是String的时候,默认情况下系统用 case 值来初始化枚举原始值:
enum TextAlignment:String{
case left
case right
case center
}
var alignment: TextAlignment = .left
print(alignment.rawValue) // "left"
4. 枚举关联值
原始值与关联值不同,枚举成员一旦设置了原始值使用中就不能在变,关联可以根据使用变化。
一个确定枚举值加上其关联值可以使的该枚举类型有更多的成员,Swift可以枚举成员关联任意类型的值
enum TextAlignment{
case left(String)
case right(String)
case center(CGFloat,CGFloat)
}
5. 枚举支持范型&关联值
范型是Swift最强大的功能之一,Swift标准库的大部分都是用通用代码构建的。它能使您编写灵活、可重用的函数和类型,这些函数和类型可以根据您定义的要求适用于任何类型,避免重复的代码。
关于枚举的范型,看如下的例子:
定义范型枚举Result
// 定义范型枚举Result
enum Result<Success, Failure>{
case success(Success)
case failure(Failure)
}
使用Result
struct LError:Error{
var message = "错误信息"
}
// 网络请求结果
var result:Result<Dictionary, LError > = .success(["code":"200"])
// 失败时
result = .failed(LError(message: "404"))
//通过switch匹配结果
switch result{
case.success(let data):
print(data)
case.failed(let error):
let ler = error as! LError
print(ler.message)
}
实际上,范型枚举都是和关联值结合使用的。Swift自带的Result类型也是这种形式的枚举。
假如我们要从本地磁盘读取文件,这个过程可能会失败,可以设定读取结果可选?这样以来,读取失败就会返回nil,但是我们不知道失败的原因,Result就可以表达那些需要提供详细信息的错误。如果我们不关注错误原因,直接忽略failed后面的关联值即可(下文有讲述如何忽略关联值)。
Swift 要求枚举必须考虑到每一种情况,最常用方法就是使用 switch 语句
普通枚举,没有关联值的情况
var aligent:TextAlignment = .left
// 模式匹配 ,所有情况 left, right,center
switch aligent{
case .left:
break
case .right:
break
case .center:
break
}
通配符 _ ,下划线匹配任意值并忽略这个值,等同default
// default 忽略
switch aligent {
case .left:
break
default:
break
}
// 通配符 _
switch aligent {
case .left:
break
case _ :
break
}
匹配多个值的情况,多个枚举值可以写在一行,也可以使用通配符_,default。
// 匹配多个的情况
switch aligent {
case .left,.right:
break
case .center:
break
}
除了switch之外,也可以用if 和if case 匹配
if aligent == .left{
// do ...
}
if case .left = aligent {
// do ...
}
值绑定模式,像处理可选值一样,可以把枚举的关联值绑定到一个let or var 声明的变量上,带关联值的枚举如下:
var aligent1:TextAlignment = .left("left")
var aligent2:TextAlignment = .center(0, 0)
// 值绑定模式
switch aligent1 {
case .left(let string): //绑定到变量 string
break
case .right(let string):
break
case .center(let x, let y): //绑定到变量x,y
break
}
// let写在前面也是可以的
switch aligent1 {
case let.center(x, y):
break
case let.right(str):
break
case _:
break
}
如果想忽略关联值,可以按照编译器提示用下划线_忽略,或者不写后面的括号()
// 用下划线_忽略
switch aligent1 {
case .left(_):
break
case .right(_):
break
case .center(_,_):
break
}
// 不写后面的括号()
switch aligent1 {
case .left:
break
case .right:
break
case .center:
break
}
关联值有单个or多个,匹配确定的关联值。
// 匹配确定的关联值 center(x,y)中的x=0,y=0的情况
switch aligent1 {
case .center(0,_):
break
case _:
break
}
// 只匹配确定的关联值 center(x,y)中的x=0的情况
switch aligent1 {
case .center(0,_):
break
case _:
break
}
假设我有一个可枚举对象enum,现在我想获取第三个项目。我知道一种通用方法是转换成数组,然后使用索引访问,如:enum.to_a[2]但这种方式会创建一个临时数组,效率可能很低。现在我使用:enum.each_with_index{|v,i|breakvifi==2}但这非常丑陋和多余。执行此操作最有效的方法是什么? 最佳答案 你可以使用take剥离前三个元素,然后剥离last从take给你的数组中获取第三个元素:third=enum.take(3).last如果您根本不想生成任何数组,那么也许:#Ifenumisn'tanEnum
以下是我认为的一些下拉列表:'form-control')%>和'form-control')%>这是我的application_helper.rbdefget_advance_bookingret=[{:require_booking=>'No'},{:require_booking=>'Yes'}]enddefget_instant_bookingret=[{:instant_booking=>'No'},{:instant_booking=>'Yes'}]end但现在的问题是,在我的模型product.rb中,我无法设置具有相同名称的枚举:classProduct我收到的错误是您
我正在使用Enumerizegemhttps://github.com/brainspec/enumerize/它允许我以简单的形式使用漂亮的选择。并且此选择中的所有选项均已翻译。en:enumerize:user:sex:male:'Man'female:'Woman'所以,在我的表单中,我选择了变体“男人”和“女人”。当我用“男人”值保存记录时,我得到了“男性”值的性别属性。现在我想在显示页面上将该值显示为“Man”,但是=@user.sex输出为'male'而不是'Man' 最佳答案 我可能会使用.text方法(您可以通过使用
给定这个类:classUser我想创建一个如下所示的fixture:testuser1:id:1username:sampermission::permission_staff我尝试了多种语法变体,但没有找到有效的方法。结果user.permission为nil或0。我知道enum是最近添加的。这可以做到吗? 最佳答案 根据enumdocs你可以像这样通过类引用可枚举的:User.permissions[:permission_staff]工厂只是ruby代码——所以他们应该能够以相同的方式访问值testuser1:id:1us
我有以下数组:arr=[1,3,2,5,2,4,2,2,4,4,2,2,4,2,1,5]我想要一个包含前三个奇数元素的数组。我知道我可以做到:arr.select(&:odd?).take(3)但我想避免遍历整个数组,而是在找到第三个匹配项后返回。我想出了以下解决方案,我相信它可以满足我的要求:my_arr.each_with_object([])do|el,memo|memo但是有没有更简单/惯用的方法来做到这一点? 最佳答案 使用lazyenumerator与Enumerable#lazy:arr.lazy.select(&:o
我有一个表,'jobs'和一个枚举字段'status'。status具有以下枚举集:enumstatus:[:draft,:active,:archived]使用ransack,我如何过滤表,比如说,所有事件记录? 最佳答案 你可以像这样在模型中声明自己的掠夺者:ransacker:status,formatter:proc{|v|statuses[v]}do|parent|parent.table[:status]end然后您可以使用默认的搜索语法_eq来检查相等性,如下所示:Model.ransack(status_eq:'ac
ruby中有没有一个很好的方法来删除可枚举列表中的重复项(即拒绝等) 最佳答案 对于数组你可以使用uniq()方法a=["a","a","b","b","c"]a.uniq#=>["a","b","c"]所以如果你只是(1..10).to_a.uniq或%w{antbatcatant}.to_a.uniq因为无论如何,几乎所有您实现的方法都将作为Array类返回。 关于Ruby删除可枚举列表中的重复项,我们在StackOverflow上找到一个类似的问题: h
一、什么是MQTT协议MessageQueuingTelemetryTransport:消息队列遥测传输协议。是一种基于客户端-服务端的发布/订阅模式。与HTTP一样,基于TCP/IP协议之上的通讯协议,提供有序、无损、双向连接,由IBM(蓝色巨人)发布。原理:(1)MQTT协议身份和消息格式有三种身份:发布者(Publish)、代理(Broker)(服务器)、订阅者(Subscribe)。其中,消息的发布者和订阅者都是客户端,消息代理是服务器,消息发布者可以同时是订阅者。MQTT传输的消息分为:主题(Topic)和负载(payload)两部分Topic,可以理解为消息的类型,订阅者订阅(Su
TCL脚本语言简介•TCL(ToolCommandLanguage)是一种解释执行的脚本语言(ScriptingLanguage),它提供了通用的编程能力:支持变量、过程和控制结构;同时TCL还拥有一个功能强大的固有的核心命令集。TCL经常被用于快速原型开发,脚本编程,GUI和测试等方面。•实际上包含了两个部分:一个语言和一个库。首先,Tcl是一种简单的脚本语言,主要使用于发布命令给一些互交程序如文本编辑器、调试器和shell。由于TCL的解释器是用C\C++语言的过程库实现的,因此在某种意义上我们又可以把TCL看作C库,这个库中有丰富的用于扩展TCL命令的C\C++过程和函数,所以,Tcl是
我想从不同线程调用一个公共(public)枚举器。当我执行以下操作时,enum=(0..1000).to_enumt1=Thread.newdopenum.nextsleep(1)endt2=Thread.newdopenum.nextsleep(1)endt1.joint2.join它引发了一个错误:Fibercalledacrossthreads.当enum在从t1调用一次后从t2调用时。为什么Ruby设计为不允许跨线程调用枚举器(或纤程),以及是否有其他方法可以提供类似的功能?我猜测枚举器/纤程上的操作的原子性在这里是相关的,但我不完全确定。如果这是问题所在,那么在使用时独占锁定