Skip to content

Instantly share code, notes, and snippets.

@ezura
Last active December 11, 2018 19:39
Show Gist options
  • Save ezura/f74f4bf4b57712aa0656fee59623630a to your computer and use it in GitHub Desktop.
Save ezura/f74f4bf4b57712aa0656fee59623630a to your computer and use it in GitHub Desktop.
Swift4 全予約語 (98語) の解説 ref: https://qiita.com/ezura/items/d011c9b13c70055b6e57
precedencegroup GroupA {
associativity: none
}
precedencegroup GroupB {
higherThan: GroupA
associativity: none
}
infix operator ***: GroupA
infix operator +++: GroupB
func *** (left: Int, right: Int) -> Int {
return left * right
}
func +++ (left: Int, right: Int) -> Int {
return left + right
}
1 +++ 1 *** 0 // => 0
switch (a) {
case 1:
printf("1\n");
case 2:
printf("2\n");
break;
default:
printf("default\n");
}
class Sample {
var member = 1
}
let a = Sample()
let b = a
a === b // -> true (指すものは同じ)
a.member = 2
b.member // -> 2
protocol SampleProtocol : class {
}
class Sample : SampleProtocol {
}
protocol SampleProtocol {
static func staticFuncInProtocol()
static var staticVarInProtocol: Int { get }
}
class Sample {
// `static func staticFuncInProtocol()` can be implemented by `static func` or `class func`
class func staticFuncInProtocol() {}
// ditto
class var staticVarInProtocol: Int { return 1 }
}
protocol SampleProtocol {
associatedtype AssociatedType // 付属型を宣言します
func sampleFunc(param :AssociatedType) -> AssociatedType
}
struct SampleStruct: SampleProtocol {
func sampleFunc(param: Int) -> Int { // 付属型が Int であると決定されます
return param + param
}
}
var i = 0
firstLoop: while true {
print("first loop: \(i)")
while true {
i += 1
print("second loop: \(i)")
switch i {
case 5:
print("break firstLoop")
break firstLoop
default:
break
}
}
}
print("finish: \(i)")
first loop: 0
second loop: 1
second loop: 2
second loop: 3
second loop: 4
second loop: 5
break firstLoop
finish: 5
let optionalSample: Int? = 1;
let optionalArraySample: [Int?] = [1, 2, nil, 3]
if case let x? = optionalSample {
print("optionalSample: \(x)")
}
for case let x? in optionalArraySample {
print("optionalArraySample: \(x)")
}
optionalSample: 1
optionalArraySample: 1
optionalArraySample: 2
optionalArraySample: 3
class SuperClass {
deinit { print("Super Class's deinit is called") }
}
class SubClass: SuperClass {
deinit { print("Sub Class's deinit is called") }
}
var subClass: SubClass? = SubClass()
subClass = nil
var i = 0
firstLoop: while true {
print("first loop: \(i)")
if i != 0 { break }
while true {
i += 1
print("second loop: \(i)")
switch i {
case 5:
print("continue firstLoop")
continue firstLoop
default:
break
}
}
}
print("finish: \(i)")
first loop: 0
second loop: 1
second loop: 2
second loop: 3
second loop: 4
second loop: 5
continue firstLoop
first loop: 5
finish: 5
func deferSample() {
defer {
print("in defer")
}
print("end of scope")
}
deferSample()
end of scope
in defer
switch 1 {
case 1:
defer { print("defer") } // ブロック(スコープ) から抜ける様子を観察
print("1-1")
if true {
fallthrough
}
print("1-2")
case 2:
print("2")
default:
print("default")
}
func guardSample1(value: Int?) -> String {
guard let value = value, value > 10 else {
// この中では必ずスコープを抜ける処理を書きます
return "in else block"
}
// ここからは value がアンラップされ、また、10 より大きいことが保証されます
return "\(value)"
}
guardSample1(nil) // => in else block
guardSample1(10) // => in else block
guardSample1(100) // => 100
func guardSample2(a: String, b: Int?) -> String {
// 複数の変数・定数の評価もできます
guard let intValue = Int(a), let b = b else {
return "in else block"
}
// ここからは b がアンラップされます
return "\(intValue + b)"
}
guardSample2("a", b: 1) // => in else block
guardSample2("1", b: 1) // => 2
guardSample2("1", b: nil) // => in else block
func ifLetSample(value: Int?) {
if let a = value {
type(of: value) // Optional<Int>.Type
type(of: a) // Int.Type
}
}
do {...} while(...)
func sample() {
return
}
var a = sample() // -> ()
switch (1, "a") {
case (1, "b"):
print("1, b")
case (1, _):
print("1, _") // ここがマッチします。 (_ はワイルドカード)
case (1, "a"):
print("1, a") // 上がマッチするので評価されません
}
while condition {
statements
}
repeat {
statements
} while condition
class A {}
let anyObj: AnyObject = A()
let a = anyObj as! A // AnyObject から A にキャスト
let v = 1 as Double
class SampleClass {}
func inoutSampleForClass(sampleClass: inout SampleClass?) {
sampleClass = nil
}
func withoutInoutSampleForClass(var sampleClass: SampleClass?) {
sampleClass = nil
}
var sampleClass: SampleClass? = SampleClass()
// inout なし
withoutInoutSampleForClass(sampleClass)
sampleClass // => SampleClass のインスタンス
// inout あり
inoutSampleForClass(&sampleClass)
sampleClass // => nil
1 is Int // -> true
(1, 1) is AnyObject // -> false
(1, 1) is (Int, Int) // -> true
// プロトコルの検査
protocol SampleProtocol { }
class SampleClass: SampleProtocol { }
let sampleClassInstance = SampleClass()
sampleClassInstance is SampleClass // true
sampleClassInstance is SampleProtocol // true
Optional.None == nil // -> true
func sample(callback: () throws -> Int) rethrows {
try callback()
}
class Sample {
var a: Int?
func sampleMethod() -> Sample {
a = 1
return self // 自身 (playground 上では Sample と見えますが、プロパティ a が変更されているので上で作成したインスタンスだと確認できます)
}
}
class Sample {
}
Sample.self // -> Sample.Type
Sample.self.init() // -> Sample のインスタンス (= Sample.self は自身の型を返しています)
if #available(iOS 10.0, *) {
print("iOS10 or later")
}
#colorLiteral­(­red­:­ <# expression #>­, ­green­:­ <# expression #>­,­ blue­:­ <# expression #>­,­ alpha­: <# expression #>­)­
func inoutSample(a: inout Int) {
a = 100
}
func withoutInoutSample(var a: Int) {
a = 100
}
var varInt = 1
// inout なし
withoutInoutSample(varInt)
varInt // => 1
// inout あり
inoutSample(&varInt)
varInt // => 100
#fileLiteral(resourceName: "<# ファイル名 #>")
#imageLiteral(resourceName: "<# ファイル名 #>")
class Object: NSObject {
let value = 1
var matryoshka: Object?
}
#keyPath(Object.value) // "value"
#keyPath(Object.matryoshka.value) // "matryoshka.value"
let object = Object()
object.matryoshka = Object()
object.value(forKey: #keyPath(Object.value)) // 1
object.value(forKeyPath: #keyPath(Object.matryoshka.value)) // 1
@interface ViewController : UIViewController
@property(assign) int num;
@end
#selector(getter: ViewController.num)
#selector(setter: ViewController.num)
prefix operator ☁
prefix func ☁ (a: inout Int) -> Int {
a *= a
return a
}
postfix operator *** // 複数文字列も可能
postfix func *** (a: inout Int) -> Int {
a *= a
return a
}
infix operator ☁
func ☁ (left: Int, right: Int) -> Int {
return left + right
}
var hoge = 2
☁hoge // => 4
hoge*** // => 16
1 ☁ 2 // => 3
class A {
var value: Int {
get { return 1 }
}
}
protocol Sample {
var value: Int { get }
}
class A: Sample {
let value = 1
}
class B: Sample {
var value: Int { return 1 }
}
infix operator ☁
func ☁ (left: Int, right: Int) -> Int {
return left + right
}
1 ☁ 2 // => 3
indirect enum SampleEnum {
case Num(Int)
case IndirectNum(SampleEnum)
}
SampleEnum.IndirectNum(SampleEnum.IndirectNum(SampleEnum.IndirectNum(SampleEnum.Num(1))))
enum SampleEnum {
case Num(Int)
indirect case IndirectNum(SampleEnum)
}
var value: Value { get nonmutating set }
postfix operator ***
postfix func *** (a: inout Int) -> Int {
a *= a
return a
}
var hoge = 4
hoge*** // => 16
prefix operator ***
prefix func *** (a: inout Int) -> Int {
a *= a
return a
}
var hoge = 4
***hoge // => 16
let protocolMetatype: SampleProtocol.Protocol = SampleProtocol.self
class A {
var value: Int {
get { return 1 }
set {}
}
}
protocol Sample {
var value: Int { get set }
}
class A: Sample {
var value = 1
}
class B: Sample {
var value: Int {
get { return 1 }
set {}
}
}
class Sample {
required init() {}
}
let metatype: Sample.Type = Sample.self
let instance = metatype.init()
// unowned = unowned(safe)
unowned var safe: AnyObject
// capture list 内で指定することが多いです
{ [unowned a] in /* ... */ }
// unowned = unowned(safe)
unowned(safe) var safe: AnyObject
// capture list 内で指定することが多いです
{ [unowned(safe) a] in /* ... */ }
// like `__unsafe_unretained`
unowned(unsafe) var unsafe: AnyObject
{ [unowned(unsafe) a] in /* ... */ }
switch (1, "a") {
case (1, "b"):
print("1, b")
case (1, _):
print("1, _") // ここがマッチします。 (_ はワイルドカード)
}
let a: Int
(a, _) = (0, 1)
a // -> 0
class A {
private var privateVar = ""
}
extension A {
func f() {
// ✅OK
print(privateVar)
}
}
class B {
let a = A()
func f() {
// ❗️error: 'privateVar' is inaccessible due to 'private' protection level
a.privateVar
}
}
for i in 1...10 {
// 処理
}
for _ in 1...10 {
// 処理
}
#if swift(>=3.0)
print(">=Swift3.0")
#elseif swift(>=2.0)
print(">=Swift2.0")
#else
print("else")
#endif
precedencegroup OperationFoldedIntoOptionalChaining {
assignment: true
}
precedencegroup OperationOutsideOfOptionalChaining {
assignment: false
}
infix operator ~~ : OperationFoldedIntoOptionalChaining
infix operator ~^ : OperationOutsideOfOptionalChaining
func ~~ (left: Int, right: Int) -> Int {
print("~~")
return left + right
}
func ~^ (left: Int?, right: Int) -> Int {
print("~^")
return left?.advanced(by: right) ?? -1
}
let values = nil as [Int]?
values?.count ~~ 5 // => nil
values?.count ~^ 5 // => -1
/*
~~ 演算は、
最初に `values` の nil 判定、nil でなければ `.count ~~ 5` を評価
values.map { $0.count ~~ 5 } と同等。この例では `~~` 演算は実行されない。
~^ 演算は、最初に `values?.count` を評価、続いて `その結果 ~^ 5` を評価
普通に `(values?.count) ~^ 5` としたのと同等。演算子の既定の動作。
*/
protocol P {
associatedtype T
}
struct S: P {
typealias T = Any
}
(1 + 1).self // 2 as Int ではない
// 証明
(1 + 1).self + 1.0 // OK
(1 + 1) + 1.0 // OK
let exp = 1 + 1 // 2 as Int
exp + 1.0 // Error (type mismatch)
let a = 1
switch a {
case 1:
print("1")
fallthrough
case 2:
print("2")
default:
print("default")
}
precedencegroup <#precedence group name#> {
higherThan: <#lower group name#>
associativity: <#left | right | none#>
}
Sub Class's deinit is called
Super Class's deinit is called
enum SampleEnum {
case A, B, C
case a, b, c
mutating func upperCase() {
switch self {
case .a: self = .A
case .b: self = .B
case .c: self = .C
default: break
}
}
}
precedencegroup MyAddition {
associativity: none
}
infix operator +++ : MyAddition
infix operator --- : MyAddition
func +++ (left: Int, right: Int) -> Int {
return left + right
}
func --- (left: Int, right: Int) -> Int {
return left - right
}
1 +++ 1 --- 1
/*
error: adjacent operators are in non-associative precedence group 'MyAddition'
1 +++ 1 --- 1
^ ~~~
*/
typealias IntAlias = Int
typealias Point = (Int, Int)
class SubscriptSample {
var hoge: Any?
subscript(index: Int) -> String {
get {
return "Int もらいました"
}
set {
hoge = newValue
}
}
subscript(index: String) -> String {
get {
return "String もらいました"
}
// setter なくても良いです
}
subscript(index: AnyObject?) -> String {
return "何かもらいました"
}
subscript(x: Int, y: Int) -> String {
return "\(x), \(y)"
}
subscript() -> String {
return "nothing"
}
}
class Sample {
var a: Int
init(_ param: Int) {
a = param
}
}
let sample = Sample(1)
class Sample {
var a: Int
init(param: Int) {
a = param
}
}
let sample = Sample(param: 1)
#if <# Custom Flag に設定した名前 (設定せずにコンパイルすると無視される) #>
print("DEBUG")
#endif
#if swift(>=3.0)
print("Swift3.0")
#endif
#if arch(arm64)
print("arm64")
#endif
#if os(OSX)
print("OSX")
#endif
dynamic <#var | let #> <# name #>
struct SampleStruct {
var x = 0
mutating func modifyX(x: Int) {
self.x = x
}
mutating func reset() {
self = SampleStruct()
}
}
infix operator <#operator name#> : <#precedence group name#>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment