- 投稿日:2020-12-08T22:50:48+09:00
演算子について【Swift】
はじめに
初歩的な演算子についての備忘録になります。
比較演算子
例 等しい a == b 等しくない a != b 大なり a > b 小なり a < b より以上 a >= b より以下 a <= b 論理演算子
例 論理否定 !a 論理積 a && b 論理和 a ll b 複合代入演算子
変数の値を更新したいときに使う(整数のみ)
例 内容 += a += b a = a + b -= a -= b a = a - b *= a *= b a = a * b /= a /= b a = a / b %= a %= b a = a % b 自然数列の和を求める例
var sum = 0 for i in 1...100 { sum += i } print(sum) // 5050三項演算子
簡単な場合分けによる値代入
書式
条件 ? trueの値 : falseの値簡単な場合分けの例
let a = 30 let b = 60 var winner = "勝者は" // if文での条件分岐 if a > b { winner += "Aさん" } else { winner += "Bさん" } print(winner) // 勝者はBさんlet a = 30 let b = 60 var winner = "勝者は" // 三項演算子 winner += a > b ? "Aさん" : "Bさん" print(winner) // 勝者はBさん
- 5行が1行にまとまりスッキリとなりました。
- 三項演算子の気をつける点としまして、半角スペースを置かずに「?」をつけると「オプショナル型の宣言」と解釈されエラーになりますのでご注意下さい。
- 投稿日:2020-12-08T18:50:27+09:00
iOSでNode.jsを動かしたい(ついでにWebRTCシグナリングサーバーも)
はじめに
これは Node.jsアドベントカレンダー2020の記事です。実用性皆無のネタ記事ですが、リラックスしてお楽しみください。
twitterで「iPadでLinuxが動く」というツイートを見たことがきっかけで、iPad/iPhone上でNode.jsを動かしてみました。内容は次の通りです。
- iSH Shell で Node.jsを動かす
- Node.jsでWebサーバーを動かし、Safariでアクセスする
- オマケ:WebRTCのシグナリングサーバーを動かして、iPadとiPhoneで通信する
iSH Shell
iSH Shellとは
利用するアプリは、「iSH Shell」(App Store)というアプリです。私は知りませんでいたが、以前からあるアプリのようです。
名前は「Shell」とありますが、実際にはアプリケーションレイヤーでlinuxをエミュレーションしています。利用されているディストリビューションは、Alpine Linuxです。ちなみに使用するには、Bluetoothキーボードがあった方が便利です。
iSH Shellのインストール
普通にApp Storeからインストールします。
中身の確認
- デフォルトのユーザーは root
- /etc/issue をみると、Alpine Linux 3.12
- CPUアーキテクチャーは、i686(インテル系32ビット)
シェルで操作~# whoami root ~# cat /etc/issue Welcome to Alpine Linux 3.12 Kernel \r on an \m (\l) ~# uname -m i686パッケージマネージャーの追加
アプリをインストールした状態では、Alpineのパッケージマネージャー apk はインストールされていません。どうやらApp Storeの規約上、取り除く必要があったようです。
(※2020.12.15現在、App Store版でもapkがインストール済みになったようです)こちらの手順に従い、apkをインストールします。
- GitHub ... https://github.com/ish-app/ish/
- Wiki ... https://github.com/ish-app/ish/wiki
- Tutorial:Installing apk ... https://github.com/ish-app/ish/wiki/Installing-apk
- ※手順はこのページに記載
シェルで操作~# wget -qO- http://dl-cdn.alpinelinux.org/alpine/v3.12/main/x86/apk-tools-static-2.10.5-r1.apk | tar -xz sbin/apk.static && ./sbin/apk.static add apk-tools && rm sbin/apk.static && rmdir sbin 2> /dev/null ~# apk --version apk-tools 2.10.5, compiled for x86.Node.js を動かす
Node.jsのインストール
iSHとapkが用意できたら、念願のNode.jsをインストールします。
~# apk add nodejs ~# apk add npm ~# node -v v12.18.4 ~# npm -v 6.14.62020/12/5現在、node v12.18と、npm 6.14がインストールされました。(※npmは応答が返ってくるまで、時間がかかります。何かのタイムアウトが発生している?)
REPLの利用
さっそくREPL(対話モード)を動かしてみます。
~# node Welcome to Node.js v12.18.4. Type ".help" for more information. > 1+2+3 6 > console.log('Hello Node.js') Hello Node.js undefined > .exit ~#Webサーバーを動かす
次はNode.jsを使って、簡単なWebサーバーを動かしてみます。
server.jsconst http = require('http'); const server = http.createServer((req, res) => { res.end('<html><h1>Hello World!</h1></html>'); }); server.listen(8000);シェルから起動します。
~# node server.jsiPadの場合
iSHがバックグラウンドに回ってしまうと、内部のプロセスの実行が停止してしまいます。そのためiPadの場合はSplit View(Appleの説明)を使って、iSHとSafariを横に並べて使います。
- iSH上で、サーバーを起動
- Split Viewで、Safariを同時に表示
- Safariで、http://localhost:8000/にアクセス
- 「Hello World!」と表示されればOK
iPadなら、そこそこ実用的にNode.jsを動かすことができます。
iPhoneの場合
iPhoneでは、Split Viewが使えず、同時に2つのアプリを動かすことができません。そこで次の手順で無理やり実行します。
- iSH上で、サーバーを起動
- Safarを起動し、http://localhost:8000/にアクセス
- ロード待ちになる
- iSHに切り替えると、サーバーがリクエストを処理する
- 再びSafariに切り替えると、Safari上でページが表示される
リクエストが飛ぶたびに、iSHとSafariを切り替えてやる必要があります。iPhoneではかなり厳しいです。
iSH Shellの制約
iSH Shellではx86をエミュレーとしてLinuxが動いていますが、一部デバイスに近い部分では使えない機能があるようです。具体的には、ネットワーク周りの機能では動かないものがありました。
例えば、Node.jsで次のコードを実行しようとすると、エラーが発生します。コードの抜粋const os = require('os'); const interfaces = os.networkInterfaces();エラーUncaught: SystemError [ERR_SYSTEM_ERROR]: A system error occurred: uv_interface_addresses returned Unknown system error 22 (Unknown system error 22)ネットワークスインターフェイスの情報が取れていないようです。
オマケ:WebRTCのシグナリングサーバーを動かす
ここからは、完全に個人の興味によるオマケです。
WebRTC とシグナリング
Node.js が動くなら、WebRTCのシグナリングを動かしたくなるのが性分です。
- WebRTC ... Web Realtime Communitaion
- Web上で、音声/映像/データをやり取りするための仕組み
- P2Pでのユースケースを想定して規格が作られたが、いまはサーバー経由の利用が増えている
- シグナリング
- これから通信を始める2者が、通信開始に必要な情報を交換するための手続き
- WebRTCではやり方は規定されていない
- サーバー経由で、WebSocket等の双方向通信の仕組みでやり取りすることが多い
ここでは説明は省略します。興味がある方は(ちょっと古いですが)こちらをご参照ください。
- WebRTCハンズオン 概要編 ... https://qiita.com/massie_g/items/916694413353a3293f73
シグナリングサーバーとWebサーバー
よくあるケース
通常はシグナリングのサーバーはローカルネットワーク内のPC上か、インターネット上で動かし、通信したい2つの端末で接続します。
iOSデバイスだけで動かしたい
今回はPC(Mac)やインターネット上のサーバーを利用せず、2台のiOSデバイスだけでシグナリングサーバーを動かし、WebRTC通信を行ってみます。
- iPad と iPad
- または、iPad と iPhone
(不自然ではありますが、そういう縛りのある状況でデモしなければならない、という設定をご想像ください汗)
また、ブラウザでメディア通信で使うカメラ/マイクにアクセスするには、セキュリティ上の制限により次の場所にあるWebページの必要があります。
- https://~
- または、 http://localhost:ポート番号/~
そのため、2台のデバイスそれぞれでWebサーバーは動かします。
iSH でWebサーバー/シグナリングサーバーを動かしてみる
Webサーバー/シグナリングサーバは、Node.js + express + ws(WebSocket) で実装しています。
準備(セットアップ)
- 2台のiOSデバイスを用意 (iPad + iPad, or iPad + iPhone)
- それぞれに、iSH Shell をインストール、apk, node.js もインストール
- それぞれに、gitもインストール
- apk add git
- それぞれに、コードを取得(ブランチを指定してください)
コードを取得~# apk add git ~# git clone https://github.com/mganeko/webrtc_1to1.git ~# cd webrtc_1to1 ~# npm install準備(情報収集)
今回シグナリングサーバー役のデバイス1は、iPadを利用する必要があります。(iSHをバックグラウンドに回さないように)。一方、デバイス2側からは、デバイス1のIPアドレスを知っておく必要があります。
- (A) 両方が、同じWiFi環境にいる場合
- デバイス1側で、割り振られているIPアドレスを確認
- 「設定」-「Wi-Fi」- 詳細情報(iボタン)で、ネットワークの情報を確認
- IPV4アドレスの表から、自分のIPアドレスを取得
- 192.168.0.xxx など
- (B) それ以外の場合
- デバイス1側で、「インターネット共有」(テザリング)をオンに
- デバイス2側で、デバイス1で共有したWiFiに接続
- デバイス2側で、接続情報を確認
- IPV4アドレスの表から、「ルーター」のアドレスを確認
- 172.20.xxx.1 など
- ※テザリングしているデバイス1でなく、そこのぶら下がるデバイス2側で確認します
(A),(B)それぞれに応じた方法で取得したシグナリングサーバー(デバイス1)のIPアドレスを、次のステップで利用します。
実行
(1) サーバーの起動
デバイス1、2の両方で、サーバーを起動します。
起動~# npm start > webrtc_1to1@1.0.0 start /root/work/webrtc_1to1 > node server_1to1.js websocket server start. port=8080 Web server start. http://localhost:8080/(2) SafariでWebサーバーにアクセス
起動したらそれぞれのデバイスでWebサーバーにつなぎますが、デバイスごとにURLが異なります。
- デバイス1(ローカルのシグナリングサーバーに接続する)
- デバイス2(シグナリングサーバーのURLを別途指定する)
- http://localhost:8080/sub.html
- ※デバイス2がiPhoneの場合は、SahariとiSHを交互に切り替えながら、Webページをロードしてください
※iOSデバイスがスリープしてしまうと、サーバーの実行が止まります。再度起動し直してください。
(3) カメラ映像の取得
- デバイス1で、[Start Video]ボタンをタップ
- アクセス許可を求められたら、[許可]をタップしてください
- 同様にデバイス2でも、[Start Video]ボタンをタップ
- アクセス許可を求められたら、[許可]をタップしてください
(4) 接続
接続はデバイス2 (sub.html)側から行います
- デバイス2側で、テキストエリアにシグナリングサーバーのURLを入力
- 例えば、「ws://192.168.0.10:8080」
- ※ポート番号は 8080 です
- デバイス2側で[Connect]ボタンをタップ
- 接続情報が交換され、通信が開始します。
(5) 切断
- デバイス1,2 どちらでも良いので、[Hang Up]ボタンをタップします
- ※この状態で[Connect]ボタンをタップすると、再接続できます
コード
https://github.com/mganeko/webrtc_1to1.git にあります。
おわりに
「iOSでNode.jsを動かしたい」という何の実用性もない記事でした。もし不幸にも(?)そういう状況に陥ったら思い出してみてください。
- 投稿日:2020-12-08T17:10:25+09:00
Xcode12.1で動かしていたが、iOS14.2のシミュレータが見つからなかった。
解決策
XCode12.1にはiOS14.2のシミュレータは含まれていない。XCode12.2以降を使う。どのXCodeにどのSimulatorが含まれているか、およびXCodeの詳細情報はApple公式でチェックできる。
https://developer.apple.com/jp/support/xcode/
補足
なお、アプリはXcode12.1でビルドしたいが、シミュレータは(XCode12.2以降にしか存在しない)iOS14.2のものでやりたい、という場合は、以下のような少しトリッキーな技が使える。
- 投稿日:2020-12-08T16:46:32+09:00
App Store ConnectでApp Privacy Detailsを登録する
はじめに
- 2020/12/8からアプリのプライバシー情報を申請時に登録が必要になりました。 今後はApp Storeにアプリのプライバシー情報がアプリページに表示されるようになります。 今回は登録時にやったことについてまとめました。
- 詳細はこちら App privacy details on the App Store
項目
やったこと
- でてくる質問に対して、該当するところにチェックを入れていきます。
- 該当するデータタイプを選択していきます
- ここまで終わると該当する項目が一覧で表示されます。
- ここからは各項目の情報の利用目的について、チェックしていきます。
- 各項目はいつでも変更可能になっています。
- 公開ボタンを押すとダイアログが表示され、公開を押すと反映されます
運用方法案
エクセルなどで管理する
- 1番よく使われる方法だと思います。手動で項目を反映さえていくのが結構手間です。
fastlane
- Uploading App Privacy Details
- 設定項目をアップロードするActionが追加されている
- JSONで管理できるので一度つくってしまえば楽だと思いました
upload_app_privacy_details_to_app_store( username: "your@email.com", team_name: "Your Team", app_identifier: "com.your.bundle", json_path: "fastlane/app_privacy_details.json" )[ { "category": "PAYMENT_INFORMATION", "purposes": [ "APP_FUNCTIONALITY" ], "data_protections": [ "DATA_NOT_LINKED_TO_YOU" ] }, { "category": "NAME", "purposes": [ "PRODUCT_PERSONALIZATION", "APP_FUNCTIONALITY" ], "data_protections": [ "DATA_LINKED_TO_YOU", "DATA_USED_TO_TRACK_YOU" ] } ]まとめ
- アプリのプライバシー情報を申請時に必要になりました。
- fastlaneなどを使って、運用を楽にしていきたいと思いました。
参考リンク
- 投稿日:2020-12-08T15:14:03+09:00
大学でコンピュータ科学を学びながら、個人でアプリやフロントを書き続けた結果得られたもの
0. はじめに
こんにちは、とうようと言います。
普段は東大大学院のコンピュータ科学専攻の学生をしていたり、Life is Tech !というところで中高生にiOS開発などを教えたり、個人や受託の形でiOS/AndroidアプリやReact.jsを使ったWebサービスを作ったりしています。今回のアドベントカレンダーは「プログラミング技術の変化で得られた知見・苦労話」がテーマということで、少し変化球ではありますが、大学で情報科学・コンピュータ科学の古典的な知識を学びながら、個人の活動で最新の技術を追い続けるようなスタイルをとっていた大学生活で何が得られたのか、どんなことが良かったのかということをポエムにしていこうと思います。
今の中高生というと、一部の物好きがプログラミングをしていた僕の中高生時代からだいぶ進んできて、企業でインターンしたり、自分で起業できるぐらいのコーディング力をすでに現段階で身につけている子がゴロゴロいるような世代になってきています。
そんな子達の進路相談なども時々受けたりするのですが、その際よく観点として上がるのが「大学に行くべきなのかどうか?」という点です。もちろんこの質問自体にはいろんな観点がありますし、そもそもコンピュータ科学を大学で学ぶべきか、後から興味がわいた時に自分で学べばいいのでは?みたいな話もあったりするので、一概には言えないのですが、そういう中高生たちやこれからコンピュータ科学を独学しようかと思っているエンジニアのみなさんの参考になるのではないかと思い今回の記事を書くことに決めました。
前置きが長くなってしまいましたが、最後に大前提として僕のスペックを箇条書きにしておくので「このくらいのレベル感の人が得られた知見」だと割り切って、少しでも参考にしてもらえればと思います。
- 大学の専門科目のテストは総合して際立っていいわけでもめちゃくちゃ悪いわけでもなかった。落単は基本的にしていなかったが、定着度もそこそこぐらいだった。
- iOSアプリ開発は個人でいくつかリリースしたのと、受託の手伝いやサマーインターンをこなしたぐらい。ただし教える立場上ある程度最新の情報は追っていたり、学生の中ではそれなりに技術力があるという程度のレベル感。
- Webフロントについては研究プロトタイプや、先日リリースされたオンライン劇場zaでNext.jsを活用していたというぐらい。そこまでちゃんと最新技術を追えているわけではないが基本不自由なく書けるぐらいのレベル感。
- プログラミング自体は中高生からやっていて、そのころは競技プログラミングを主にやっていた。
1. コンピュータ科学って結局何を学ぶの?
まずはじめに、どんなことを学ぶのかの全体像がわかってないと今後の話もあやふやになると思うのでまずはそこから行きたいと思います。
というわけで今回は自分の成績表から科目名をざっくり引っ張り出してきてみました。一部選択科目などもあるので一概にこれがコンピュータ科学の科目です!とは言い切れないのですが、東京大学理学部情報科学科・東京大学大学院情報理工学系研究科コンピュータ科学専攻で学べるシラバスの一例としてみてもらえればと思います。
それではドン!
科目名 簡易説明 情報数学 情報分野で扱うような数学、符号理論とか群環体あたりの話 形式言語理論 オートマトンとか正規言語とか 計算機システム 計算機の仕組み、アセンブリの知識など ハードウェア構成法 ASICや論理回路設計の話 アルゴリズムとデータ構造 基本的なアルゴリズムを学ぶ 情報科学基礎実験 C,Scheme,アセンブリで色々実装してプログラミングの基礎を叩き込む コンピュータグラフィクス論 CGの仕組み学んだり、実際に実装したり オペレーティングシステム OSの仕組みを実習もしながら学ぶ 離散数学 グラフ理論、線形計画法とか 情報論理 一階述語論理とか、不完全性定理とか 言語処理系論 言語処理系を構築する理論とか構文解析について 情報科学演習I 離散数学と情報論理の問題を解いていく 知能システム論 人工知能の基本的なこと 計算機構成論 計算機アーキテクチャについて、特定のCPUについて調べて発表したり 言語モデル論 プログラミング言語のモデル、意味論、型推論のこととか 計算量理論 チューリングマシンやNP完全、近似アルゴリズムについて学ぶ 連続系アルゴリズム 浮動小数点や数値積分などを扱うアルゴリズム周りのあれこれ 情報科学演習II 計算量理論、連続系アルゴリズムの問題を解く コンピュータネットワーク インターネットの仕組みなどを学ぶ システムプログラミング実験 Linuxをいじったりシェルを作ったりする演習 関数・論理型プログラミング実験 関数型言語を学ぶ、PrologとかOCamlとか ハードウエア実験 VHDLを使って論理回路とかを実装 プロセッサ・コンパイラ実験 FPGAを使って3~4人チームでCPU,コンパイラ,シミュレーターなどを分担して作り、レイトレーシングプログラムを動かすことを目指す ユーザーインターフェイス ユーザーインターフェイスの歴史を学び、課題に応じてユーザーインターフェイスを実装 計算アルゴリズム論 数値積分や偏微分方程式の数値解法について 離散アルゴリズム論 離散アルゴリズム(確率を使ったものや量子系)について 計算科学シミュレーション HPCについて学び、HPC向けのアルゴリズムなどについて学ぶ 計算機言語論 コンパイラとかの理論の発展 自然計算 自然科学が関わるようなアルゴリズムなどについて、セルオートマトンとか 量子計算科学 量子コンピュータとかで扱われるもろもろについて 知識処理論 機械学習の授業 統計的機械学習 機械学習の中でも統計で扱うようなものについて メディア情報学 ユーザーインターフェイスの論文を輪講した後、最後に題材を使って面白いものを作る 配列解析アルゴリズム特論 配列を扱うようなアルゴリズムに関して 言っても大学と大学院の4年半のカリキュラムの中で行われている授業の一覧なので多少端折ったとはいえ量は結構多いですね。
このように一般的なプログラミングや普段使っているパーソナルコンピュータの仕組みはもちろんのこと、アルゴリズム一つとっても通常のCPU、HPC、量子コンピュータそれぞれに向けたものを各科目で学んでいたりと、古典となる理論から最新の機械学習事情まで幅広く学ぶのが情報科学・コンピュータ科学を「アカデミックで」学ぶということになります。なおここではこのざっくり説明以上のことは本筋からも逸れてしまうので語りません。もっと詳しく知りたい方は学科のHPで色々みてみてください。
2. 大学の知識が役立った瞬間5選
ざっくり説明でどんなことをやっているかさらってもらったところで続いて大学で学んだことが役立った瞬間をいくつか例にあげていきたいと思います。
Case 1: 関数型の気持ちがわかった瞬間
まず1つ目は関数型の気持ちがわかった瞬間です。このこと自体は関数型が好きな人からしてみれば別に大学でやらなくてもというところだと思いますが、大学では関数型言語をただ学ぶだけでなくその仕組みや背景などもいろんな科目を通して学ぶことになります。
そのため中高時代は競技プログラミングメインで手続き型に慣れていて、なかなか関数型を使いこなすレベルまで行けていなかった自分でも関数型の気持ちがわかってきて、SwiftやTypeScriptを書くときも関数型的な機能を自然に使いこなせるようになりました。
Case 2: 自分のする解説・理解に厚みが出た瞬間
次は自分のする解説・理解に厚みが出た瞬間です。例えばプログラミング言語のほとんどが配列を0-indexedで扱うようにしているということ自体は有名な話ですが、これを初学者に説明する場合みなさんならどのように解説するでしょうか?
普通に考えると「そういうふうになってるから注意してね」というようなワンポイント解説的なものに留まってしまうことが多いのではないでしょうか?
ですが僕はこれに関してちょうどOSやらシェルやらを扱っている授業を通して次のような気付きを得ました。「Cの配列とポインタって同じように扱えるよな、array[3]とarray + 3が同じ意味になると考えると0-indexedになるのは確かに自然な実装だよな」
さらに
「ポインタってことはこれはメモリ上でのアドレスを示しているよな、配列の先頭のアドレスを配列の名前で表せるとして、そこから連続して値が入ってるわけだから配列のsubscriptにどのくらいアドレスをずらすと目的の値がみれるのか渡せば目的の値を取り出すのに一番必要な論理演算少なく取り出せるよな、だから1-indexedにはしないのか」
みたいな。(※ 個人での気づきなので本当にこう考えて設計されたという証拠はあまりないです)
もちろんこれをそのまんま解説しても基礎がわかっていない人には何の話じゃという感じになってしまいますが、ある程度理解してきたときに「実は...」的な感じで話せばプログラミングっておもしろい!って思ってもらえる一つのきっかけ程度にはなるんじゃないでしょうか。
このように多角的にコンピュータのことを学んでいるからこその気付きが出てくるのがアカデミックに学ぶ利点の大きなところかなと思っています。Case 3: 知見のない分野に「こうすればいいのでは力」を発揮できた瞬間
3つ目は知見のない分野に「こうすればいいのでは力」を発揮できた瞬間です。
IT技術って本当に多岐に渡りますよね。そんな中一つの分野について極めてくるとその分野の新しい技術や仕組みに出会ったときに「こうすればうまくいくんじゃないか?」みたいな予感が働くことってあるんじゃないでしょうか。こういう力っていうのは通常、自分が深く関わっている分野に何かしら関連がないと働かないものだと思いますが、アカデミックなコンピュータ科学では広範囲に手を広げているので、かなりの範囲でその力を働かせることができるようになります。
これはもちろんその分野をかじっていて、そこまで覚えてなくても記憶の片隅に何か残ってるから、というのもありますが、もっと大きな要因としては各分野のつながりをわかっているからというものがあるのではないかなと思っています。だからこそ自分の引き出しの中からこれに当てはめれば似たようなやり方でできそう、がかなりの広範囲でできるということです。あくまで個人的な感覚でしかないですが、おそらくこのおかげでかなりフルスタックにカバーできる技術力を身につけられたのではないかなと思います。
Case 4. 曲芸のようなデバッグができた瞬間
4つ目は曲芸のようなデバッグができた瞬間です。
アプリ開発やサービス開発をしていると往々にして「謎のバグ」に立ち向かうハメになることはありますよね。
そんなときその分野での一般的なデバッグ方法が役に立たない瞬間というのもあるのではないでしょうか?そこで「何となくこんな感じの原因な気がする」とあたりをつけて全くの別角度から攻めてデバッグ成功する、こういう曲芸というか飛び技というかができるのがコンピュータ科学を知っている強みだと思います。
Case 5. 日常の開発にアルゴリズムを活用できた瞬間
最後は日常の開発にアルゴリズムを活用できた瞬間です。これはどちらかというと大学の知識、というより競技プログラミング力なのかもしれませんが、何か日常の開発で「こういうロジックを組めばうまくいきそう」とアルゴリズムを組んでいけるのは大きな強みかなと思っています。
以上他にも自分で気づいてないうちに恩恵を受けている部分はもっとあると思いますがその中でも印象深いものを例にあげてみました。
このような恩恵が活かせるのが「コンピュータ科学」です。3. 技術の進化に関係なく使える力
さて、本編最後としてアドベントカレンダーのテーマにもかけて技術の進化に関係なく使える力というテーマで語っていきたいと思います。
ここまで紹介してきた大学で学ぶ学問としてのコンピュータ科学、幅広いとは言いましたがそのほとんどが現代型計算機ができたノイマンの時代、さらにはその前から着実に積み上げられたもので最近の技術の発展のスピードから見たら古典的な知識が多いことは事実だと思います。
一見これらの知識は不要なものかもしれません。事実、現代のエンジニアの中にはここらへんの知識を一切知らないけど活躍している方は相当数いると思います。ですがそんな知識でも役に立つ瞬間が数多くあるのは前の章で見てもらった通りだと思います。進化の早いこの世界、3年もすれば古くて使い物にならないなんてざらなこの業界でなぜそんなことがありうるのでしょうか?
そこに僕は技術の進化に関係なく使える力というものが関わってくると思います。正直に言うと、僕自身最初に定着度はそこそこと述べた通り各授業の詳細はほとんど覚えていません。もともと授業を受けている間も苦手だった離散数学の問題なんか持ってこられても1ミリも解けずに終わってしまうと思います。またHPCやOSをいじることなんてこの先ソフトウェアエンジニアとして生きていく中で少なくとも仕事ではほとんどないと思います。これらの知識はある意味直接的には使わない知識です。
ですがどんなに知識を忘れていても考え方のエッセンスみたいなものは身についていると思います。それこそが技術の進化に左右されない力なのではないでしょうか。
もう少し踏み込んでこれを説明してみましょう。物事の定着にはいかに自分のすでに持っている知識と結びつけられるかが大事です。僕自身はそれをここまで語ってきたコンピュータ科学の分野、さらにリアルタイムに最新の技術を追うことでその知識も絡めて行うことができました。
つまり、コンピュータの過去から現在を一気通貫でリンクする、そんな経験を大学時代にできたわけです。これが何よりの僕の経験で得られた財産であると思っており、これこそが考え方のエッセンスそのものなのではないかと考えています。4. 番外編: 大学に入ったからこそ得られた機会
おまけとして大学に入ったからこそ得られた機会についてみていこうと思います。
これは結論から言ってしまいますが、一番は「人」だと思います。ありきたりの答えですが、この結論は揺るがないかもなと思っています。
大学には本当に多様な人がいます。特に総合大学だとなおのことでしょう。
法学部でバリバリのアプリエンジニアになったサークル同期がいたと思えば、全くプログラミングをしていなかったクラスの同級生がCTOになってたり、同じ学科の中でも理論が好きな人からゲーム制作が得意な人までさまざまな人がいるのが大学の多様性です。(もちろんエンジニア関連以外にもいろんな人がいますよね、同じ学科から吉本興業のマネージャーに就職した人なんかもいます)
もちろんインターンを渡り歩いたりいろんなところに顔を出すことで同じ経験を大学に行かずとも得られる人もいるとは思います。ですがアカデミック志向な人ってなかなか、大学じゃないと出会えないんじゃないでしょうか。いや、別にそんな例を無理に見つけ出さなくても、自分から頑張ってようやくその機会を得られるのか、いるだけでその機会を得られるのかは多分雲泥の差だと思います。
そんな利点があるのが、大学です。これを見て利点と思わなかったり、もっと大事なことがあるひとは別の道を選ぶのもありなのかなと思います。
あくまでこの記事は「参考」でしかないので。
5. まとめ
以上大学でガチガチの情報科学・コンピュータ科学を学びながら、趣味や仕事ではフロントやアプリの最新技術を追い続けた僕なりの知見をつらつらと語ってみました。
ちなみにこの記事は「だから○○がいいよ」と宣伝するような意図の記事ではありません。あくまで「冒頭で述べたようなスペックの学生がこういう経験をするとこんなことを得られるよ」という一例であるので、ぜひそこを十分に踏まえた上で進路を決めたり、コンピュータ科学を学ぶ上での参考にしてもらえればなと思います。
また手前味噌ですが、今年のアドベントカレンダーでこの記事とは別に今度は「教える側」について語った記事も用意しています(あわせると卒業文集になります。嘘です。修論がんばります。)
研修をする際や、自分で学ぶ際、ぜひこちらも参考にしてみてください。それではみなさん、メリークリスマス!笑
illustrated by unDraw
- 投稿日:2020-12-08T01:43:42+09:00
【Swift5】UITableViewCellで画像や色を変えたのにも関わらず同じセルが表示されるバグの対処法
はじめに
UItableViewCellのセルの再利用の仕組みによって、指定したcellの見た目を変える処理をした際に、過去のセルの変更が残ってしまうというちょっとしたバグが発生したので今回はUItableviewのセルの仕組みをみていきます
セルの再利用
TableViewは、大量にある同じ種類の情報をリスト表示する際に利用されます。そのため実装方法によってはセルの描画数が非常に多くなり、特にスクロール時には、パフォーマンスの低下が考えられます。これを解決するのがcellの再利用です。毎回新しくviewを作るのではなく以前に生成したcellを利用することで、メモリ割り当てを最小限にできます。
まずセルの再利用の際にはUItableviewにデフォルトで設定されているこのメソッドを使います公式ドキュメント参照
https://developer.apple.com/documentation/uikit/uitableview/1614891-dequeuereusablecellfunc dequeueReusableCell(withIdentifier identifier: String, for indexPath: IndexPath) -> UITableViewCellそしてこのメソッドを、cellの生成されるタイミングで上のメソッドを発火させます
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { //処理 }このメソッドは、再利用可能なcellがあればそれを、なければ新しく作成したcellを返します。再利用可能なcellは、reuseIdentifierに紐づけられた
reuse queue
という場所に格納されています。Reuse Queue
tableviewは裏側で
reuse queue
という、データの箱のようなものを持っており、reuseIdentifierごとにreuse queueが存在します。画面外に出たcellは、自身のidentifierに紐づいたreuse queueに追加されます。そして、同じidentifierのcellが表示されようとする時、queueから取り出されます。
下の図のようにスクロールしたら次のcellがqueueから取り出されるイメージ
セルの再利用の落とし穴
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // セルを取得(セルの再利用メソッド発火) let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "cellidendifier", for: indexPath) print(indexPath.row) //セルのviewを変更する処理 cell.textLabel!.text = "\(self.data[indexPath.row])" if indexPath.row == 3{ cell.backgroundColor = UIColor.red } return cell }例えばこんな感じで指定したセルの色を変えたい時にこのような処理を書くと、背景色を赤に変えたセルは、他のセルにも再利用されてしまいます。
指定した以外の色は元に戻す必要がありますfunc tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // セルを取得(セルの再利用メソッド発火) let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "cellidendifier", for: indexPath) print(indexPath.row) //セルのviewを変更する処理 cell.textLabel!.text = "\(self.data[indexPath.row])" if indexPath.row == 3{ cell.backgroundColor = UIColor.red } else { cell.backgroundColor = 元の色 } return cell }カスタムセルの中身の画像を動的に変更したい場合はこのようにカスタムセルの画像を初期化する必要があります
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // セルを取得(セルの再利用メソッド発火) let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "cellidendifier", for: indexPath) //画像を初期化 cell.sampleimage.image = nil return cell }最後に
セルを再利用してることで前の状態が残るので、想定とは異なるview状態になります
今後似たような症状が起きた場合は、再利用によるセルリセットし忘れを疑いましょう