【Swift】Array内の要素を指定して消去する

もくじ

  1. removeAllを使用する
    • 短くかける
  2. for文を使用する
    • ちょっと冗長
  3. その他の参考

注意

この方法の場合、比較する要素に一致するデータは全て配列から消去されます

1.removeAllを使用する

removeAll(where:)メソッドを使用し、要素を比較して一致している値全てを消去する

1
2
3
4
5
6
7
8
9
//	配列定義
var testArray :Array<String> = Array<String>()

// 要素追加
testArray.append("test")
testArray.append("kemono")

// testと一致する要素を全て消去
testArray.removeAll(where: {$0 == "test"})

2.for文を使用する

for文を使用して配列内の要素を列挙して、要素を比較した結果一致している配列内要素を全て消去する

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//	配列定義
var testArray :Array<String> = Array<String>()

// 要素追加
testArray.append("test")
testArray.append("test")
testArray.append("kemono")

// 要素を操作するのでコピーを作成して、それをfor文で列挙する
let copyArray = testArray

// 一致する要素を消去
for i in 0...copyArray.count - 1{
if(copyArray[i] == "test"){
testArray.remove(at: i)
}
}

3.その他の参考

【Xcode】EntryPointを変更する方法

もくじ

  1. 環境
  2. Entry Pointとは
  3. StoryBordから変更する
  4. コードから変更する
  5. [おまけ]初回起動時のみ特定の画面を表示させる

0. 環境

  • MacBook Air M1
  • Xcode 12.4

1. Entry Pointとは

  • プログラムの開始される位置
  • この記事では開始される画面の位置も含まれる

画面上で見ると以下の画像の矢印部分がEntry Pointを表している

EntryPointの矢印

アシスタントエディタで確認すると以下赤枠部分

EntryPointのアシスタントエリアでの表示

2. StoryBordから変更する

ドラックアンドドロップで矢印を移動させる

EntryPoint変更(マウス).gif

Utilites areaから移動させる

Attributes inspector内Is Initial View Controllerにチェクを入れる
EntryPoint変更(Inspector)

3. コードから変更する

1. Main.storybordの遷移させたいViewControllerにStoryboad IDを設定する

  • Identity Inspector 内のSotryboard IDを設定

Inspector.png

  • 今回はこのように設定
    • 1画面目 : FirstView
    • 2画面目 : SecondView

2. SceneDelegate.swift

  1. 何も変更していないデフォルトの状態だとこのようなコードになっていると思います

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    import UIKit

    class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?


    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
    // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
    // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
    guard let _ = (scene as? UIWindowScene) else { return }
    }

    func sceneDidDisconnect(_ scene: UIScene) {
    // Called as the scene is being released by the system.
    // This occurs shortly after the scene enters the background, or when its session is discarded.
    // Release any resources associated with this scene that can be re-created the next time the scene connects.
    // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
    }

    func sceneDidBecomeActive(_ scene: UIScene) {
    // Called when the scene has moved from an inactive state to an active state.
    // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
    }

    func sceneWillResignActive(_ scene: UIScene) {
    // Called when the scene will move from an active state to an inactive state.
    // This may occur due to temporary interruptions (ex. an incoming phone call).
    }

    func sceneWillEnterForeground(_ scene: UIScene) {
    // Called as the scene transitions from the background to the foreground.
    // Use this method to undo the changes made on entering the background.
    }

    func sceneDidEnterBackground(_ scene: UIScene) {
    // Called as the scene transitions from the foreground to the background.
    // Use this method to save data, release shared resources, and store enough scene-specific state information
    // to restore the scene back to its current state.
    }


    }
  2. sceneメソッド内に以下のコードのコードを追記します

    • この時、guard let _ =_の部分をwindowに変更しています。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
    // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
    // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
    guard let windowScene = (scene as? UIWindowScene) else { return }

    window = UIWindow(windowScene: windowScene)
    let storybard = UIStoryboard(name: "Main",bundle: nil)

    // 初めて起動しているか
    if(lanchIsFIrstTme()){
    window?.rootViewController = storybard.instantiateViewController(identifier: "FirstView")
    firstLanch()
    }else{
    window?.rootViewController = storybard.instantiateViewController(identifier: "SecondView")
    }

    window?.makeKeyAndVisible()
    }

