iOSアプリ開発の逆引き辞典

iPhone/iPadで使えるアプリ開発のTipsをまとめてみました

カスタムURLスキームを設定して自分自身のカスタムURLスキームを呼び出す

カスタムURLスキームを使用して他のアプリを起動する方法をいくつか紹介しました。

上記で紹介した方法は、呼び出し元アプリと呼び出し先アプリが異なるケースです。呼び出し元が呼び出し元のカスタムURLスキームを使っているケースはあまり知りません。

本記事では呼び出し元アプリ側にカスタムURLスキームを設定して、呼び出し元アプリがカスタムURLスキームを使って自分自身を呼び出す方法を紹介します。

使い道はあまりないかもしれませんが、カスタマイズ可能なAR機能を提供するAurasma SDKやグループチャット機能を提供するLobi SDK(旧称:nakamap SDK)を使用して、制御がアプリから離れてライブラリ側に持っていかれている際に、ユーザー操作によるアプリ側の振る舞いを制御することができるかもしれません。

例えば、Aurasma SDKでは、マーカーを認識するとターゲットに画像や動画を被せることができます。その被せている画像や動画(オーバーレイ・オブジェクト)をタップするとWebサイトへ遷移することができます。これはSDK側・ライブラリ側で実装されていますので、Safariを起動させるのではなく、アプリ内ブラウザ(UIWebView)で表示させたい時にアプリ側でトリガーを拾うことができません。

Info.plistの「URL Types」を追加する

URL Schemesの値をcallmyselfappに設定しておきます。

f:id:ch3cooh393:20140314172225p:plain

他のアプリからcallmyselfapp://というURLを開くことで、このアプリを起動させることができるようになりました。

カスタムURLスキームを開く

ここではサンプル的に下記のようにボタンがタップされるとカスタムURLスキームを開いています。

- (IBAction)tappedButton:(id)sender
{
    NSURL *url = [NSURL URLWithString:@"callmyselfapp://"];
    if ([[UIApplication sharedApplication] canOpenURL:url]) {
        [[UIApplication sharedApplication] openURL:url];
    }
}

カスタムURLスキームが開かれたのを受信する

カスタムURLスキームが呼ばれると、AppDelegateのapplication:openURL:sourceApplication:annotationが呼ばれます。

-(BOOL)application:(UIApplication *)application
           openURL:(NSURL *)url
 sourceApplication:(NSString *)sourceApplication
        annotation:(id)annotation
{
    return YES;
}

ここで条件によって処理を分ければ良いでしょう。

複数の画像を合成させて新しいUIImageオブジェクトを生成したい

本記事では、すでに画像(UIImageオブジェクト)が複数枚用意されていて、それらのすべての画像を合成させてみましょう。

ここでは例として「わーっ」と描かれたセリフ画像と「滑っているネコ」が描かれている画像を1つの画像として合成させてみます。

f:id:ch3cooh393:20140307185112p:plain

- (UIImage *)compositeImages:(NSArray *)array size:(CGSize)size
{
    UIImage *image = nil;
    
    // ビットマップ形式のグラフィックスコンテキストの生成
    UIGraphicsBeginImageContextWithOptions(size, 0.f, 0);
    
    // 塗りつぶす領域を決める
    CGRect rect = CGRectMake(0, 0, size.width, size.height);
    
    for (id item in array) {
        if (![item isKindOfClass:[UIImage class]]) {
            continue;
        }
        UIImage *img = item;
        [img drawInRect:rect];
    }
    
    // 現在のグラフィックスコンテキストの画像を取得する
    image = UIGraphicsGetImageFromCurrentImageContext();
    
    // 現在のグラフィックスコンテキストへの編集を終了
    // (スタックの先頭から削除する)
    UIGraphicsEndImageContext();
    
    return image;
}

呼び出し元はこんな感じ。

- (IBAction)tappedButton:(id)sender
{
    // ImageViewのサイズを取得する
    CGSize size = self.imageView.frame.size;

    // 重ねて描画したい画像の配列を作成します
    NSArray *images = @[[UIImage imageNamed:@"neko1"],
                        [UIImage imageNamed:@"neko2"]];
    
    // 合成したUIImageオブジェクトを生成する
    UIImage *image = [self compositeImages:images size:size];
    
    // 生成したUIImageオブジェクトをImageViewに設定する
    self.imageView.image = image;
}

上記のコードを実行すると下記のような画像が生成することが可能です。

f:id:ch3cooh393:20140307190102p:plain

色とサイズを指定して円が描画されたUIImageオブジェクトを生成する

本記事では、UIImageオブジェクトをプログラム(コード)だけで動的に生成する方法を紹介します。

塗りつぶされた円が描画されたUIImageオブジェクトを生成する

塗りつぶされた円を描画するにはCGContextFillEllipseInRect関数を使用します。

