#はじめに
某プログラミング学習サイトの学習記録を記します。
#共通操作
・範囲選択:Shiftを押しながらクリック
・複数行コメントアウト:Command /
#01
・Xcodeでplaygraoundを新規作成する
・種類はBlankを選ぶ (他にはGame, Map, Single Viewがある)
#02
・下記について、C言語と同じ
・コメント
・print関数
・文字列を""で囲むこと
・文末が;であること
・実行形式の選択は、□または△を長押しすることで変更できる
短く押すと実行される。
・右ペインに実行結果が表示される
#03:変数と定数
・変数:var
・定数:let
・例
let msg:String; // 文字列型の定数msgを宣言
msg = "hello"; // msgに"hello"を代入
let msg = "hello"; // 型推論が行われmsgは文字列型となる
※:C言語と違い、
#04:データ型
・下記はC言語と同じ
・Int:整数型
・Float, Double
・キャスト(型変換)
・Bool型:true / false
#05:演算
・下記はC言語と同じ
・四則演算
・単項演算子(+=, = /= -=)
・論理演算(&&, ||, !)
・文字列
・+で連結 "hello " + "world" → "hello world"
・()で数値を文字に変換できる。()の中で演算できる。
(例) 変数yが15の時
"y is (y)" → "y is 15"
"2y is (2y)" → "2y is 30"
#06:分岐
・下記はC言語と同じ
・分岐(if, else, if else)
・比較(>, >=, <=, ==, !=)
・条件演算子(条件文 ? 真 : 偽)
#07:switch
・switchの構文はC言語と同じ
・default, breakもC言語と同じ
・caseの作り方
・単一: (例) case 0:
・複数: (例) case 1, 2, 3:
・範囲: (例) case 4...6:
・範囲: (例) case 7..<9: 9を含まない
・比較: (例) case let n where n > 20; 20超の場合
#08:while
・whileの構文はCと同じ
・C言語のdo whileと同じ機能が repeat whileで実現される
repeat {
実行文;
} while (条件)
#09:for
・構文 for 変数 in データ範囲 {処理}
・例 for i in 0...5 {print(i); }
・break, continueはC言語と同じ。
#10:オプショナル型
・nil:空白の値
・nilを代入可能とするには、Optinal型とする必要がある
(例) let s:String = nil; // ×
(例) let s:Optinal = nil; // ○
(例) let s:String? = nil; // ○
・nilの判定
(例)if (s != nil) {
print(s!); // unwrap
}
・unwrap:変数の後ろに!を付けてOptinal型から値を取り出すこと
・Optinal Binding:unwrapを行う別の方法
(例) if let value = s { 処理}
sがnilでない場合だけunwrapしてvalueに代入する
・さらに別の方法
(例) print(s ?? "this is nnil");
sがnilでなければsを、nilであれば文字列を表示する
#11:配列
・データの型を[]で囲う
(例) var scores:[Int] = [50, 40]; // 型を指定
(例) var scores2 = [50, 40]; // 型推論して省略
・配列の要素を制御する
(例) score[0] = 30;
・配列の要素数を数える:count関数
(例) score.count
・配列が空かどうかを調べる:isEmpty関数
(例) score.isEmpty
・空の配列を作成する
(例) var names = String;
・末尾への要素追加
(例) names.append = "abc";
(例) names += ["def"];
#12:タプル(異なる型のデータを扱える)
・(例) var items = ("apple", 5):
・(例) 読出:print(items.0);
・(例) 書込;items.1 = 3;
・変数名を宣言する
(例) var items = ("apple", 5);
let (product, amount) = items;
・一部だけを変数宣言する
(例) var items = ("apple", 5);
let (product, _) = items;
・初期化時に名前を付ける
(例) var items = (product:"apple", amount:5);
print(items.product);
#13:集合
・集合は、順序を持たず、値の重複を許さない
・宣言方法
(例) var winners:Set = [3, 5, 8, 8];
(例) var winners:Set = [3, 5, 8, 8]; // 型推論
print(winners); // [3, 5, 8]
・データを含むか判定する
(例) winners.contais(3); // 3を含むならtrueを返す
・データを追加
(例) winners.insert(10); // 10を追加
・データを削除
(例) winners.remove(5); // 5を削除
・データ数を数える
(例) winners.count; // データ数を返す
・空集合の作成
(例) let s = Set();
print(s.isEmpty); // trueを返す
・演算
(例) let a:Set = [1, 3, 5, 8]
let b:Set = [3, 5, 8, 9]
print(a.union(b)); // 和集合:[5,8,3,1,9]を返す
print(a.intersection(b)) // 直積 :[5,3,8]を返す
print(a.subtracting(b)); // 差 :[1]を返す
#14:辞書(キーと値で管理するデータ)
・(例)キーが文字列、値が整数の場合
var sales:Dictionary = ["MrA":300, "MrB":400]
var sales = ["MrA":300, "MrB":400]; // 型推論
・値の代入
(例) sales["MrB"] = 500;
・値の取出し
(例) print("sales["MrB"] ?? "n.a.") // MrBが存在しなければ"n.a."
// キーに対する値が存在しない場合はOptional型のnilが返ってくる
・データの追加
(例) sales["MrC"] = 100; // MrCを追加(代入と同じ)
・データ数を数える
(例) print(sales.count)
・一覧を出力
(例) for (key, value) in sales {
print("(key):(value)")
}
・空の辞書を作成する
(例) let d = String:Int; // キー:String, 値:Intの空の辞書
print(d.isEmpty); // trueを返す
#15:関数
・引数と戻り値がなければC言語と同じ
・戻り値がある場合
(例)
func sayHi() -> String { // 文字列を返す関数の宣言
return "hi" // 戻り値
}
print(sayHi()); // 戻り値を印字
#16:引数
・関数名の後に(変数名:型)の形式で指定する
(例) func sayHi(name: String) {
print("hi (name)")
}
sayHi(name: "A") // 結果:"hi A"
・変数名にラベルを付けることで、宣言時と違う変数名で実行する
(例) func sayHi(from name: String) { // 変数nameにfromというラベルを付ける
print("hi (name)")
}
sayHi(from: "B") // 結果:"hi B"
・変数名のラベルを省略する
(例) func sayHi(_ name: String) {
print("hi (name)")
}
sayHi("C") // 結果:"hi C"
・変数の初期値を決める
(例) func sayHi(_ name: String = "D") {
print("hi (name)")
}
sayHi() // 結果:"hi D", 引数は初期値を使用する
#17:inoutキーワード
・引数を渡す際、アドレスを渡す場合にinoutキーワードが必要になる
(例)
func add10(x:inout Int) { // アドレス渡し
x = x + 10; // inoutキーワードがなければエラーとなる
print(x)
}
var i = 10;
add10(x : &i); // アドレス渡し
print(i); // 20
#18:class
・宣言
(例) class User { // classの宣言
let name:String 1/ propertyの定義
var score:Int
init() { // propertyの初期化
self.name = "me" // selfを使って代入
self.score = 20
}
}
・インスタンス化して利用
(例)
let user:User = User(); // クラスUserのインスタンスuserを定義して初期値代入
print(user.name); // インスタンスuserのnameを印字
#19:イニシャライザ
・インスタンス毎に違う値を持たせる
(例) class User {
let name:String;
var score:Int
init (name:String, score:Int) { // 引数:String型のnameとInt型のScore
self.name = name; // 引数nameをclassのnameに代入
self.score = score;
}
}
let tom = User(name:"tom", score:20);
print(tom.name); // 結果:tom
print(tom.score); // 結果:20
・変数名を省略
イニシャライザ:init(_ name :String, _ score:Int)
インスタンス化:let tom = User("tom", 23);
・引数が渡されなかったときのイニシャライザを作成
(例) class User {
let name:String;
var score:Int
init (name:String, score:Int) {
self.name = name; // 引数nameをclassのnameに代入
self.score = score;
}
init () { // 引数を指定しない場合のイニシャライザ
self.name = "no name"; // 引数nameをclassのnameに代入
self.score = 0;
}
}
let noname = User(); // 引数を指定しない
print(noname.name); // "no name"
print(noname.score
#20:計算プロパティ(動的に計算可能なプロパティ)
・クラス内の変数にはget関数とset関数を追加できる
(例)
class User {
let name:String;
var score:Int
var level:Int {
get {
return Int(self.score/10) // levelの取得時、scoreの1/10を返す
// return Int(score/10) // 自明な場合は、selfを省略可能
}
set {
if newValue >= 0 { // 値をnewValueで受け取る
score = newValue * 5; // 5倍してscoreに入力する
}
}
}
// 戻り値だけの場合(getだけ)の場合の記述方法
//var Int {
// return Int(score/10);
//}
let u = User("MrA", 2);
u.level = 5;
print(u.score) // 結果:50
#21:プロパティの値の変化前後
・willSet関数で変化前、didSet関数で変化後を監視できる
・(例)
class User {
var score:Int {
willSet { // 変化前
print("(score) -> (newValue)")
}
didSet { // 変化後
print("Changed: (score - oldValue)")
}
}
let tom = User("tom", 2)
tom.score = 53 // "2 -> 53, Changed:51
tom.score = 20 // "53 -> 20, changed:-33
#22:メソッド
・func 関数名(引数)
・例
class User {
let name:String
var score:Int
init(_ name : String, _ score:Int) {
self.name = name;
self.score = score;
}
func sayHi(_ msg:String) { // データ型の省略fs
print("(msg) (name)")
}
}
let tom = User("tom", 2)
tom.sayHi("hola"); // 結果:"hola tom"
#23:クラスの継承
// 親クラス(スーパークラス)
Class User {
let name:String;
var score :Int;
init(_ name:String, _ score:Int) {
self.name = name;
self.score = score;
}
func sayHi() { // overrideを禁止したい場合は、「final func 関数名」とする
print("hi (name)")
}
}
// 子クラス(サブクラス)
class AdminUser:User { // class 子クラス名:親クラス名
func sayHello() {
print("hello (name)")
}
override func sayHi() { // override:親クラスのメソッドを上書き
print("admin hi (name)")
}
}
let tom = User("tom", 23);
let bob = AdminUser("bob", 30);
print(bob.name); // 結果:bob
print(bob.score); // 結果:30
bob.sayHi(); // 結果:admin hi bob
bob.sayHello(); // 結果:hello bob
#24:型プロパティ、型メソッド
・インスタンスではなく、クラスに直接関連するプロパティやメソッドはstaticを先頭に付ける
・(例)
Class User {
let name:String;
var score:Int;
static var count = 0; // クラスから直接扱う
init(_ name:Stirng, _ score:Int) {
self.name = name;
self.score = score;
User.count += 1; // イニシャライザはインスタンスから呼ばれるので、型プロパティへのアクセスにはクラス名を付ける
}
class func getInfo() {
// static funcにするとoverrideを禁止できる
print("(count) instances);
}
class AdminUser:User {
override class func getInfo() {
print("admin (count) instances")
}
}
User.getInfo(); // 結果:0
let a = User("a", 1);
User.getInfo(); // 結果:1
AdminUser.getInfo(); // 結果:1
let b = AdminUser("b", 2);
AdminUser.getInfo(); // 結果:2
#25:型キャスト
・(例)
class User {
let name : String;
init(_ name : String) {
self.name = name;
}
}
class AdminUser : User{}
let tom = User("tom")
let bob = AdminUser("bob")
// 配列として扱う
let users:[User] = [tom, bob];
// 「:[User]」は記述しなくても型推論してくれる
// 親子クラスのため同じ種類として扱ってくれる
for user in users {
// AdminUserの場合だけ表示する(1)
if let u = user as? AdminUser // 「as?」で一語(スペース挿入禁止)
// as?で変換可能か調べる。失敗ならnilが返ってくる
// optional bindingを使う
// 成功時はAdminUser型のuserがuに代入される
print(u.name); // 結果:bob
}
// AdminUserの場合だけ表示する(2)
if user is AdminUser { // userがAdminUser型であるか確かめる
let u = user as! AdminUser // as!でunwarpしてくれる
// AdminUser型のuserが返ってくる
print(u.name); // 結果:bob
}
}
// unwrap:optional型からデータを取り出すこと
// optional型:nilを格納できる型
// optional Binding:値がnilで内場合だけ値を取り出す
#26:プロトコル
・クラスに対して、実装が必須なプロパティやメソッドを定義する
・(例)
protocol Printable { // プロトコル定義
var type:String { get } // 読み取り専用
var count:Int {get set} // 読み書き可能
func printout() // 実装はクラスで行うので定義は不要
// イニシャライザは不要
}
class User:Printable {
let type = "Laser"
let count = 0;
let name:String;
init(_ name:String) {
self.name = name
}
func printout() {
count += 1;
print("(type) : (count)")
}
}
let a = User("a")
a.printout(); // 結果「Laser:1」
a.printout(); // 結果「Laser:2」
a.printout(); // 結果「Laser:3」
a.printout(); // 結果「Laser:4」
#27:エクステンションによる拡張
・既存の型に新しいプロパティやメソッドを追加する
・(例)
// String型を拡張し、文字列長を返す変数を追加する
extension String { // String型を拡張
var length :Int { // lengthという変数を追加
return self.characters.count // プロパティの一つであるcountを返す
}
}
let msg = "hello"
print(msg.characters.count) // String型の元々の文字列長の取得
print(msg.length); // 新規に追加したlength変数による文字列長の取得
(例)
protocol Printable { // Printableのプロトコル(実装必須関数の定義)
func printout()
}
extension Printable { // 既存のPrintableに
func printout() { // 関数printoutを追加
print("printing)
}
}
// PrintableをUserクラスに適合させる
class User:Printable { // Printableのインスタンス
let name:String
init(_ name:String) {
self.name = name;
}
} // インスタンス内にprintout関数の実装が不要
let tom = User("tom")
tom.printout()
#28:参照型と値型
・Int, doubleなどは値型
・Classは参照型
(例)
class User {
var name:String;
init(_ name:String) {
self.name = name;
}
}
var org = User("A)
var copy = org;
org.name = "B"
print(org.name) // 結果:B
print(copy.name) // 結果:B
#29:構造体
・classと、ほぼ同じ機能を持つ。
・classが参照型であるのに対して構造体は値型である。
・classと違って継承が出来ない
・extension, protocolは使える
・メソッドでプロパティを変更するには、funcの前にmutatingを付ける
#30::列挙型
・enum (型名) {
case 値1
case 値2
}
・例
enum Direction :Int {
case right = 1
case left = -1
}
print(Direction.rihgt.rawValue); // 値を取り出す
var dir:Direction
dir = .right // Direction.rightの省略形
switch (dir) {
case .right: print("right");
case .left: print("left");
}
#31:ジェネリクス型
・データ型を汎用化させる
関数名の後にを追加し、データ型をTとする。
・func getData(x:Int) { // 通常の書き方
・func getData(x:T) { // ジェネリクス型を使用
print(x)
}
getData(x:"Hello") // 結果:"Hello"
getData(x:2.3) // 結果:"2.3"
#32:サブスクリプト
・サブスクリプト:インスタンスに対して、配列と同じようにインデックスを付ける
class Teams {
var memvers = ["A", "B", "C"]; // サブスクリプトのアクセス対象のデータを用意
subscript (index : Int) -> String { // indexに使う値の型と返値の型を指定
get { // サブスクリプトで取得する時の処理
return members[index]
}
set { // サブスクリプトで設定する時の処理
members.insert(newValue, at:index) // 設定値をnewValueで取得できる
}
}
}
var t = Team()
print(t[1]) // 結果:"B"
t[3] = "D"
print(t[3]) // 結果:"D"
#33:guard
・異常処理を分かりやすく書くための仕組み
・guardを使わない書き方
func test(_ msg:String?) { // StringのOptional型
if let s = msg { // nil判定
print(s)
} else {
print("nil")
}
}
・early return , early exitを使用する
func test(_ msg:String?) {
if msg == nil {
print("nil")
return
}
print(msg!) // unwrapする
}
・guardを使う
func test(_ msg:String?) {
// msgがnilでなければsに代入、sならelse以下を処理する
guard let s = msg else {
print("nil")
return // guardの中では、returnを忘れるとエラーを出してくれる
}
print(s)
}
#34:例外処理
// 例外の種類を列挙型で定義
enum LoginError:Error { // プロトコルを使用する
case emptyName
case shortName
}
class User {
let name:String
init(_ name:String) {
self.name = name
}
// 例外が発生する可能性がある場合は関数名の後にthrowsを付ける
func login() throws {
// nameが空でないときは無処理。空の時の処理を定義する
guard name != "" else {
throw LoginError.emptyName // 例外を投げる
}
guard name.count > 5 else {
throw LoginError.shortName
}
print("success")
}
}
let a = User("AAAAA") // 結果:short
let a = User("AAAAAA") // 結果:Success
let a = User(") // 結果:enter
// 例外が発生するときの書法
do {
try a.login()
} catch LoginError.emptyName {
print("enter")
} catch LoginError.shortName {
print("short")
}
#35:Optional Chaining
・Optinal型が連続する場合に安全にnilチェックする
class User {
var name:String? = "" // nameがoptional型の場合
}
let user:User? // Userがoptional型の場合(Optional型を短く宣言する)
user = User()
user?.name = "a" // ※1
if let s = user?.name?.uppercased() { // ※1 ※2
print(s)
}
// ※1:Optional Chaining:optional変数の後に?を付ける。
// nilの場合はnilを、nilでなければその値を含むOptional型を返す
// ※2:Optional Binding
#36:暗黙的アンラップオプショナル (Implicity Unwarpped Optional)
・通常のOptinal型
var msg:String? // Optional型(nilを取ることができる)
msg = "a"
if msg != nil { // nilチェック
print(msg!) // Optional型をUnwap
}
・暗黙的アンラップオプショナル(UnWrap不要)
var msg:String! // 末尾を「?」ではなく「!」にする
msg = "a"
print(msg) // Unwrap不要(末尾の「!」不要)
#以上