4. [おまけ]初回起動時のみ特定の画面を表示させる

一つ前で実装した切り替え処理とユーザーデフォルト機能を組み合わせて、初回起動かどうかを判定する

  • 確認用メソッドと登録用メソッドを作成

    1
    2
    3
    4
    5
    6
    7
    8
    9
    private let STORED_KEY = "lanched"

    func firstLanch(){
    return UserDefaults.standard.set(true,forKey: STORED_KEY)
    }

    func lanchIsFIrstTme() -> Bool{
    return !UserDefaults.standard.bool(forKey: STORED_KEY)
    }
  • 一つ前で実装したコードを改変

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
    // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
    // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
    guard let windowScene = (scene as? UIWindowScene) else { return }

    window = UIWindow(windowScene: windowScene)
    let storybard = UIStoryboard(name: "Main",bundle: nil)

    // 初めて起動しているか
    if(lanchIsFIrstTme()){
    window?.rootViewController = storybard.instantiateViewController(identifier: "FirstView")
    firstLanch()
    }else{
    window?.rootViewController = storybard.instantiateViewController(identifier: "SecondView")
    }

    window?.makeKeyAndVisible()
    }

こんな感じになればOK

最終確認

参考

https://stackoverflow.com/questions/10428629/programmatically-set-the-initial-view-controller-using-storyboards/47691073

XcodeでVimキーバインドを使う「XVim2」

目次

  1. 証明書の発行
  2. XVim2のインストール
  3. XcodeにXVim2を読み込ませる
  4. .xvimrcでカスタマイズ 
  5. 参考

1. 証明書の発行

  1. アプリケーションのKeychain Access(キーチェーンアクセス)を起動

  2. Keychain Accessウィンドウの左側のデフォルトチェーン内のログインを選択

  3. 画面上部のメニューバーから、キーチェーンアクセス->証明書アシスタント->証明書を作成を選択

    キーチェーン証明書作成

  4. 以下と同じ情報を設定して、作成ボタンを押下

    • 名前 : XcodeSigner
    • 固有名のタイプ : 自己署名ルート
    • 証明書のタイプ : コード署名

    証明書作成時の入力内容

  5. 作成時の警告が出るが、続けるを選択

    証明書作成時の警告

  6. 以下の画像のような画面が表示されれば証明書の発行は成功

    証明書完成

2. XVim2のインストール

この作業では、任意の場所にリポジトリをクローンして作業を行ますが、今回はDesktopで作業することとして解説します。

Xcodeのパスの確認

インストール作業を行う前に、Xcodeが配置されているファイルパスの確認をします。

以下のコマンドで、/Applications/Xcode.app/Contents/Developerというパスが表示されればOKです。それ以外のパスが表示されてしまった場合は、以下コマンドで、パスを設定してください。

1
xcode-select -p

それ以外のパスが表示されてしまった場合は、以下コマンドで、パスを設定してください。

1
xcode-select -s /Applications/Xcode.app/Contents/Developer

インストール

注意 : この作業を行うときは、Xcodeを完全に落として(タスクキル)から行ってください

  1. ディレクトリを移動

    1
    cd ~/Desktop
  2. リポジトリをクローン

    1
    git clone https://github.com/XVimProject/XVim2.git 
  3. クローンしてきたリポジトリのディレクトリに移動

    1
    cd XVim2/
  4. makeコマンドでプラグインをビルド

    1
    make
  5. 出力がたくさん流れたあと、に以下のような文字が表示されれば成功

    1
    ** BUILD SUCCEEDED **

3. XcodeにXVim2を読み込ませる

  1. Xcodeを起動すると、以下の画像のようなウィンドウが表示されるので、Load Bundleを選択する
    Xcode起動時の確認画面
  2. 上部メニューバーのEditメニューの一番下にXVimが表示されて入れば導入成功

間違えて、Skip Bundleを選択してしまった場合

一度XCodeを閉じて(タスクキル)して、以下コマンドをターミナルで実行してから再度XCodeを実行するとまた確認ウィンドウが表示さる

X.X = 自分が使っているXcodeのバージョン

1
defaults delete com.apple.dt.Xcode DVTPlugInManagerNonApplePlugIns-Xcod-X.X

