とりあえずnull

プログラミングの勉強日記

Xcode上でiOSアプリをRunしたときの処理順序について整理してみた

実行ファイルの読み込まれる順番

  1. main.m
  2. Appdelegate.m
  3. ViewController.m(任意に作ったController)

となっている。 以下のようにNSLog()を使って確かめてみた。

// main.m
#import <UIKit/UIKit.h>
#import "AppDelegate.h"

int main(int argc, char * argv[]) {
    NSLog(@"main.m");
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

 

// AppDelegate.m
#import "AppDelegate.h"

@interface AppDelegate ()

@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    NSLog(@"AppDelegate.m");
    return YES;
}

 

// ViewController.m
#import "ViewController.h"

@interface ViewController ()
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    NSLog(@"ViewController.m");
    // Do any additional setup after loading the view, typically from a nib.
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

  実行結果

2015-04-23 12:16:01.167 processTest[24460:504513] main.m
2015-04-23 12:16:01.733 processTest[24460:504513] AppDelegate.m
2015-04-23 12:16:01.738 processTest[24460:504513] ViewController.m

以上より、main -> AppDelegate -> ViewControllerという順番に読み込まれているのがわかった。

main.mでやっていること

  • FoundationフレームワークのFoundation.hを読み込んでいる
  • AppDelegate.hを読み込んでいる
  • @autoreleasepoolメソッド処理をしている。メモリの自動解放処理っぽい。よくわかっていない

AppDelegate.mでやっていること

  • はじめてのときに呼び出したり、バックグランドになる直前に呼び出したりとアプリ起動時の節々のタイミングで行ないたい処理をまとめている。詳しくはまだわかってない

ViewController.mでやっていること

  • そのControllerにて行ないたい処理を実行する

UIパーツを配置なら避けては通れないならマスターしちまえ!CGRectの使い方とコツのまとめ

相変わらずWebのフロントばかり触っていると、捉え方が幾分違うiOSの世界に戸惑うばかりです。そんな状態ですがCGRectについて学んでみた。

位置を指定するCGRectの基本的な使い方

UIViewやUIViewのサブクラスのオブジェクトの位置を指定する時に使えるクラスであるCGRect。要するにUIパーツなどの配置を決める時に必要なやつ。座標をしてくれるってだけのクラス。引数にはx軸の開始位置, y軸の開始位置, オブジェクトの横幅, オブジェクトの縦幅の4つを指定することができる。

// (x, y) = (0, 0)からwidth100, height100のオブジェクトの形を指定
CGRect sample = CGrectMake(0, 0, 100, 100);

// UILabelにて位置とサイズを指定してみる
UILabel *nameLabel = [[UILabel alloc] init];
nameLabel.frame = CGRectMake(0, 0, 100, 100);

CGRect・CGPoint・CGSize

CGRectの他にもCGPointとCGSizeという指定用のクラスがあるっぽい。CGPointは開始位置を指定できるクラス。CGRectでいう1番目、2番目の引数にあたる部分。CGSizeはサイズを指定するクラス。CGRectでいう3番目、4番目の引数にあたる部分。というわけでCGRectはCGPointとCGSizeの両方をまとめて指定できる便利なクラスってことらしい。

参考URL: サイズ指定(CGRect CGPoint CGSize) - iPhoneアプリ開発の虎の巻

画面サイズごとに自動で横幅調整する際のチップス

iPhone4系, iPhone5系, iPhone6系で画面サイズ(ピクセル)が異なります。絶対値指定でCGRectを安易に使って配置しちゃいますとあるデバイスでは奇麗にみえても、別のサイズのデバイスでは隠れてしまう現象が起きかねません。そんな不幸を解決するには以下のような準備必要とのこと。

// 画面のフル横幅とフル縦幅を取得し、iPhone4系, iPhone5系, iPhone6系の最小公倍数で分割して単位を決める
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenRatioWidth = screenRect.size.width / 320; // 横幅の基本単位
CGFloat screenRatioHeight = screenRect.size.height / 568; // 縦幅の基本単位

例) 使い方

// 基本単位の設定
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenRatioWidth = screenRect.size.width / 320; // 横幅の基本単位
CGFloat screenRatioHeight = screenRect.size.height / 568; // 縦幅の基本単位

// 余白の設定
CGFloat padding_w = screenRatioWidth * 10; // 横余白の基本単位
CGFloat padding_h = screenRatioWidth * 10; // 縦余白の基本単位

// ラベルの基本サイズ設定
CGFloat viewLabelWidth = (self.view.frame.size.width - padding*2);
CGFloat viewLabelHeight = (self.view.frame.size.height - padding*2);

UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(padding, padding,viewLabelWidth, viewLabelHeight )];

label.backgroundColor = [UIColor redColor]; // 背景色指定
[self.view addSubview:label]; // 画面出力

