作者: shanks
本周整理问题如下:
对应的代码都放到了 github 上,有兴趣的同学可以下载下来研究: 点击下载
Q1链接地址
楼主直接就问:如何在 swift 中使用 [a-zA-Z]+@[a-zA-Z]+.[a-zA-Z]
这样的正则表达式?
目前在 Swift 中使用正则表达式,还是直接调用 oc 里面的 NSRegularExpression 来完成的。
喵神有一个 tips 专门介绍了这个知识点:
http://swifter.tips/regex/下面是跟帖的代码,解决了问题:
let test = "someone@somewhere.com"
do {
let regex = try NSRegularExpression(pattern: "[a-zA-z]+@[a-zA-Z]+.[a-zA-Z]", options: [])
if regex.firstMatchInString(test, options: [], range: NSMakeRange(0, test.characters.count)) != nil {
print("matched")
} else {
print("not matched")
}
} catch let error as NSError {
print(error.localizedDescription)
}
Q2链接地址
Swift 类中定义的方法,传入参数默认是值拷贝,也就是说,即使方法内部改变参数值,传入的参数原始值是不会改变的。
楼主纠结如何实现引用拷贝,也就是,赋值给类中的属性以后,改变了属性的值,传入的参数也会跟着改变,见代码如下:
import Foundation
class Foo {
var foo : Array<Int>
init(foo: Array<Int>) {
self.foo = foo
}
func modify() {
foo.append(5)
}
}
var a = [1,2,3,4]
let bar = Foo(foo: a)
bar.modify()
print(a) // My goal is that it will print 1,2,3,4,5
实际上,使用inout,也不能解决问题,inout 只是应用在方法内部直接改变传入值的时候有用,而上例中,是先赋值给了类的一个属性,改变了属性的值,而没有改变传入参数值。因为 Array
class Foo1 {
var foo : Array<Int>
init(foo: Array<Int>) {
self.foo = foo
}
func modify() {
foo.append(5)
}
}
let bar1 = Foo1(foo: a)
bar.modify()
print(a) // 还是没有改变 a
以下代码是跟帖中提供的解决方案,使用 UnsafeMutablePointer
class Foo2 {
var foo : [Int]
var pInner: UnsafeMutablePointer<Int>
init(foo: [Int]) {
pInner = UnsafeMutablePointer(foo)
self.foo = Array(UnsafeBufferPointer(start: pInner, count: foo.count))
}
func modify(inout pOuter: UnsafeMutablePointer<Int>) {
foo.append(5) // <-- foo gets new memory adress
pInner = UnsafeMutablePointer(foo)
pOuter = pInner
}
}
var pOuter: UnsafeMutablePointer<Int> = UnsafeMutablePointer(a)
var bar2 = Foo2(foo: a) // 'bar.foo' now at same address as 'a'
print(bar2.foo) // [1,2,3,4]
bar2.modify(&pOuter) // -> [1,2,3,4,5]
a = Array(UnsafeBufferPointer(start: pOuter, count: bar.foo.count))
/* Same pointer adress, OK! */
print(bar2.pInner)
print(pOuter)
/* Naturally same value (same address in memory) */
print(bar.foo)
print(a)
此问题其实在实际编码中,应该尽量避免,一个类,去改变外部的值,违背了类的封装性。
Q3链接地址
楼主是新手,新手最多的几个问题之一就是对 Optional 的理解。楼主的问题是:[String!] and [String]! 的区别是什么?
[String!] 是一个包含隐式解包 Optional String 的数组,数组的值可以为 nil。
[String]! 是一个隐式解包 Optional 的数组,数组类型是 String,可以直接对这个数组赋值为nil,但是因为数组元素类型是 String,所以数组元素不能为nil
let list0: [String!] = ["Hello", nil, "world", nil]
let list1: [String]! = nil
let list2: [String]! = ["Hello", "world"]
Q4链接地址
楼主有一个二维数组,想通过数组中的 type 字段,进行过滤。于是他写出了如下报错的代码:
var data = [["type":"Sport", "model":"R6"],["type":"Enduro", "model":"Tenerre"],["type":"Chopper", "model":"Intruder"]]
//data.filter({ (type: String) -> Bool in
// return true
//})
数组 filter 方法的定义:
filter(includeElement: (T) -> Bool) -> T[]
在这个例子中,数组是二维的,所以 T = [String:String],也是一个数组。所以正确答案应该是:
let filteredData = data.filter { (dict:[String:String]) -> Bool in
return dict["type"] == "Sport"
}
Q5链接地址
楼主的问题是:为什么 self.self 这样的写法在其他语言会报错,而 Swift 中,不会报错:
class test {
var someProperty = ""
func test() {
print(self.self.someProperty)
}
}
实际上,无论支持还是不支持这种语法,一个 self,应该就足够了。跟帖也在质疑这种用法的实用性在那?例如如下的形式,这样写与只带一个 self,没什么区别:
let s = "Hello".self.self.self.self.self.self.self.self
let s1 = "Hello".self