4. .xvimrcでカスタマイズ

ホームディレクトリ直下に.xvimrcファイルを作成して、.vimrcと同じように記述していく

1
vim ~/.xvimrc

5. 参考

【Linuxコマンド】よく使うlsコマンドオプション

目次

  1. 隠しファイル.ファイルまで表示させる
  2. ファイル詳細を表示させる
  3. 1列1ファイルで表示させる
  4. カンマ区切りで表示させる

普通にlsを使った場合

1
2
% ls
Memo_App Memo_App.xcodeproj README.md

1. 隠しファイル.ファイルまで表示させる

オプション-aをつける

1
ls -a

実行例

1
2
3
%ls -a
. .DS_Store .gitignore Memo_App.xcodeproj
.. .git Memo_App README.md

2. ファイル詳細を表示させる

lsコマンドのオプションに-lをつける

1
ls -l

実行例

1
2
3
4
5
% ls -l
total 8
drwxr-xr-x 12 daiki staff 384 2 28 01:39 Memo_App
drwxr-xr-x@ 5 daiki staff 160 2 28 02:03 Memo_App.xcodeproj
-rw-r--r-- 1 daiki staff 10 2 27 22:39 README.md

3. 1列1ファイルで表示させる

lsコマンドのオプションに-1をつける

1
ls -1

実行例

1
2
3
4
% ls -1
Memo_App
Memo_App.xcodeproj
README.md

4. カンマ区切りで表示させる

lsコマンドのオプションに-mをつける

1
ls -m

実行例

1
2
% ls -m
Memo_App, Memo_App.xcodeproj, README.md

【Gitエラー】「fatal: Out of memory, malloc failed (tried to allocate xxxxxxxxxxx bytes)」の解決方法

原因

ファイル容量の大きいGitリポジトリをチェックアウトしようとしたら起きたので、Gitの解凍処理でメモリが食い尽くされているのが原因らいしい

解決策

解凍処理を小分けにする

~/.gitconfigに以下を追記する

1
2
3
4
5
6
7
8
[core]
packedGitLimit = 128m
packedGitWindowSize = 128m

[pack]
deltaCacheSize = 128m
packSizeLimit = 128m
windowMemory = 128m

自作ソート【Swift】

目的

  • ソートアルゴリズムの基本を身につける
  • Swiftになれる

要件

  • 数字をソートアルゴリズムを使ってソートする(Swiftのソート関数は使わない)
  • 日本語ひらがな、アルファベット小文字の1文字をソートする
  • インプットは数字の場合と、文字の場合がある (ただし、文字と数字の組み合わせはない、どちらか1種類のみの羅列が入力される)
  • 最後に昇順 or 降順の指定がある
  • ユーザーは決まった手順を守るとは限らないので、その場合の例外の対応方法の組み込み (無理矢理処理しても、エラーを返してもいい)k

コード

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
import UIKit

let testValue1:String = "24,6723,23,111,43,1,昇順"
let testValue2:String = "え,い,う,か,と,昇順"
let testValue3:String = "-2,-22347999,あ,2,い,3,-1,ああ,昇順"

enum OrderType:String{
case none = "例外"
case ascending = "昇順"
case descending = "降順"
}

enum ValueType:String{
case Iregular = "例外"
case Number = "数字"
case Charactor = "ローマ字"
case Japanese = "日本語"
}

// ============= メイン処理 ==============
// 入力された文字列を分割
var inputValueList = testValue3.split(separator: ",")

// ソートタイプのチェック
var orderType:OrderType = OrderType(rawValue: String(inputValueList.last ?? "")) ?? OrderType.none

if(orderType == OrderType.none){
print("ソート方法を指定してください")
print("指定がないため、昇順ソートを行います")

orderType = OrderType.ascending
}else{
// ソート指定は邪魔なので取り除く
inputValueList.removeLast()
}

// 入力文字列のタイプを判定
let valueType = CheckValueType(targetValueList: inputValueList)

// ソート処理
var sortedNumberList:Array<Substring> = Array<Substring>()
sortedNumberList = Sort(targetNumberList:inputValueList)