出力結果:
f:id:noriven:20150408023531p:plain
ちゃんと縦横に余白が均等に作られているのが確認できるかと思います。

WebフロントのCSSなどとは考え方が違っていて指定もめんどくさいし、なんだかんだ絶対値指定を画面サイズごとに単位を変えながら余白をうまく利用して無理矢理やらわざるをえない感じがあって辛い。

地方の学生エンジニアはもっと東京に目を向けたほうが幸せになれると思う

リクルート主催のApplication Developer Festivalに参加してきました。東京だけではなく、色んな地域から集まった選りすぐりの優秀な情報系の学生さんが集まって人工知能作って競ったり、ショートコーディングしたりとにもかくにも色んなコンテンツ目白押しの中技術力を競い合う素晴らしいイベントでした。

recruit-jinji.jp

同世代の優秀なエンジニア・技術者と出会える意味と価値

こういった場に集まる学生さんって変態かよ!って突っ込みたくなるぐらい本当に優秀なのです。それを実感しました。四六時中ゲーム攻略のためにAI用のアルゴリズムを考えたり、触ったことのない技術を試して面白いものを作ったり、各々の得意領域をコラボしてまた別の、個人では到底作れなかったであろうプロダクトが作れたり、とにもかくにも柔軟性も技術力も凄まじい学生ばかりでした。そんな方々と出会えるということは、エンジニアとしての人生において、すごく大事なことだと思うわけです。もちろん乗り越えないといけない壁もたくさん出現しますし、道のりは思っていた以上に遠く感じてしまうし、下手したら自信喪失するレベルの体験をしかねないのですが、それでも同じ年代でこうも楽しく技術について語れる仲間・同士ができることの喜びはかけがえのないことだと思います。

地方の学生はもっとこういうイベントに参加したほうが幸せになれると思う

地方の学生ほど、こういった優秀な学生が集まって何かやるイベントに参加するべきだと思いました。地方にいるとどうしても自分自身が壁になってきますし、他者を見て危機感を持つ、とか自分の学習速度を気にする、なんてほぼない環境になりがちだと思います。だからこそ、こういったイベントで他の自分より優秀な学生とつながっておけば、地方に戻っても感化しあえますし、自分の学習もより有意義になるだろうし、就活や今後の人生においてもこれまで地方にいて考えるだけでは得られなかった思考の幅が出てくるのではないかなぁと思います。

獲得したいなら動ける、続けられる時代

今回のこのイベント、なんとリクルート側が交通費もホテル宿泊代も持ってくれて、学生さんは無料で東京滞在&イベント参加ができるものとなっていました。仮に費用がでなかったとしても、今はLCCもバンバン増えてますし、新幹線も新しく増えましたね。Twitterがあればイベントで知りあった学生さんとその後も連絡とれるし、就活においては選考情報とかもキャッチアップしあえますね。なにか共同でつくろうものなら、githubを通じてその後もコミットできる。地方にいて、東京に行くことへの時間や費用についてひたすら愚痴っていること自体が恥ずかしい時代となってきました。言い換えると、動いたもん勝ちってやつなのでしょうか。面白そうで勉強になりそうでガンガン自分の中に積み上げたいものを積み上げられる環境があるのであれば、活用してもっと面白いことをしていったほうが絶対楽しい。

ってことで、地方学生さん、もっと活発に動いて可能性広げよう〜っていう意識高めなイベント参加ログ。

楽しかったです。ありがとうございました。

配列の要素を逆順にする

参考書見ながら手取り足取り教えてもらってコード書くと考えるチカラ自体は付きにくいなぁと思ったので、問題だけみてゼロから書いてみることに。 するとなんということでしょう。すごい汚いコードになってしまった。ってことで、とりあえず動けばいいや精神で動作したものを載せておく。 今度、参考書の例も載せようと思います。

考え方と流れ:

  • まずは要素の詰まった配列を用意する
  • デバッグ用にとりあえず出力
  • 要素を逆順にしてあげる
  • 逆順にする際、一時保管するための変数tを用意して、上書きされた時に元の値が消えないようtに保管してあげる
  • あとは入れ替えるのみ
  • 入れ替えるときに繰り返す回数は要素数の半分だけ。でないと、さらに逆順の逆順処理が始まり元に戻ってしまうから

コード:

#include <stdio.h>
#define NUMBER 5

int main(void){
  
  int a[NUMBER];

  printf("要素に数値を入力してください。\n");
  
  for(int i = 0; i <= NUMBER; i++){
    printf("a[%d]:", i);
    scanf("%d", &a[i]);
  };

  //初期の状態で出力
  printf("入力した順に出力\n");
  for(int h = 0; h < NUMBER; h++){
    printf("a[%d]の値は%d\n", h, a[h]);
  }

  // 配列を逆順にする
  for(int j = 0; j < NUMBER/2; j++){
    int t = a[j];
    a[j] = a[NUMBER - j - 1];
    a[NUMBER - j - 1] = t;
  }

  printf("逆順にするこうなりました。\n");
  for(int k = 0; k < NUMBER; k++){
    printf("a[%d]:%d\n", k, a[k]);
  }
  
  return 0;
}

