Javaから見たSwiftとの違い ~for文編~
こんにちは。今回はSwiftネタです。
最近C#とSwiftに一気に手を出してしまったため、苦悶の日々を過ごしております(笑)
両方ちょっとだけ触ってみる予定だったのに…
そんなわけでSwiftに挑戦しているわけですが、よく分からないところが多い!
さらに、Swiftはバージョンがどんどんあがってるようで、今使われているのはSwift3というものだそうです。
そのため、ググってみても古い情報だった、なんてことがよくあります。
『ちょっと手を出したかっただけなのに、苦しめやがって、このやろう!』な気分なので、苦しめられたところをメモしていこうかな、と思います。
今回は、第一回としてfor文を扱っていこうと思います。
本記事をお読みの方へ
ここで注意点ですが、この記事はJavaなどのC言語的文法をもった言語から見ての感想が大いに含まれています。なぜなら私はJavaしか使ったことがない趣味のプログラマーだから。
ほかのもっとモダンな言語使いのプロフェッショナルな方々には、鼻で笑われてしまうような内容となっておりますので、これを読まずにもっとましなものをお読みください。
それでは参りましょう!
for文の基本構文
みなさん、for文使いますか?
うんうん、そうですよね、使いますよね!
巷では、for文を使わなきゃプログラミングしてるとは言わない、と言われてるとか言われてないとか。
ということで、Swiftでfor文を書こうと思うわけですが、これが一癖あります。
Javaではfor文は以下のようになります。
int a = 0; for(int i = 0; i < 10; i++){ a += i; }
aに0から9までを足し続けるという、びっくりするぐらいのくそコードですが、その際そんなことはどうだっていいんです(笑)
C言語もC#もほとんど一緒です。しかし、Swiftではこうなります。
var a = 0 for i in 0 ..< 10{ a += i }
for文が全然違うじゃないか!ってなりませんか!?
あっ、なりませんか。すいません。
少なくとも私はそう思いました。
forをいつものように書くとXcodeが怒ります。
おい、Cっぽい書き方をやめないか!的なエラーがでて驚かされます。
ここでぐぐってみると、Swiftにはモダンなforの書き方があって、上のものがそうだ、と知りました。
ちなみに、0..<10 は 0≦i<10 を、0...10は 0≦i≦10 を表すそうです。
上のソースを見ると、ちゃっかり型推論が使われています。varってなんかすごいなー、という気分になります。
色々なfor文
上に書いた書き方は、1ずつ増やして処理したい(i++する)時でしか使えません。ではそのほかの場合ではどうなるのでしょうか。
Javaと比較しながら書いておきます。見出しがJava的な書き方となっております。
for(i = 0; i < 10; i +=2)と書きたいとき
for i in stride(from : 0, to : 10, by : 2)
for(i = 0; i <= 10; i +=2)と書きたいとき
for i in stride(from : 0, through : 10, by : 2)
for(i = 10; i >= 0; i -=2)と書きたいとき
for i in stride(from : 0, through : 10, by : 2).reversed()
まとめ
stride()を使えば、刻み幅を変えることができます。toなら~未満を、throughなら~以下を表しています。
徐々に減らしていく処理では、最後にreversed()を付ければよいそうです。
ネットの記事ではよくreverse()とされていますが、そう書くとXcodeに怒られました。
最後に
いかがでしたでしょうか。今後もよく分からないところが出ましたら、その都度書いていこうと思います。
こういう書き方もあるよ!とかここは違うよ!といったアドバイスをいただけると、大変助かります。
ではまた。
Xamarin.Formsでlabelのテキストを動的に変更する
初歩中の初歩ですが、ググっても欲しい情報が一発ででなかったため、ここにメモします。
C#もxamlも初めて触るので、何もかも分からないのです。やっぱり最初は入門書を読むべきかな?!
方法
任意のxamlファイルに(今回はMainPage.xaml)Labelを追加します。
Textタグに記入した文字は、初期値として表示されます。
Nameタグにより、要素に名前を付けるようです。今回はLabelTextという名前にしました。
MainPage.xaml
<Label x:Name="LabelText" Text="Hello, world!" />
あとは、csファイルに処理を加えるだけです。
MainPage.xaml.cs
LabelText.Text = "Good job!"
(要素名).Textにて、要素内の文字列を制御できます。Buttonなど他の要素でも一緒です。
まとめ
非常に簡単です。AndroidのならfindViewByIdで、いちいちidを取得する、という行程を経なければなりませんが、C#ではこれがないため、すっきりとした見た目になったな、と感じます。
これを調べた際に、XamarinのSamplesが非常に役立ちました。今まで、分からないことはすぐググる、という手順で書いておりましたが、Xamarinの場合は、まずサンプルを見てみる、という方が良さそうです。
Samples - Xamarin
ではまた。
小学校のプログラミング必修化について調べてみる
こんにちは、たけぼーです。
今日は小学校でプログラミングを必修化する動きがあるので、いまさらですが調べてみたことを中心に自分なりに考えてみた、という話です。
なぜ『プログラミング』なのか
なぜ、必修化されるのはプログラミングなのでしょうか。
ITの普及した現代
この現代において、IT技術の爆発的な普及を考えると、教育課程でITに関する技術や知識、マナーなどを学ぶことのメリットは大きいと思います。
いまや小学生でもスマホを持ち、日々ネットを使い、友達と連絡をする。
こんな世の中ですから、ICT教育の必要性については言わずもがなであると思います。
しかし、ICT教育は現在のカリキュラムでも実施されています。情報リテラシーは、どの学生も一度は教えられることでしょう。
では、なぜ今回プログラミングが必修化されるのでしょうか。
プログラミング学習の目的
なぜなのか、これをプログラミングを学ぶ目的から考えてみましょう。
このプログラミング必修化で子どもたちに学んでほしいこととして、プログラミングに用いられる論理的思考や問題解決能力(プログラミング的な思考)を身につける、ということがあげられています。
プログラミングは、○○をしたら○○をする、もし○○なら○○をする、○○である間○○をする、などといった順序だてた思考が必要です。
二足歩行ロボットで例を挙げるなら、右足を出したら左足を出す、もし前に障害物があったら止まる、障害物がない場合ずっと歩く、といったことです。
私も、自分でプログラミングをする時、命令の順序や分岐、ループといった、いつ・何をさせるとうまくいくのかを強く考えながらコードを書いていると思います。これが、プログラミング的な思考なのだと思います。
論理的思考を育てるプログラミング
今書いてきた目的から考えると、論理的思考や問題解決能力という力を、小さなうちから身につけさせる、ということを目指すためには、プログラミングが最適だったわけです。
たとえば数学の証明問題といった類の問題でも、同じ様な力は身につけられるかもしれません。
しかし、これを小学生にさせるのはハードルが高すぎる、というよりも不可能です。証明問題を解くにはかなりの前提知識がいりますから。
その点、プログラミングで必要な前提知識としては、四則計算と言ったところでしょう。もっといえば、それも必要ないかもしれない。
ここが、他の分野ではなくプログラミングを選んだ所以なのかな、と思います。
まとめると、プログラミングが必修化されたのは、
- 論理的思考や問題解決能力を育てられる
- 事前に持っているべき知識がほとんどない
- 現代に不可欠なIT技術を肌で感じることができる
からだ、と思います。
どうやって教えるのか
次に、どうやって教えるのか、に焦点を当ててみましょう。
小学校では、教科を教えるのはすべて担任の先生です。情報分野を教える先生が別にいる場合もありますが、担任の先生が担当することが多いでしょう。
では、小学校の先生はプログラミングができるしょうか。
答えは、多くの場合でNoでしょう。
プログラミングは専門知識がいる
小学校の先生は、専門の教科のみを教える中高と違い、幅広くすべての教科を教えます。
小学校の先生方が大学でどの教科を専攻していたか、はバラバラなのです。
その中で、大学までにプログラミングをしたことがある、もしくは習っていたという先生は少ないでしょう。大学でプログラミングを扱う学部・学科は数限られています。
つまりほとんどの先生が、プログラミング経験がないまま子どもたちに教えなければならない、ということです。
当然、先生方も授業研究を重ねて、基礎知識を身につけられることだと思いますが、よっぽどプログラミングが好きでないと、1から10まで独学で学ぶことは難しいでしょう。
どの言語を選ぶのか
このことから考えると、小学校で扱われるプログラミングというのは、CやJava、HTMLやjavascriptといった、実際にゴリゴリとソースコードを書いて動かすものではないでしょう。
中高の情報教育では、HTMLを用いてソースコードを書いて、ブラウザで確認してみる、という内容を扱うところもありますが、やはりこれは、専門知識がある教科ごとの先生だからできることです。小学校の先生には負担が大きすぎます。
では、なにを教えるのか。私はScratchを扱う可能性が高いのでは、と思います。
Scratchは、文字を書く必要がありません。ブロック状になったコマンドを組み合わせることで、キャラクターに動きを与えることができます。
ブロックの形から、組み合わせられる命令を判断でき、シンプルな操作性のため、積み木を積むようにしてプログラミングのようなことができます。
ブラウザ上で実行できるため、インストール不要で管理もしやすいでしょう。
厳密に言えば、これがプログラミングなのか、という感じがしないこともないですが、『論理的思考を身につける』という目的は十分達成できるでしょう。
Scratchでなければならない、という理由はありませんが、ビジュアルにてプログラミングができるものが、小学校の教育では最適なのではないでしょうか。
プログラミング教育を行う効果
最後に、プログラミングを行うことによって、どのようなことが起こるのでしょうか。
プログラミングを小学校で扱うということは、プログラミングという行為に楽しさを覚え、興味を持つ子供が増えるでしょう。
小さな時に持った興味は、将来を左右する場合も多々あるため、プログラマーになりたい、という人が増えるかもしれません。
しかし、プログラミングにかけられる時間は、せいぜい2時間程度で、そのごく短期間の間に興味を持つ生徒はかなり少ないのでは、と思います。
世界的なプログラマー不足から、このプログラミング必修化で、プログラマーになる人を増やしたい、という考えがあると思いますが、実際のところどれほどの効果があるかは分かりません。
それでも、この現代にありがちな“プログラミングをする人は暗い”といった偏見めいたものが、無くなる効果はあるかもしれませんね。
最後に
余談ですが、私はプログラミング必修化が必要だと思いません。たぶん小学校でやらなくても、興味を持つ子は持つんだろうし、それは小学校で短時間プログラミングをやっても対して変わらないでしょう。
それに、先生にとってその短時間のためにかかる負担はかなり大きなものになると思います。
そこまでしてやることなのかな?というのが、私の意見です。
しかし、プログラミングを教えるために、小学校にバイトが雇われるなら、それはそれで良いのかな、とも思います。
小学校にプログラミング教えにいってみたいなー。
ということで、今回はプログラミング必修化について考えてみました。内容が固く、真剣な文章で読みにくかったと思います。すいません。
次回はもっと、技術的なことを書きたいと思います!
ではまた。
BigDecimalで誤差が出てしまった話
こんにちは、たけぼーです。
今日はJavaで正確な数値計算を行うための、BigDecimalについてです。
Androidのプログラミングをしていたら、誤差のない計算が必要になる時がありますよね。
例えば、電卓なんかを作るなら誤差が出たら大変です。
誤差が出る原因は、値をfloat,double型として計算するからです。
どうも、10進数を2進数に直して計算すると、正確に2進数に変換できないということが原因だそうです。
こんなときは、BigDecimal型という特殊な型を使って計算を行えばよいのです。
BigDecimalは、誤差を生じさせないように計算することを目的としたものだそうです。
私もBigDecimalで計算すればいいや、と思って使ったのですが・・・
まだ誤差が出る!!
おいおい、なんなんだこれは。誤差が出ないって言ったから使ったのに・・・
16×0.03(=0.48が正解)を小数点以下第2位まで切り捨て計算したところ、堂々と0.47と表示しやがる。
なんなんだ君は、という気分ですが。
どう調べても、BigDecimalでは絶対に誤差は出ません!と書いてあるので、どこが間違いなのかわかりませんでしたが、やっと解決策を見つけました。
では、解決策へ参りましょう。
BigDecimalで誤差が出ないようにする
原因は、どのようにBigDecimalの生成のときにdouble型が混ざっていたからです。
元のソースは以下のとおり。
//これでは結果が0.47となる double a = 0.03; double b = 16; ・・・ BigDecimal db_a = new BigDecimal(a); BigDecimal db_b = new BigDecimal(b); BigDecimal db_c = a.multiply(b).setScale(2,RoundingMode.FLOOR); double ans = db_c.doubleValue();
ここでの失敗の原因は
BigDecimal db_a = new BigDecimal(a);
ここです、悪の根源は。
この生成部分でカッコ内にdouble型のデータを渡していることです。
double型自体が元から誤差を含んでいるものなので、このままでは誤差が受け継がれてしまうようです。
誤差が出ないためには以下のように変更すれば良いのです。
//これで結果は0.48となる //double から Stringに変更 String a = 0.03; String b = 16; ・・・ //String型で渡される BigDecimal db_a = new BigDecimal(a); BigDecimal db_b = new BigDecimal(b); BigDecimal db_c = a.multiply(b).setScale(2,RoundingMode.FLOOR); double ans = db_c.doubleValue();
a,bをString型に変更することで、BigDecimalの生成時には文字列として渡されるので、誤差は出なくなります。
実際に計算すると、ちゃんと正確な値が出ました。
ということで、今日はここまで。
ではまた。
cocos2d-xでHelloWordがコンパイルできない
こんにちは、たけぼーです。
最近cocos2d-xに手を出し始めました。
macのXcodeを使ってコーディング中です。
今までWindowsを使っていましたが、iOSのプログラミングにはmacが必要ということで移行してきた初心者です。
Xcodeの洗礼
初めてcocosのプロジェクトを作成し、さあコンパイルしてみよう!と意気込んでいたその時!
謎のエラーに見舞われたのです・・・
HelloWorldScene.cppの70行目あたりにある
sprite->setPosition(Vec2(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
が赤く表示され、EXC_BAD_ACCESSと表示されています。
What's!? なんじゃこれ!
これがmacの洗礼なのか・・・
なんて思いながら、google先生に聞いてみました。
すると、参照している画像が上の処理を行ったときにメモリに存在しないことが原因である、ということがわかりました。
いやいや待ってくれ。一行前に追加したばかりの画像が次の行で消えているってどういうことなんだ!?
困り果てて諦めようとしていたその時、spriteの文字にカーソルを合わせると、NULLと表示されていることに気づきました。
え!?NULLじゃダメでしょ!
コンパイルエラーを治す
これによると、このプロジェクトのbuild Settingsの項目が関係しているらしい!
では、直してみましょう。
プロジェクトのトップに表示されている青マークをクリック
私の場合、プロジェクト名をTestとして作成したため、Testと表示されています。
この中のBuild Settingsをクリックすると、項目がたくさん出てきます。
この中の『All』を選択し、検索欄にmetaと入力することで、Compress PNG Files - Packagingの項目を表示させます。
この中のRemove Text Metadata From PNG Files の項目をNoにしてから再度コンパイルすると、動きました!
これなんのための設定なんだろ、わからん。
まあ、成功したからいいですよね!笑
ではまた。
firebaseのNotificationでプッシュ通知をやってみる
こんにちは、たけぼーです。
今回は、googleが無料で提供しているfirebaseのNotificationを使ってみようと奮闘しました。
きっかけは、プッシュ通知とかできたらかっこよくね?という安直なもの。
いやー、苦戦しました。
素人の私がかっこよさだけでやると大変なことになりましたよ。
ですが、今後プッシュ通知は何かと役に立つので、いい経験になったと思います。
今回参考にさせていただきましたサイトはこちら
このページを見れば、利用登録からプッシュ通知の送信まで、一気にわかります。
正直、私が新たに書く必要がない 笑
ですが、ところどころハマったポイントがあったので、そこを書こうと思います。
では、まいりましょう。
まずは、ここに書いてあるようにやっていったのですが、いざやってみますと、エラーで落ちてしまう。
なぜなんだ・・・
エラーをよーく見てみると、なにかしらのパーミッションが足りません、的なエラーが出ました。
google大先生に聞いてみると、どうもAndroidManifestに
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/>
を、足さなければならないらしいです。それ先に言ってくれよ・・・
こんなの誰も書いてなかったので、もしかしたらfirebaseと関係ないのかもしれません。
ですから、エラーが出たときだけ試してみてくださいね!
これでエラーもなく通知を受け取れるようになったわけですが、実はこれ、アプリがバックグラウンドにいるときだけなんです。
バックグラウンドならシステムが自動で通知を生成してくれるのですが、アプリが起動しているときにはまたもやエラーが出てしまいます。
これは、firebaseのメッセージを受信するserviceがアプリの中にないからで、公式のガイドにもonMessageReceivedを作成するように書かれています。
ということで、サクッと作成してみます。
もはや実用的かはわかりませんが、とりあえず通知が表示されるようになります。
package ... ; import android.app.Notification; import android.app.PendingIntent; import android.content.Intent; import android.support.v4.app.NotificationManagerCompat; import android.support.v4.content.ContextCompat; import android.support.v7.app.NotificationCompat; import com.google.firebase.messaging.FirebaseMessagingService; import com.google.firebase.messaging.RemoteMessage; import java.util.Map; public class NotificationService extends FirebaseMessagingService { @Override public void onMessageReceived(RemoteMessage remoteMessage) { NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext()); builder.setSmallIcon(R.drawable.ic_stat_create); builder.setContentTitle(getString(R.string.app_name)); builder.setContentText(remoteMessage.getNotification().getBody()); builder.setColor(ContextCompat.getColor(getBaseContext(),R.color.colorPrimary)); builder.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS); builder.setAutoCancel(true); Intent intent = new Intent(this, MainActivity.class); PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); builder.setContentIntent(contentIntent); NotificationManagerCompat manager = NotificationManagerCompat.from(getApplicationContext()); manager.notify(1, builder.build()); } }
Serviceとして認識させるため、AndroidManifest.xmlに追記しました。
<service android:name=".NotificationService"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT"/> </intent-filter> </service>
こちらを参考にさせていただきました。
qiita.com
これで、アプリが起動していてもプッシュを受け取ることができるようになりました。
最後に、システムが自動で通知を生成する場合(アプリがバックグラウンドにいる場合)通知に表示されるアイコンが真っ白になってしまいました。
これは、通知に表示されるアイコンが自動的にアプリのランチャーアイコンになるからです。
要するに、アイコンのシルエットが表示されるので、白いものが表示されるのです。
私はすでに通知用のアイコン(背景を透明にしてあるアイコン)がありますので、それを表示させたい。
こいうことで、システムに通知用アイコンを指定するため、AndroidManifest.xmlに追記しました。
<meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/ic_stat_create"/> <meta-data android:name="com.google.firebase.messaging.default_notification_color" android:resource="@color/colorPrimary"/>
これで、無事に通知を受け取ることができるようになりました!
ということで今回はここまで。ではまた。
Androidで起動時にアイコンを表示する
お久しぶりです、たけぼーです。
今日は、タイトル通り起動時にアイコンを表示させることを考えます。
例えば、LINEを起動したら、緑の背景にLINEのマークが表示され、そのあとメイン画面に切り替わりますよね。
今回はあれを自分でやってみよう!ってなわけです。
起動時に表示されるあの画面をスプラッシュ画面と言います。
実は、例の画面がスプラッシュというなんて知らなかったんです・・・
ですので、「あれ作りたいなー」と軽い気持ちで検索しても、全然出てこなかった 笑
スプラッシュ画面で検索すると一発なんですけどね 笑
検索すると、Activityを起動させてスプラッシュを表示させ、そのあとMainActivityにintentする、っていうものがたくさん出てきます。
こうすると、起動したときにスプラッシュを表示しながら、何かの処理を行うことができるようです。
例えば、初期データのダウンロードなんかを行うことができますね(たぶん)。
しかし、これでは、スプラッシュの前に一瞬ブランクが表示されるようです。
これでは少しダサい気がします。
今回の私の目的は、起動時にそのブランクが表示されるのをスプラッシュでごまかすことが目的だったりするので、この方法ではまずいんです。
ということで他の方法を探したところ、ありました。画期的な方法が(たぶん自分が知らなかっただけ)。
ということで、その画期的(?)な実装方法をメモしておきます。
実装
まず最初に、背景色を決めてcolors.xmlに記述しておきます。
colors.xml
<resources> ... <color name="colorBackground">#fafafa</color> </resources>
また、styles.xmlにスプラッシュ画面用のテーマを用意します。
以下のテーマを追記します。
styles.xml
<style name="SplashTheme" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:windowBackground">@drawable/splash</item> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style>
そして、drawable内にsplash.xmlを作成し、以下のようにします。
splash.xml
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android" android:opacity="opaque"> <item android:drawable="@color/colorBackground"/> <item android:gravity="center"> <bitmap android:src="@mipmap/ic_launcher"/> </item> </layer-list>
最後に、AndroidManifest.xmlのMainActivityの部分を以下のようにします。
<activity android:name=".MainActivity" android:theme="@style/SplashTheme"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
要するに、themaを追記するだけです。
これだけで、簡単にスプラッシュ画面が出来上がります!
とても簡単ですよね!?
注意点
最後に注意が一つ。
これでスプラッシュを作ると、MainActivityの背景がスプラッシュ画面と同じになってしまいます。
ですから、activity_main.xml内のトップレベルのところで、背景色を指定してください。
例えばこんな感じ。
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" xmlns:autofit="http://schemas.android.com/apk/res-auto" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.hoge.hoge.MainActivity" android:background="#fafafa">
これで、背景色は固定され、スプラッシュ後はいつものMainActivityが表示されます。
じつは、この背景色の指定をしていなかったため、MainActivityの背景が変な色になって困りました・・・
まあ、未熟者の私がスプラッシュに手を出したからですね 笑
今回は、こちらのページを参考にさせていただきました。
sakebook.hatenablog.com
ということで今回はここまで。ではまた。