プログラミングと音楽とアニメとiPhoneとiPadとMacとAndroidとLogicとギターとテニスと車

アプリ開発系の勉強メモやTipsなどを中心に他いろいろと書いていきます。

SSZipArchiveでパスワード付きzipファイルを扱う

iOSアプリ開発でパスワード付きのzipファイルを扱う機会があったので、
SSZipArchiveというライブラリが便利そうだったので、扱い方のメモになります。

  1. SSZipArchiveのライブラリをダウンロード
  2. ダウンロードしたライブラリをプロジェクトに追加
  3. libz.dylibを追加
  4. パスワード付きzipファイルの用意
  5. 実装の解説
  6. サンプルコード

1. SSZipArchiveのライブラリをダウンロード
GitHub - ZipArchive/ZipArchive: ZipArchive is a simple utility class for zipping and unzipping files on iOS and Mac.

2. ダウンロードしたライブラリ内のSSZipArchiveフォルダごとプロジェクトに追加
f:id:travitu:20141222234552p:plain
f:id:travitu:20141222234557p:plain
f:id:travitu:20141222235153p:plain

3. プロジェクトのTARGETS>Build Phases>Link Binary With Libraries でlibz.dylibを追加
f:id:travitu:20141222234608p:plain
f:id:travitu:20141222234609p:plain

4. パスワード付きzipファイルの用意
ここではテストでphoto1.zipというzipファイルを用意しました。
中身はphoto1.jpgという画像ファイルです。
このzipファイルをプロジェクトに追加しておきます。
f:id:travitu:20141222235842p:plain

photo1.jpg→photo1.zipへのパスワード付きzip圧縮は、Macのターミナルで以下のコマンドで行いました。
$ zip -e -r photo1.zip photo1.jpg

5. 実装
#import "SSZipArchive.h"を記述して実装していきます。

パスワード付きzipを解凍するSSZipArchiveのメソッド

// Unzip
+ (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination overwrite:(BOOL)overwrite password:(NSString *)password error:(NSError **)error delegate:(id<SSZipArchiveDelegate>)delegate;

この他にも、SSZipArchive.hでいくつかメソッドが宣言されていますが、今回はこれを利用しました。
引数の種類はこんな感じです
unzipFileAtPath: プロジェクトに追加したzipファイルのパスの文字列
toDestination: 解凍したzipの中身を展開する場所のパスの文字列
overwrite: 上書きを許可するかどうかのBOOL値
password: zipのパスワードの文字列
error: エラー参照の設定
delegate: デリゲートの設定

デリゲートを設定しておけば、zip解凍の処理が完了した時に以下のメソッドが呼ばれるので、ここでzipの中身のファイルを読み込んで利用する処理を実装します。

- (void)zipArchiveDidUnzipArchiveAtPath:(NSString *)path zipInfo:(unz_global_info)zipInfo unzippedPath:(NSString *)unzippedPath


6. サンプルコード
例として、ViewController.m内に実装してみました。

#import "ViewController.h"
#import "SSZipArchive.h"

@interface ViewController () <SSZipArchiveDelegate>

@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // パスワード付きzipを解凍する
    NSString *zipFilePath = [[NSBundle mainBundle] pathForResource:@"photo1" ofType:@"zip"];
    NSString *destinationPath = NSTemporaryDirectory();
    NSString *password = @"12345";
    NSError *error = nil;
    [SSZipArchive unzipFileAtPath:zipFilePath
                    toDestination:destinationPath
                        overwrite:YES
                         password:password
                            error:&error
                         delegate:self];
    if (error) {
        // エラーが発生した場合
        NSLog(@"error:%@", error);
    }

}

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

#pragma mark - SSZipArchiveDelegate
- (void)zipArchiveDidUnzipArchiveAtPath:(NSString *)path zipInfo:(unz_global_info)zipInfo unzippedPath:(NSString *)unzippedPath {

    // 解凍したzipファイルから画像ファイルを読み込んでUIImageViewに設定する
    NSString *filePath = [NSString stringWithFormat:@"%@/photo1.jpg",unzippedPath];
    NSData *photoData = [NSData dataWithContentsOfFile:filePath];
    self.imageView.image = [UIImage imageWithData:photoData scale:[[UIScreen mainScreen] scale]];
}

