Javaな日々

NO JAVA, NO LIFE.

FreeBSDにApacheをインストールして起動

環境

手順

# cd /usr/ports/www/apache22
# make install clean
# vi /usr/local/etc/apache22/httpd.conf 

"2.1.5 以降の Apache では、システムが FreeBSDだと、 デフォルトでAcceptFilterが有効となってしまうようだ。"
とのことなので,この2行を追加.

AcceptFilter http none
AcceptFilter https none

Webサーバーを起動.

# apachectl start

さくらの VPS でマルチプレイ用 Minecraft サーバーを立てる

環境

手順

  1. root でログイン,不要なデーモン (マイクラサーバーを運用していく上で特に使用しないサービス) をOFFにする.
    最後に再起動して設定を反映させる.

    $ chkconfig auditd off
    $ chkconfig haldaemon off
    $ chkconfig lvm2-monitor off
    $ chkconfig mdmonitor off
    $ chkconfig messagebus off
    $ chkconfig netfs off
    $ chkconfig restorecond off
    $ chkconfig smartd off
    $ reboot

    これを実施することで CentOS 自体のメモリ使用量が 500MB 超から 100MB 程度になりました.

    $ free
                 total       used       free     shared    buffers     cached
    Mem:       1020580      97964     922616          0       6972      32868
    -/+ buffers/cache:      58124     962456
    Swap:      2097144          0    2097144

    マイクラサーバーを起動した状態でこんな感じ.

    $ free
                 total       used       free     shared    buffers     cached
    Mem:       1020580     327952     692628          0       8012      57524
    -/+ buffers/cache:     262416     758164
    Swap:      2097144          0    2097144

  2. Java をインストール.
    JDK のリンクは Oracleのサイト から入手可能です.

    $ wget http://download.oracle.com/otn-pub/java/jdk/7u9-b05/jdk-7u9-linux-x64.rpm?AuthParam=1354713154_7cab191ee6d836452cd9d23a0bc74f65
    $ mv jdk-7u9-linux-x64.rpm?AuthParam=1354713154_7cab191ee6d836452cd9d23a0bc74f65 jdk-7u9-linux-x64.rpm
    $ sudo rpm -ivh ./jdk-7u9-linux-x64.rpm

  3. screen をインストール.

    $ sudo yum install screen

  4. Minecraft Server をダウンロード.
    ホームディレクトリにマイクラサーバー用のフォルダを作成し,その中にサーバー本体をダウンロードします.

    $ cd ~
    $ mkdir minecraft
    $ cd minecraft
    $ wget https://s3.amazonaws.com/MinecraftDownload/launcher/minecraft_server.jar
    $ wget -O minecraft "http://www.minecraftwiki.net/wiki/Tutorials/Server_startup_script/Script?action=raw"
    $ chmod a+x ./minecraft

  5. Minecraft Server を起動.

    $ ./minecraft start

  6. Minecraft Server を停止.

    $ ./minecraft stop

UIAlertViewのボタンが押された時の処理

環境

手順

ViewController.h
#import <UIKit/UIKit.h>

@interface ViewController : UIViewController <UIAlertViewDelegate>

@end
ViewController.m
#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

// いろいろ省略

- (void)viewDidLoad
{
    // デリゲートをselfにセットします
    // cancelButtonTitle,otherButtonTitlesを設定
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"アラートのタイトル" message:@"アラート本文" delegate:self cancelButtonTitle:@"いいえ" otherButtonTitles:@"まあまあ", @"はい", nil];
    [alert show];
}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    switch (buttonIndex) {
        case 0:
            // 1番目のボタン「いいえ」が押されたとき
            break;
        case 1:
            // 2番目のボタン「まあまあ」が押されたとき
            break;
        case 2:
            // 3番目のボタン「はい」が押されたとき
            break;
        default:
            break;
    }
}

@end

カメラ, カメラロール, フォトアルバムから画像を選択してメール添付する

f:id:yksris:20121115183518p:image:h320

アクションシートを利用して画像をどこから(カメラ,カメラロール,フォトアルバム)選択するかというのと,選択した画像をメールに添付して送信するというのを実装してみます.

環境

手順

Interface BuilderやStoryboadにて適当にボタンを2つ作成,それぞれのIBActionをビューコントローラーのクラスのヘッダーファイルに割り当てておく.
今回はStoryboadにてボタンを2つ作成し,PhotoSelectViewControllerというUIViewControllerクラスを継承したクラスのヘッダーファイルにAction(pressedCameraButton, pressedComposeButton)を割り当てた.

PhotoSelectViewController.h
#import <UIKit/UIKit.h>