// 何をソートしたか表示
switch valueType {
case .Number:
print(ValueType.Number.rawValue + "ソート完了")
case .Charactor:
print(ValueType.Charactor.rawValue + "ソート完了")
case .Japanese:
print(ValueType.Japanese.rawValue + "ソート完了")
case .Iregular:
print(ValueType.Iregular.rawValue + "ソート完了")
}

// ソートタイプによって出力を切り替え
switch orderType {
case .ascending:
print(sortedNumberList)
case .descending:
print(Array(sortedNumberList.reversed()))
case .none:
print("ソート失敗")
}

// =====================================

// ============== メソッド ===============
// 値のタイプを判定
func CheckValueType(targetValueList:Array<Substring>)-> ValueType{
var retVal : ValueType = ValueType.Iregular
let targetValueCount = targetValueList.count

var numberCount = 0
var charCount = 0
var japaneseCount = 0

// 数字の並びかチェック
for i in 0...inputValueList.count - 1{
let str:Int = Int(inputValueList[i].cString(using: .shiftJIS)!.first!)
if(str >= 48 && str <= 57){ // 数字
numberCount += 1
}else if(str >= 97 && str <= 122){ // 小文字
charCount += 1
}else if(str >= 65 && str <= 90){ // 大文字
charCount += 1
}else if(str == -125){ // ひらがな
japaneseCount += 1
}else if(str == -126){ // カタカナ
japaneseCount += 1
}
}


if(numberCount == targetValueCount){
retVal = ValueType.Number
}else if(charCount == targetValueCount){
retVal = ValueType.Charactor
}else if(japaneseCount == targetValueCount){
retVal = ValueType.Japanese
}else{
retVal = ValueType.Iregular
}

return retVal
}

// ソート処理
func Sort(targetNumberList:Array<Substring>)->Array<Substring>{

var sortList = targetNumberList
var isChange = false

for index in 0...sortList.count - 1{

if(index + 1 == sortList.count)
{
break
}

let firstList = sortList[index].cString(using: .shiftJIS)!
var firstSign = 1
var firstJapaneseSign = 0

let firstCheckValue = firstList.first!
if(firstCheckValue == 45 ) // マイナス符号
{
firstSign = -1
}

if(firstCheckValue == -125 || // ひらがな
firstCheckValue == -126) // カタカナ
{
firstJapaneseSign = Int(firstCheckValue) * -1
}


var first:Int = 0

for fc in firstList{
first += Int(fc) * firstSign
}

if(firstJapaneseSign != 0){
first *= firstJapaneseSign
}


let secondList = sortList[index+1].cString(using: .shiftJIS)!

var secondSign = 1
var secondJapaneseCheckSign = 0

let secondCheckValue = secondList.first!
if(secondCheckValue == 45) // マイナス符号
{
secondSign = -1
}

if(secondCheckValue == -125 || // ひらがな
secondCheckValue == -126) // カタカナ
{
secondJapaneseCheckSign = Int(secondCheckValue) * -1
}
var second:Int = 0

for sc in secondList{
second += Int(sc) * secondSign
}

if(secondJapaneseCheckSign != 0){
second *= secondJapaneseCheckSign
}


let firstValue = sortList[index]
let secondValue = sortList[index+1]

if(first > second)
{
isChange = true

sortList[index] = secondValue
sortList[index + 1] = firstValue
}
}

if(isChange){
sortList = Sort(targetNumberList: sortList)
}

return sortList
}
// =======================================

備考(感想)

  • 文字コード変換する時に全てShiftJISのコードで変換されてしまった(未解決)
  • 今回使ったソートアルゴリズムは「バブルソート」
  • 小数に対応していない

div属性について

dev(devision)要素について

  • dev要素は、複数のブロックに対して、レイアウトを適応させることができる
  • \<dev\>\</dev\>で囲んだブロック全体にレイアウトが適応させる
  • 基本的な概念は内部CSSのclassidと同じ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<html>
<head>
<style>
.A{
background:pink;
}
#B{
background:yellow;
}
</style>
</head>
<body>
<!--classを使用-->
<div class="A">
<h1>これは見出しです</p>
<p>これは見出しに対する本文です</p>
</div>

<!--idを使用-->
<div id="B">
<h1>これは見出し2です</p>
<p>これは見出し2に対する本文です</p>
</div>

</body>
</html>