今回のサンプルコード
GitHub - travitu/ZipArchiveSample

Xcode5と6を共存させて利用する方法のメモ

1、AppStoreで既存のXcodeのアップデートを行う
現在の最新版Xcode6.0.1にアップデートされます。

2、iOS Dev Centerで旧バージョンのXcodeをダウンロードする
一覧から利用したいバージョンをダウンロードします。
今回はXcode5.1.1を選びました。

f:id:travitu:20140921134941p:plain

f:id:travitu:20140921134955p:plain

3、2でダウンロードしたXcodeをインストール
この時に「両方とも残す」を選択します。

4、3でインストールしたXcodeのファイル名を分かりやすいように変更する(任意)

Cocos2d-x v3.2のAndroid NDK対応バージョンについて

Cocos2d-x v3.2の正式版がリリースされたので、Androidの開発環境もついでにアップデートしようと思い、EclipseAndroid SDKAndroid NDKの最新版を入れてみました。
その過程で、Android NDKのバージョンがここ
Android NDK | Android Developers
にあるのですが、どのバージョンがよいか少し迷ったのでメモを。

Mac OS X 64bit環境では、「android-ndk64-r10-darwin-x86_64.tar.bz2」というNDKが最新版になりますが、調べてみると、Cocos2d-xのv3.2の方がまだこのNDKは推奨しておらず、NDK r9dを使ってくださいとの事です。

参考
http://www.cocos2d-x.org/news
このページの「Compiling and linking error when using NDK r10 to build cocos2d-x v3.2」というタイトル部分あたりに説明があります。

ndk-r9dのダウンロードリンク
Mac
http://dl.google.com/android/ndk/android-ndk-r9d-darwin-x86_64.tar.bz2
Windows
http://dl.google.com/android/ndk/android-ndk-r9d-windows-x86_64.zip

USB端子&オーディオインターフェース搭載のFender製ギターが発売されました♪

DELUXE STRATOCASTER® HSS PLUS TOP WITH IOS CONNECTIVITY
http://www.fender.jp/topics/news/001732.php

iPhoneiPadなどのiOSデバイスとUSBで接続して様々なアプリを通して音が出せるようです。
オーディオインターフェースもあるのでDTMでも使えそうです。
ギター本体はハイエンドなモデルではなさそうなので、鳴りやバランスとか気になります。
本体のボディー材はアルダー?でしょうか。

音のデモみたいなのがないかYouTubeで探したらありました。
https://www.youtube.com/watch?v=N77rNvP2Pas
これではちょっと分かりにくいですが、やはり音が気になるので
近くの楽器店に入荷したら試奏してこうようかと思います。

Appleの新言語Swiftの「先取り!Swift」という電子書籍が発売されています

今日Amazonで発見したので早速購入してみました!
まだざっとしか見てませんが、丁寧な解説で読みやすそうです。

先取り!Swift

先取り!Swift

xib(Nibファイル)からUIViewを生成するカテゴリのライブラリを公開しました

UIView-LoadNib

https://github.com/travitu/UIView-LoadNib

現在制作中のアプリでレイアウトやデザインが少し異なる複数のUIViewを用意して、
ViewController上でそれらのUIViewを切り替えて表示したい所があったので、
コードで同じようなUIViewを書くより、xibで作った方がすぐ見分けがつけやすいと思い、簡易的ですが、カテゴリのライブラリを作りました。

【使い方】

ライブラリをダウンロードして、以下の2つのファイルを含んだ UIView+LoadNibフォルダごとプロジェクトに追加します。

  • UIView+LoadNib.h
  • UIView+LoadNib.m