出力結果:

$ ./sample
要素に数値を入力してください。
a[0]:100
a[1]:200
a[2]:300
a[3]:400
a[4]:500
a[5]:600
入力した順に出力
a[0]の値は100
a[1]の値は200
a[2]の値は300
a[3]の値は400
a[4]の値は500
逆順にするこうなりました。
a[0]:500
a[1]:400
a[2]:300
a[3]:200
a[4]:100

メモ:

最初、要素数の分、逆順に代入処理していて意図しない結果が返ってきて戸惑った。入れ替える際は要素に対して前半分の回数だけ入れ替えてあげれば全要素が入れ替わり逆順になる、という当たり前のことに気づくのに時間がかかった。

配列を使った最大値の求め方

RubyばっかりやっているとC言語の配列の扱いがすごく厄介に感じますが、慣れだと思ってとりあえずは書いてみる。今回はconst修飾子を使うシーンがあったのでそこも勉強してみた。

考え方と流れ:

  • 準備として配列を用意し、要素に値を入力していく作業をする。
  • 次に最大値を求める処理を書く。今回は参考書に従ってmaxof関数を作り、main関数と処理を分離。
  • maxof関数内では配列の最初の要素をmaxとして仮定し、順々にmaxとその他の配列の値を比較し、現maxより大きければmaxを入れ替えるという処理を全要素の検証が終わるまで繰り返す。

コード

#include <stdio.h>

int maxof(const int a[], int n){
  int i;
  int max = a[0];

  for(i = 1; i < n; i++){
    if(a[i] > max) max = a[i];
  }
  return max;
}

int main(void){
  int i;
  int x[7];
  int nx = sizeof(x) / sizeof(x[0]);

  printf("%d個の整数を入力してください。\n", nx);
  for(i = 0; i < nx; i++){
    printf("x[%d]:", i);
    scanf("%d", &x[i]);
  }

  printf("最大値は%dです。\n", maxof(x, nx));
  return 0;
}

出力結果

$ ./sample
7個の整数を入力してください。
x[0]:10
x[1]:20
x[2]:50
x[3]:97
x[4]:100
x[5]:89
x[6]:47
最大値は100です。

メモ:

  • 配列の受け渡し C言語では配列をそのまま受け取ることはできず、配列の先頭要素のポインタを渡す、という処理になる。 なので今回のmaxof関数にて引数に設定されているint型変数nように要素数を意味する変数を用意する必要がある。 また引数にconst(定数化)をつけると配列の要素に対して変更を加えることができなくなるので、変更がない場合はconstをかけておくと便利。

左下が直角の三角形を作る

この問題の類似も含め、for文使いこなせるようになるためには必須のアルゴリズム問題な気がする。

考え方と流れ:

  • 高さを決めるために、縦に繰り返す回数を任意に決めれるようにしよう
  • 各ループで、そのループ番目と同じ数の■を出力しよう
  • ってことで、欲しい変数はfor文の初期値用変数、縦用の変数、文字出力用の変数ぐらいかな

コード:

#include <stdio.h>

int main(void){
  int i, h, j;

  printf("三角形の高さを決めてください。");
  scanf("%d", &h);

  for(i = 1; i <= h; i ++){
    for(j = 1; j <= i; j++){
      printf("■");
    };
    printf("\n");
  };
};

出力結果:

$ ./list1-1
三角形の高さを決めてください。10
■
■■
■■■
■■■■
■■■■■
■■■■■■
■■■■■■■
■■■■■■■■
■■■■■■■■■
■■■■■■■■■■

1〜nまでの和を求める

高校の数列でよくやるあれです。

考え方と流れ:

1〜nまでの合計値を求めたいので、とりあえず初期値1の変数iとこちら側が適当に決めた値を入力して保存しておく変数nを持っていると上手くいけそうな気がする。
合計値を保存する用の変数sumも用意しておこうかな。
for文でiを動かしながらsumに繰り返し代入し続け、iとnが同じになった時点で加算を止めれば求めたい動作してくれそう。

コード:

#include <stdio.h>

int main(void){
  int i, n, sum;
  sum = 0;
  printf("整数nの値を決めてください。"); scanf("%d", &n);

  for(i = 1; i <= n; i++){
    sum += i;
  };

  printf("1〜%dまでの和は%dです\n", n, sum);
  return 0;
}

出力結果:

$ ./list1-1
整数nの値を決めてください。100
1〜100までの和は5050です

$ ./list1-1
整数nの値を決めてください。30
1〜30までの和は465です