@interface PhotoSelectViewController : UIViewController <UIActionSheetDelegate>

@property (strong, nonatomic) UIImage *image;

- (IBAction)pressedCameraButton:(id)sender;
- (IBAction)pressedComposeButton:(id)sender;

@end
PhotoSelectViewController.m
#import "PhotoSelectViewController.h"
#import <MessageUI/MessageUI.h>

@interface PhotoSelectViewController ()

@end

@implementation PhotoSelectViewController

// 省略

- (IBAction)pressedCameraButton:(id)sender {
    
    UIActionSheet *sheet = [[UIActionSheet alloc]
             initWithTitle:@"送信する写真を選択"
             delegate:self
             cancelButtonTitle:@"キャンセル"
             destructiveButtonTitle:nil
             otherButtonTitles:@"フォトライブラリー", @"カメラ", @"カメラロール", nil];
    [sheet showInView:self.view];
}

- (IBAction)pressedComposeButton:(id)sender {
    
    MFMailComposeViewController *mailComposeViewController = [[MFMailComposeViewController alloc] init];
    // メールの送信・キャンセルをデリゲートで受け取るためにセット
    [mailComposeViewController setMailComposeDelegate:self];
    [mailComposeViewController setToRecipients:[NSArray arrayWithObject:@"example@example.com"]];
    [mailComposeViewController setMessageBody:@"メールの本文" isHTML:NO];
    
    // _imageのnilチェック
    if (_image){
        // 圧縮率
        CGFloat compressionQuality = 0.8;
        // UIImageJPEGRepresentationでJPEG圧縮
        NSData *attachData = UIImageJPEGRepresentation(_image, compressionQuality);
        // 圧縮した画像を添付
        [mailComposeViewController addAttachmentData:attachData
                                            mimeType:@"image/jpeg"
                                            fileName:@"image.jpg"];
    }
    
	[self presentModalViewController:mailComposeViewController animated:YES];
}

// アクションシートのデリゲートメソッド(アクションシートのボタンが押された時の処理)
- (void)actionSheet:(UIActionSheet*)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
    
    UIImagePickerControllerSourceType sourceType;
    UIImagePickerController *ipc;
    
    switch (buttonIndex) {
        case 0:
            // フォトライブラリーを表示
            sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
            if (![UIImagePickerController isSourceTypeAvailable:sourceType]) {
                UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"エラー" message:@"フォトライブラリーを表示できません" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
                [alert show];
                return;
            }
            
            ipc = [[UIImagePickerController alloc] init];
            [ipc setSourceType:sourceType];
            [ipc setDelegate:self];
            [self presentModalViewController:ipc animated:YES];
            break;
            
        case 1:
            // カメラを起動
            sourceType = UIImagePickerControllerSourceTypeCamera;
            if (![UIImagePickerController isSourceTypeAvailable:sourceType]) {
                UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"エラー" message:@"カメラを起動できません" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
                [alert show];
                return;
            }
            
            ipc = [[UIImagePickerController alloc] init];
            [ipc setSourceType:sourceType];
            [ipc setDelegate:self];
            [self presentModalViewController:ipc animated:YES];
            break;
            
        case 2:
            // カメラロールを表示
            sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
            if (![UIImagePickerController isSourceTypeAvailable:sourceType]) {
                UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"エラー" message:@"カメラロールを表示できません" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
                [alert show];
                return;
            }
            
            ipc = [[UIImagePickerController alloc] init];
            [ipc setSourceType:sourceType];
            [ipc setDelegate:self];
            [self presentModalViewController:ipc animated:YES];
            break;
            
        default:
            break;
    }
}

// アクションシートのデリゲートメソッド(画像を選択したあとの処理)
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    
    UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
    _image = image;
    
    if ([picker respondsToSelector:@selector(presentingViewController)]) {
        [[picker presentingViewController] dismissModalViewControllerAnimated:YES];
    } else {
        [[picker parentViewController] dismissModalViewControllerAnimated:YES];
    }
}

@end

Mac OS Xの“Web共有”でPHPやCGIを有効にする

環境

手順

  1. /etc/apache2/httpd.conf の以下の行のコメントアウトを外す.

    #LoadModule php5_module libexec/apache2/libphp5.so
    


  2. /etc/apache2/users/${USERNAME}.conf

    <Directory "/Users/USERNAME/Sites/">
    Options Indexes MultiViews
    AllowOverride None
    Order allow,deny
    Allow from all
    </Directory>
    

    このようになっているので,以下のように適宜書き加える.

    <Directory "/Users/USERNAME/Sites/">
    AddHandler cgi-script .cgi
    Options Indexes MultiViews Includes ExecCGI
    AllowOverride None
    Order allow,deny
    Allow from all
    </Directory>
    


  3. システム環境設定 → 共有 とたどって「Web共有」を一旦無効にして再度有効化.
    f:id:yksris:20121114224834p:plain