そしてUIViewを作ります。この時xibも追加します。
デモでは、以下のファイル名にしています。

  • MyCustomView.h
  • MyCustomView.m
  • MyCustomView.xib

MyCustomViewクラスに必要な実装を行います。
実装内容については後で説明します。
f:id:travitu:20140618003152p:plain

MyCustomView.xibを表示して、File's Ownerを選択し、
Custom Classに先ほど作成したMyCustomViewを指定します。
デモでは分かり易いようにUIView上にラベルを追加しています。
f:id:travitu:20140618003231p:plain

Main.storyboardでUIViewを新しく追加し、位置やサイズなどを適宜合わせます。
f:id:travitu:20140618003334p:plain

追加したUIViewのCustom ClassにMyCustomViewを指定します。
f:id:travitu:20140618003343p:plain

以下、ライブラリのコードと実装するコードの解説です。

UIView+LoadNib.h

#import <UIKit/UIKit.h>

@interface UIView (LoadNib)
// xibからUIViewを生成するメソッド(引数有りと無しの2種類)
- (UIView *)tra_loadViewFromNibNamed:(NSString *)nibName;
- (UIView *)tra_loadViewFromNib;
@end

UIView+LoadNib.m

#import "UIView+LoadNib.h"

@implementation UIView (LoadNib)
- (UIView *)tra_loadViewFromNibNamed:(NSString *)nibName
{
    UIView *view = [[[NSBundle mainBundle] loadNibNamed:nibName owner:self options:nil] objectAtIndex:0];
    view.frame = self.bounds;
    // translatesAutoresizingMaskIntoConstraintsはデフォルトではYESになっています。
    // もしAutoLayoutの制約をコードで書く場合はNOにします。
    view.translatesAutoresizingMaskIntoConstraints = YES;
    return view;
}

- (UIView *)tra_loadViewFromNib
{
    NSString *nibName = NSStringFromClass([self class]);
    UIView *view = [self tra_loadViewFromNibNamed:nibName];
    return view;
}
@end

MyCustomView.h

#import <UIKit/UIKit.h>

@interface MyCustomView : UIView

@end

MyCustomView.m

#import "MyCustomView.h"
#import "UIView+LoadNib.h"

@implementation MyCustomView

// Interface BuilderからこのViewを生成するためのメソッドです。
- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if (self) {
        [self customViewInit];
    }
    return self;
}

// コードからこのViewを生成するためのメソッドです。
- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self customViewInit];
    }
    return self;
}

- (void)customViewInit
{
    // UIView+LoadNibのメソッドを使用してxibからUIViewを生成します。    
    UIView *view = [self tra_loadViewFromNibNamed:@"MyCustomView"];
    [self addSubview:view];
}

@end

あとはビルドすれば下記のようにMyCustomViewが表示できます。
f:id:travitu:20140618003354p:plain

【補足】

今回はxibでUIViewを生成する目的だったので、デモではinitWithCoder:を使いましたが、
コードでUIViewを生成する場合はinitWithFrame:を使います。

UIView+LoadNib.mにtranslatesAutoresizingMaskIntoConstraintsを書きましたが、
このプロパティはデフォルトではYESとなっています。もしAutoLayoutの制約をコードで書く場合などは
NOにする必要があり、詳しくは以下のドキュメントに載っています。
https://developer.apple.com/jp/devcenter/ios/library/documentation/AutolayoutPG.pdf


以上、ひとまず作りましたが、このカテゴリのメソッドを使うUIView側の実装の仕方や、
カテゴリ側でインスタンス変数が持てるようにしたり、エラー処理など配慮が足りない部分を改良していく予定です。

【勉強会】これでわかる!ヒットアプリを作るための企画、UI、マネタイズ!

標題の勉強会がappC cloud主催で今月あるみたいで、
申し込みしようとアクセスしたら、今日の時点ではまだページが無かったです。

日時:2014/6/25 wed 19:00〜21:30
場所:ニフティ株式会社セミナールーム
申し込みURL:http://peatix.com/event/40286