- (UIImage *)imageFillEllipseWithColor:(UIColor *)color size:(CGSize)size
{
    UIImage *image = nil;
    
    // ビットマップ形式のグラフィックスコンテキストの生成
    UIGraphicsBeginImageContextWithOptions(size, 0.f, 0);
    
    // 現在のグラフィックスコンテキストを取得する
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    // 塗りつぶす領域を決める
    CGRect rect = CGRectMake(0, 0, size.width, size.height);
    
    CGContextSetFillColorWithColor(context, color.CGColor);
    CGContextFillEllipseInRect(context, rect);
    
    // 現在のグラフィックスコンテキストの画像を取得する
    image = UIGraphicsGetImageFromCurrentImageContext();
    
    // 現在のグラフィックスコンテキストへの編集を終了
    // (スタックの先頭から削除する)
    UIGraphicsEndImageContext();
    
    return image;
}

上記で定義したUIImageオブジェクトを返すimageWithFillColor:size:メソッドを実行します。

- (IBAction)tappedButton:(id)sender
{
    // ImageViewのサイズを取得する
    CGSize size = self.imageView.frame.size;

    // 塗りつぶしたい色のUIColorオブジェクトを生成する
    UIColor *color = [UIColor magentaColor];
    
    // 色とサイズを指定してUIImageオブジェクトを生成する
    UIImage *image = [self imageWithFillColor:color size:size];
    
    // 生成したUIImageオブジェクトをImageViewに設定する
    self.imageView.image = image;
}

実行すると下図のようになります。

f:id:ch3cooh393:20140307184303p:plain

塗りつぶされた円が描画されたUIImageオブジェクトを生成する

(線だけの)円を描画するにはCGContextStrokeEllipseInRect関数を使用します。

- (UIImage *)imageFillEllipseWithColor:(UIColor *)color size:(CGSize)size
{
    UIImage *image = nil;
    
    // ビットマップ形式のグラフィックスコンテキストの生成
    UIGraphicsBeginImageContextWithOptions(size, 0.f, 0);
    
    // 現在のグラフィックスコンテキストを取得する
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    // 塗りつぶす領域を決める
    CGRect rect = CGRectMake(0, 0, size.width, size.height);
    
    CGContextSetStrokeColorWithColor(context, color.CGColor);
    CGContextStrokeEllipseInRect(context, rect);
    
    // 現在のグラフィックスコンテキストの画像を取得する
    image = UIGraphicsGetImageFromCurrentImageContext();
    
    // 現在のグラフィックスコンテキストへの編集を終了
    // (スタックの先頭から削除する)
    UIGraphicsEndImageContext();
    
    return image;
}

上記で定義したUIImageオブジェクトを返すimageWithFillColor:size:メソッドを実行します。

- (IBAction)tappedButton:(id)sender
{
    // ImageViewのサイズを取得する
    CGSize size = self.imageView.frame.size;

    // 塗りつぶしたい色のUIColorオブジェクトを生成する
    UIColor *color = [UIColor magentaColor];
    
    // 色とサイズを指定してUIImageオブジェクトを生成する
    UIImage *image = [self imageWithFillColor:color size:size];
    
    // 生成したUIImageオブジェクトをImageViewに設定する
    self.imageView.image = image;
}

実行すると下図のようになります。

f:id:ch3cooh393:20140307184616p:plain

色とサイズを指定して1色で塗りつぶされたUIImageオブジェクトを生成する

本記事では、UIImageオブジェクトをプログラム(コード)だけで動的に生成する方法を紹介します。

- (UIImage *)imageWithFillColor:(UIColor *)color size:(CGSize)size
{
    UIImage *image = nil;
    
    // ビットマップ形式のグラフィックスコンテキストの生成
    UIGraphicsBeginImageContextWithOptions(size, 1.f, 0);
    
    // 現在のグラフィックスコンテキストを取得する
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    // 塗りつぶす領域を決める
    CGRect rect = CGRectMake(0, 0, size.width, size.height);
    
    CGContextSetFillColorWithColor(context, color.CGColor);
    CGContextFillRect(context, rect);
    
    // 現在のグラフィックスコンテキストの画像を取得する
    image = UIGraphicsGetImageFromCurrentImageContext();
    
    // 現在のグラフィックスコンテキストへの編集を終了
    // (スタックの先頭から削除する)
    UIGraphicsEndImageContext();
    
    return image;
}

上記で定義したUIImageオブジェクトを返すimageWithFillColor:size:メソッドを実行します。

- (IBAction)tappedButton:(id)sender
{
    // ImageViewのサイズを取得する
    CGSize size = self.imageView.frame.size;

    // 塗りつぶしたい色のUIColorオブジェクトを生成する
    UIColor *color = [UIColor magentaColor];
    
    // 色とサイズを指定してUIImageオブジェクトを生成する
    UIImage *image = [self imageWithFillColor:color size:size];
    
    // 生成したUIImageオブジェクトをImageViewに設定する
    self.imageView.image = image;
}

実行すると下図のようになります。

f:id:ch3cooh393:20140307182146p:plain