UICollectionViewを実装する

f:id:yksris:20121108205621p:image:h320

iOS 6から追加されたUICollectionViewという,グリッド表示の実装を容易にしたものを使ってみようと思います.iOS 6から追加されたものなので,一般向けのアプリの中で使えるようになるのはもう少し先のことでしょうかね.

今回はアプリを開いて最初に出てくるViewControllerをUICollectionViewControllerとするアプリを例として作ってみます.

環境

実装

AppDelegate.h

実装側でUICollectionViewControllerを初期画面としてセットするために,プロパティの“viewController”のクラスを“ViewController”からより汎用性の高い“UIViewController”に変更しておきます.

#import <UIKit/UIKit.h>

@class ViewController;

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) UIViewController *viewController;

@end
AppDelegate.m

UICollectionViewControllerのレイアウトを作って初期化時に渡してあげます.
(今回は“UICollectionViewFlowLayout”を利用しました)

#import "AppDelegate.h"

#import "CollectionViewController.h"

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    
    // Override point for customization after application launch.
    UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];

    // セルのサイズ
    layout.itemSize = CGSizeMake(96, 72);
    // セクションごとのヘッダーのサイズ
    layout.headerReferenceSize = CGSizeMake(0, 0);
    // セクションごとのフッターのサイズ
    layout.footerReferenceSize = CGSizeMake(0, 0);
    // 行ごとのスペースの最小値
    layout.minimumLineSpacing = 8.0;
    // アイテムごとのスペースの最小値
    layout.minimumInteritemSpacing = 8.0;
    // セクションの外枠のスペース
    layout.sectionInset = UIEdgeInsetsMake(8, 8, 8, 8);
    
    UIViewController *collectionViewController = [[CollectionViewController alloc] initWithCollectionViewLayout:layout];
    
    // 初期画面としてcollectionViewControllerをセット
    self.viewController = collectionViewController;
    
    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];
    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application {}
- (void)applicationDidEnterBackground:(UIApplication *)application {}
- (void)applicationWillEnterForeground:(UIApplication *)application {}
- (void)applicationDidBecomeActive:(UIApplication *)application {}
- (void)applicationWillTerminate:(UIApplication *)application {}

@end
CollectionViewController.h

表示するセルのアイテムを配列として宣言しておきます.
多次元配列として利用し,行をセクション数,列をアイテム数として後ほどカウントします.

#import <UIKit/UIKit.h>

@interface CollectionViewController : UICollectionViewController

@property (strong, nonatomic) NSArray *array;

@end
CollectionViewController.m
#import "CollectionViewController.h"

@interface CollectionViewController ()

@end

@implementation CollectionViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    // 画像を読み込んで配列に格納
    NSMutableArray *photo1 = [NSMutableArray array];
    
    for (int i = 1; i <= 5; i++) {
        UIImage *img = [UIImage imageNamed:[NSString stringWithFormat:@"img0%d.jpg", i]];
        [photo1 addObject:img];
    }
    
    NSMutableArray *photo2 = [NSMutableArray array];
    
    for (int i = 1; i <= 3; i++) {
        UIImage *img = [UIImage imageNamed:[NSString stringWithFormat:@"img1%d.jpg", i]];
        [photo2 addObject:img];
    }
    
    self.array = @[photo1, photo2];
    
    // collectionViewにcellのクラスを登録
    [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"CollectionViewCell"];
}

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

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
    // セクション数をカウント
    return [self.array count];
}

- (NSInteger)collectionView:(UICollectionView *)view numberOfItemsInSection:(NSInteger)section {
    // セクション内のアイテム数をカウント
    return [[self.array objectAtIndex:section] count];
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"CollectionViewCell" forIndexPath:indexPath];
    
    UIImageView *imgView = [[UIImageView alloc] initWithImage:[[self.array objectAtIndex:indexPath.section] objectAtIndex:indexPath.item]];
    imgView.frame = CGRectMake(0.0, 0.0, 96.0, 72.0);
    
    // cellにimgViewをセット
    [cell addSubview:imgView];
    
    return cell;
}


@end

第2回 AndroiderのためのiOS勉強会に参加してきました

実は今年の夏に開催された 第1回 AndroiderのためのiOS入門勉強会 も参加していたわけですが,第2回が開かれるということで参加してきました.このシリーズの勉強会では本当に濃い時間が作れてて何があっても行きたいと思いますね.