カテゴリー別アーカイブ: Xcode

【Xcode】Apple Watch用アプリのテスト(1)

【Xcode7.2 + MacOX10.11.2 + watchOS 2】
Apple Watch用アプリを試してみました。実機がないのでSimulatorで確認。

いろいろ探してみたけど、見た中ではこの記事が一番わかりやすかった。

・簡単な Apple Watch アプリを初めて作ってみる – Apple Watch アプリプログラミング –

Apple Watchアプリは、必ず親となるiPhoneアプリがあって、その子としてWatchKit App を作成するということのようです。

このサイトの通りで基本的に問題ないのだけれど、唯一違うのはwatchOSが2にバージョンアップされているので、プロジェクトエディターの追加ボタンから、Apple Watch のWatchKit App を選択するところで、選択肢が2つに増えているところ。ここでは左(watchOS 2)を選択。

WatchKit Appが、watchOS 2とwatchOS1の2種類あるある。
WatchKit Appが、watchOS2とwatchOS 1の2種類ある。無印がwatchOS2用。

もう1点、Simulatorで実行時に「”Install of Apple Watch Application never finished” 」というエラーが出たこと。これは、iPhone側のSimulatorでWatchアプリから、該当アプリの設定を開いて”Show App on Apple Watch”のスイッチを一度切ってから入れ直せばOKでした。詳しくは下記リンクで。

ios – “Install of Apple Watch Application never finished” Error when deploying watch kit app to device – Stack Overflow

これでSimulator上でApple Watchアプリの確認ができました。

【Xode】NavigationController配下にTabBarControllerを組み込む

【Xcode6.2 + iOS 8.4(iPhone5) + MacOX10.9.5】

文字通りのことをやろうと思ったんだけど、なかなかいい例がなかったのでメモ。

TabBarControllerとNavigationContorollerの組み合わせ例はいくつかあったんだけど、大抵がTabBarControllerをベースにして、子にNavigationContorollerを使うというパターン。

今回やりたかったのは、NavigationContorollerをベースにして、その配下でTabBarControllerを使うパターン。アプリの設定画面部分だけをTabBarControllerにするようなイメージです。

それから前提として「Viewは、プログラム生成ではなくStoryboardに配置する」ということ。AutoLayoutを使うことを考えると、レイアウトはStoryboard、処理はコードで分けるのがいいんじゃないかと。

Storyboardの構成はこんな感じです。
storyboard

・ViewController
・SettingViewController
・TimeSettingViewController
・SpeedSettingViewController

この4つは、それぞれ同名のカスタムクラスを作ってStoryboardで割り当てています。ViewControllerがrootControllerになっていて、ボタンタップで2つのタブ(TimeSettingViewController, SpeedSettingViewController)を持つTabBarController(SettingViewController)を呼び出す構成です。

※ちなみにTabBarControllerを配置すると自動的に接続されるSegueは削除してあります。その設定もコード上で試してみたかったので。

で、まずはUITabBarControllerの定義。どこで使うにせよ、これはAppDelegateの中に書くのが定石らしい。

【AppDelegate.h】
・Storyboardの各Viewを参照するので、その定義ファイル(.h)のimportと保存するUITabBarControllerの定義を追加する。

#import <UIKit/UIKit.h>
#import "SettingViewController.h"
#import "TimeSettingViewController.h"
#import "SpeedSettingViewController.h"

@interface AppDelegate : UIResponder <UIApplicationDelegate,UITabBarControllerDelegate>
{
    UITabBarController *myTabBarController;
}

@property (strong, nonatomic) UIWindow *window;
@property (nonatomic,strong) UITabBarController *myTabBarController;

@end

【AppDelegate.m】
・あとで参照する可能性もあるので、各タブのcontrollerも一応定義しておく。
・UITabBarController の生成は、didFinishLaunchingWithOptionsで行う。
・tabControllerの切替イベント(shouldSelectViewController, didSelectViewController)もココに定義。

#import "AppDelegate.h"

@interface AppDelegate ()

@end

@implementation AppDelegate
{
    TimeSettingViewController *TimeSettingVC;
    SpeedSettingViewController *SpeedSettingVC;
}

@synthesize myTabBarController;


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    //UITabBarControllerを生成(storyboard上のUITabBarControllerを指定)
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    myTabBarController = [storyboard instantiateViewControllerWithIdentifier:@"SettingVC"];
    
    //各タブ用UIViewControllerを生成(storyboard上のUIViewControllerを指定)
    TimeSettingVC = [storyboard instantiateViewControllerWithIdentifier:@"TimeSettingVC"];
    SpeedSettingVC = [storyboard instantiateViewControllerWithIdentifier:@"SpeedSettingVC"];
    
    //UITabBarControllerに各タブ用UIViewControllerを設定
    NSArray *controllers = [NSArray arrayWithObjects:TimeSettingVC,SpeedSettingVC, nil];
    [myTabBarController setViewControllers:controllers animated:YES];
    
    //デリゲートの設定
    myTabBarController.delegate = self;
    
    //初期表示のタブを指定
    myTabBarController.selectedViewController = myTabBarController.viewControllers[1];
    
    NSLog(@"--array: %@",myTabBarController.viewControllers);
    NSLog(@"--selectedViewController: %@",myTabBarController.selectedViewController);
    NSLog(@"--index: %d",myTabBarController.selectedIndex);

    return YES;
}

-(BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
{
     NSLog(@"--tabBarControllerを切り替えます!");
    NSLog(@"--selectedIndex: %d",tabBarController.selectedIndex);
    NSLog(@"-- vc: %@",viewController);
    
    return YES;
}

-(void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
    NSLog(@"--tabBarControllerが切り替わった!");
    NSLog(@"--selectedIndex: %d",tabBarController.selectedIndex);
    NSLog(@"-- vc: %@",viewController);
}

@end

※22行目〜28行目までは、tabBarControllerに各タブを定義する処理なので、Storyboard上でSegueが定義されている場合は不要。

ここでのポイントは、AppDelegateからStoryboardを参照するには、storyboardWithNameを使わないといけないということ。各Viewからなら、self.storyboardでいけるんだけど。

【参考】

次にtabBarContorollerを呼び出す処理を書きます。viewControllerにボタンを配置して、そこからリンクします。

【ViewController.h】
・AppDelegateをimport。
・showSettingViewはボタンタップ時の処理。

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

@interface ViewController : UIViewController

- (IBAction)showSettingView:(id)sender;

@end

【ViewController.m】
・AppDelegateを参照してtabBarControllerを取得して、pushViewControllerで表示する。

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}

- (IBAction)showSettingView:(id)sender {
    //AppDelegateを参照して、myTabBarControllerを呼び出す
    AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    [self.navigationController pushViewController:appDelegate.myTabBarController animated:YES];
}

@end

iOS View Controller カタログ(PDF)によれば・・・

Tab Barインターフェイスを作成する前に、その使い方を決定する必要があります。Tab Barインターフェイスはデータに対して支配的な構成となるため、用途は以下に限定されます。
・ウィンドウのルートView Controllerとして追加する。
・Split Viewインターフェイスの2つのView Controllerの1つとして追加する。(iPadのみ)
・別のView Controllerからモーダルモードで表示する。
・Popoverから表示する。(iPadのみ)

モーダルモードでのTab Bar Controllerの表示
(一般的ではありませんが)アプリケーションでTab Bar Controllerをモーダルモードで表示すること もできます。Tab Barインターフェイスは、通常はアプリケーションのメインウインドウにインストー ルされ、必要な場合にだけ更新されます。ただし、インターフェイスの設計において必要と認められ る場合には、Tab Bar Controllerをモーダルモードで表示することも可能です。たとえば、アプリケー ションの主たる操作モードを、Tab Barインターフェイスを使用したまったく別のモードに切り替える には、クロスフェードトランジションを使用して、第2のTab Bar Controllerをモーダルモードで表示します。
Tab Bar Controllerをモーダルモードで表示する場合は、必ずpresentModalViewController:animated: メソッドの第1パラメータにTab Bar Contrllerオブジェクトを渡します。このTab Bar Controllerは、表示する前にすでに設定されていなければなりません。したがって、Tab Barインターフェイスをメインウ インドウにインストールする場合とまったく同じ方法で、ルートView Controllerを作成して設定し、それらをTab Bar Controllerに追加する必要があります。

ということらしいので、

・TabBarControllerの定義は、AppDelegateで行う。
・表示は、別のView Controllerからモーダルモードで行う。

ということでいいようです。

【参考】
Tab Bar Controllers
Combined View Controller Interfaces
iOS View Controller カタログ(PDF/上記2つの日本語訳)
iOS View Controller プログラミングガイド(PDF)
StoryboardとSegueの基本 – Kesin’s diary
画面間でのデータの受け渡しに付いて: 永遠ログ
iOS – segue による画面遷移メモ – Qiita
日本語ドキュメント – Apple Developer
プログラム側からUITabBarControllerを切り替えて、さらに画面遷移させたい時 – makoラボ
Programming.log, [Objective-C] applicationDidFinishLaunching とは

【Xcode】UIBezierPathをアニメーションで描画

【Xcode6.2 + iOS 8.4(iPhone5) + MacOX10.9.5】

UIBezierPathはベジェ曲線を描画するクラスですが、この描画そのものをアニメーションさせられないかと調べてみました。

まずはUIBezierPathの使い方、この辺が参考になります。
[iPhone] UIBezierPath 図形の描画 (Objective-C)
[Swift] UIBezierPathを使って、直線、楕円、矩形などで描画する
UIBezierPathで曲線を描画してみた | 丸ノ内テックブログ
UIBezierPathで図形を描画する。: iPhoneソースコードがきたなくて

で、実際に書いてみたのがこちら。

iOS Simulator Screen Shot 2015.10.05 3.03.25
UIBezierPathでローディング的な円を描いてみた。

コードはこんな感じ。

・CircleView.h

//
//  CircleView.h
//  testUIBezierPath
//
//  Created by c-geru on 2015/10/04.
//  Copyright (c) 2015年 c-geru. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface CircleView : UIView

@end

・CircleView.m

//
//  CircleView.m
//  testUIBezierPath
//
//  Created by c-geru on 2015/10/04.
//  Copyright (c) 2015年 c-geru. All rights reserved.
//

#import "CircleView.h"

@implementation CircleView

// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // 円弧 -------------------------------------
    UIBezierPath* arc
    = [UIBezierPath bezierPathWithArcCenter:
       CGPointMake(self.frame.size.width/2,self.frame.size.height/2) radius:125.0f startAngle:M_PI/2*-1 endAngle:M_PI*2 clockwise:YES];
    UIColor *aColor = [UIColor lightGrayColor];
    [aColor setStroke];
    arc.lineWidth = 10;
    // 点線のパターンをセット
    CGFloat dashPattern[2] = { 2.0f, 4.0f };
    [arc setLineDash:dashPattern  count:2 phase:0];
    [arc stroke];

    // 円弧 (アニメーション)-------------------------------------
    UIBezierPath* arc2
    = [UIBezierPath bezierPathWithArcCenter:
       CGPointMake(self.frame.size.width/2,self.frame.size.height/2) radius:125.0f startAngle:M_PI/2*-1 endAngle:M_PI*4/4 clockwise:YES];

    UIColor *aColor2 = [UIColor blueColor];
    [aColor2 setStroke];

    arc2.lineWidth = 10;
    // 点線のパターンをセット
    CGFloat dashPattern2[2] = { 2.0f, 4.0f };
    [arc2 setLineDash:dashPattern2  count:2 phase:0];
    [arc2 stroke];
}
@end

で、この青い部分をローディングバー的にアニメーションしたかったわけです。

基本的にアニメーションはCALayerってことはわかったんだけど、アニメーションさせるためのパラメタの渡し方がよくわかりませんでした。

iPhone – パスに沿ってアニメーションさせる – Qiita
CALayerを使ってアニメーションしよう – make.appアプリ開発Tips

更に調べてみると、描画要素(fillColor,strokeColor,lineWidth,lineDashPattern)をUIBezierPathでなく、CALayer側に渡してあげればいいみたい。アニメーションで描画するので、考えてみれば当然か。

iOS Development Tricks: Custom Circular Progress View for iOS
CAShapeLayer example – Round corners view with dashed line border | Luka Gabric

最終的にアニメーションできたコードがコレ。

・CircleView.h

//
//  CircleView.h
//  testUIBezierPath
//
//  Created by c-geru on 2015/10/04.
//  Copyright (c) 2015年 c-geru. All rights reserved.
//

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

@interface CircleView : UIView

@end

・CircleView.m

//
//  CircleView.m
//  testUIBezierPath
//
//  Created by c-geru on 2015/10/04.
//  Copyright (c) 2015年 c-geru. All rights reserved.
//

#import "CircleView.h"

@implementation CircleView

// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // 円弧 -------------------------------------
    UIBezierPath* arc
    = [UIBezierPath bezierPathWithArcCenter:
       CGPointMake(self.frame.size.width/2,self.frame.size.height/2) radius:125.0f startAngle:M_PI/2*-1 endAngle:M_PI*2 clockwise:YES];
    UIColor *aColor = [UIColor lightGrayColor];
    [aColor setStroke];
    arc.lineWidth = 10;
    // 点線のパターンをセット
    CGFloat dashPattern[2] = { 2.0f, 4.0f };
    [arc setLineDash:dashPattern  count:2 phase:0];
    [arc stroke];

    // 円弧 (アニメーション)-------------------------------------
    UIBezierPath* arc2
    = [UIBezierPath bezierPathWithArcCenter:
       CGPointMake(self.frame.size.width/2,self.frame.size.height/2) radius:125.0f startAngle:M_PI/2*-1 endAngle:M_PI*4/4 clockwise:YES];

    if (self.pathLayer == nil)
    {
        CAShapeLayer *shapeLayer = [CAShapeLayer layer];

        shapeLayer.path = [arc2 CGPath];

        shapeLayer.fillColor = [UIColor clearColor].CGColor;
        shapeLayer.strokeColor = [UIColor blueColor].CGColor;
        shapeLayer.lineWidth = 10;

        shapeLayer.lineDashPattern = [NSArray arrayWithObjects:[NSNumber numberWithInt:2], [NSNumber numberWithInt:4], nil];

        [self.layer addSublayer:shapeLayer];
        self.pathLayer = shapeLayer;
    }

    CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    pathAnimation.duration = 3.0;
    pathAnimation.fromValue = [NSNumber numberWithFloat:0.0];
    pathAnimation.toValue = [NSNumber numberWithFloat:1.0];
    [self.pathLayer addAnimation:pathAnimation forKey:@"drawCircleAnimation"];
}
@end

【Xcode】Facebook投稿でplugin com.apple.share.Facebook.post invalidated

【Xcode6.2 + iOS 8.4(iPhone5) + MacOX10.9.5】

引き続きFacebook投稿の話です。

前回のポストに書いたようにFacebook投稿自体は出来るようになったのですが、プログラムで設定したメッセージが表示されませんでした。コードはこんな感じ。

//facebook:送信
- (IBAction)sendFB:(UIBarButtonItem *)sender {

    // 組み込みのFacebookが利用可能な端末かを検証する
    if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeFacebook]) {
        
        // Facebook投稿機能のインスタンスを作成する
        SLComposeViewController *slComposeViewController = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
        
        
        // 投稿するコンテンツを設定する
        // 表示する文字列
        [slComposeViewController setInitialText:@"#アイコン顔カメラ"];
        // URL
        [slComposeViewController addURL:[NSURL URLWithString:@"http://www.c-geru.com/"]];
        // 画像
        [slComposeViewController addImage:[UIImage imageNamed:@"icon_10.png"]];
        
        // 処理終了後に呼び出されるコールバックを指定する
        [slComposeViewController setCompletionHandler:^(SLComposeViewControllerResult result) {
            
            switch (result) {
                case SLComposeViewControllerResultDone:
                    NSLog(@"Done!!");
                    break;
                case SLComposeViewControllerResultCancelled:
                    NSLog(@"Cancel!!");
            }
        }];  
        
        // 表示する
        [self presentViewController:slComposeViewController animated:YES completion:nil];    
    }

}

で、表示される画面がコレ。「slComposeViewController setInitialText:」のテキストが表示されていません。
メッセージが表示されない

この画面でテキスト入力すると、そのテキストは投稿されますが、Xcodeに下記のようなメッセージが表示されます。

plugin com.apple.share.Facebook.post invalidated

【追記】2015.8.17 ちなみに「slComposeViewController setInitialText:」をコメントにしても、投稿後に上記メッセージが表示されます。

調べてみると、こんな情報が。

ios – UIActivityViewControllerでFacebookにシェアできない – スタック・オーバーフロー
sharing – ios plugin com.apple.share.Facebook.post do not show provided text – Stack Overflow

これによると、Facebook側のポリシー変更ということのようです。

Platform Policy 2.3 Example and Explanation

メッセージは基本ユーザに入力してもらうと考えれば、ハッシュタグつけるとか以外に困ることはなさそうですが、一応備忘録として。

【Xcode】Facebook投稿で「ログインしていません」と表示される

【Xcode6.2 + iOS 8.4(iPhone5) + MacOX10.9.5】

アプリからFacebook/twitterへの投稿は、投稿するだけなら各サービスへのアプリ登録は必要なく、Social.FrameworkをインポートしてSLComposeViewControllerを使えばカンタンに出来るらしい。

Objective-C – LINE/Facebook/Twitter投稿 – Qiita
[XCODE] iOS組み込みのFacebook投稿機能を使う方法 – YoheiM .NET
【Xcode】Facebook、TwitterにiOS標準フォームで投稿する
serviceType – SLComposeViewController Class Reference

で、試してみたところ、Facebookの方は「ログインしていません」とメッセージが出て投稿できない。

ログインしていません
表示されるアラート

iPhone側では・・・

・Facebookアプリはインストール、ログイン済。
・iPhoneの 設定>Facebook でID、パスワードは登録済み。

になっています。

いろいろテストしてみたところ、下記の手順で投稿できるようになりました。

1.Facebookアプリをログアウト。
2.iPhoneの 設定>Facebook でID、パスワードの登録を確認。
3.Facebookアプリでログイン。

Facebookアプリに最初にログインしたときに、iPhoneの 設定>Facebook でID、パスワードを登録せずに、Facebookアプリ側でログインしていたため、Xcode側からは設定情報を使ってログインされていないと判断されていたみたいです。

またFacebookアプリはログイン状態を保持しているので、iPhone上でFacebookアプリが起動されているかどうかではなく、Facebookアプリログインされた状態になっているかどうかで判断しているようです。

ブラウザ上でのFacebookページへのログイン状態は関係しないようです。まあ設定の情報を使っていないので、当たり前か。

【Objective-C】BSXPCMessage received error for message: Connection interrupted というエラーメッセージ

【Xcode6.2 + iOS 8.4(iPhone5) + MacOX10.9.5】

Xcode5でiOS7をターゲットにして作ったアプリの改修をしていて、Xcode6.2でiPhone5の実機にビルドすると「BSXPCMessage received error for message: Connection interrupted」というメッセージが出てきます。

※同じ環境で、iPhone4S(iOS 7.1.2)では発生せず。

起動時のみログにメッセージが表示されるだけで、動作そのものには影響なさそうだけど、気になるので調べてみました。

【参考】ios – BSXPCMessage received error for message: Connection interrupted – Stack Overflow

このサイトを見てみると、どうやら「iOS 8でCIFilterのバグが原因」ということらしい。

CIContextのcontextWithOptionsで指定するoptionに、iOS8以降で項目(kCIContextPriorityRequestLow, kCIContextWorkingFormat)が追加されているので、明示的にオプションを指定しないとダメということなのかな?

【参考】+ contextWithOptions: – CIContext Class Reference
【参考】Context Options – CIContext Class Reference

とりあえずこのアプリはiOS7以上になっているので、「kCIContextUseSoftwareRenderer」を指定することでエラーは消えました。

【修正前】

_imageContext = [CIContext contextWithOptions:nil];

【修正後】

NSDictionary *contextOptions = [NSDictionary dictionaryWithObjectsAndKeys:
                                    [NSNumber numberWithBool:YES],kCIContextUseSoftwareRenderer,nil];
_imageContext = [CIContext contextWithOptions:contextOptions];

※ imageContextはCIContextとして定義されています。

@property (nonatomic, strong) CIContext *imageContext;

その他、下記のサイトを参考にしました。感謝。

超できるかな(Swiftでカメラアプリ1)
Study Swift: CIFilter – Invert the photo color by built-in filter
CoreImageで画像の加工をする その3「GPUにするべきかCPUにするべきか」 – Teratoma

手持ちの環境が対応してないので確認出来ないんだけど、Xcode6.3では直っているのかしらん?

【Xcode】Audio Uint関連リンク

あるアイデアが浮かんだので、Audio Uint関連を調べてみたけど、現状まだよくわかりません。。。

リンクばかり増えてSafariがタブだらけなので、まとめておきます。

・Objective-C – iOSで特定の周波数の音を鳴らす方法 – Qiita
これはやってみた。iOS8からは一部変更されているようで、warningが全ては消えないものの、とりあえずXcode6.2で動作しました。変更点はここ(CoreAudio Changes/iOS Developer Library — Prerelease)にあるけど、イマイチ理解できず。

よさそうなのが、今や入手困難な「iPhone Core Audioプログラミング」の著者が書いたブログ。書籍のベースになった記事らしい。この順に読むのがいいらしい。途中まで読んだ。

・Getting Started With Audio Unit
・Introduction to Audio Unit Development
・iPhone Core Audio

本家Appleのドキュメント

・Audio Unit Hosting Guide for iOS

あとコレ。第10〜15回までAudio関連の話。

・実践! iPhoneアプリ開発 (10) 楽器アプリの作り方 (1) – iPhoneのオーディオフレームワーク | マイナビニュース

Core Audio関係はこの辺り。後で必要になるかもしれないので。ただ一般的な話とか、オーディオファイル再生みたいな話は、前にMusicPlayerを試作したときにある程度調査済。

・iOS CoreAudioを使う上で参考になったサイト – 日々の記録。
・iOS Core Audio | シリーズ |Developers.IO
・Core Audioの概要(PDF)
・Core Audioの復習 | Second Flush

iOSには直接関係しないけど、Web Audio API関連。

・Web Audio API を使用してウェブブラウザをギターのチューナーにする件. | hirooka.pro
・Web Audio API の Oscillator で楽器を作りたい話 – Mach3.laBlog

これも直接関係ないけど、周波数の話として。
・ギターの音程とフレット/ELECTRIC GUITAR & BASS SUPER MANUAL

今のところ、見つかったのはこんなところで。やっぱり資料的にはObjective-Cの方が潤沢。特にあまり情報のないものは。

【2015.8.3 追加】
・Audio Unit 再入門 – Over&Out その後

【Objective-C】調査中のリンクまとめ(主にカメラ周り)

いろいろ調べ物が重なって、ブラウザのタブ開きすぎなのでメモ的にまとめ。ブックマークだと埋もれてしまうので。

【UIImagePickerController. cameraOverlayView関連】
・UIImagePickerController Class Reference
・UIImagePickerControllerの使い方など | ビズリーチラボ
・[Objective-C] UIImagePickerViewController のカメラ上に自作ボタンを置く | 極上の人生

【AVCaptureSession関連】
・5分で作るiOS7風カメラアプリ | Coma’s Tech Blog
・iOS Still Image Capture Using AVCaptureSession | musical geometry
・AVCaptureDevice Class Reference
・UIImagePickerControllerを使わないカメラ機能のサンプルView(iOS4以上) – 西海岸より
・iOSのカメラ機能を使う方法まとめ【13日目】 | Developers.IO

【その他】
・UIActivityIndicatorView を使って画面中央にインジケーターを表示してみた – present

【Swift】大重さんのSwiftセミナー私的まとめ(67WS GAT銀座/2014.11.12)

今日はGAT銀座で「【無料】Xcode 6のSwiftがすごい! みんなそろってiOSアプリ開発再スタート!」というセミナーに行ってきました。講師は大重美幸さん。

話の中で一番大事だと思った言葉は「ネットにあるサンプルの多くは、iOS8やSwift1.0以前が多くて最新版だと動かないものが多い」とのこと。

以下、ざっくりまとめです。ちなみに絶賛Objective-C修行中なので、Swiftは未体験。

・Swiftは.h(ヘッダファイル),.m(実行ファイル)の二つではでなく、.swiftファイル1つで書き出される

・StoryboardはiPad画面が基本で、端末ごとのレイアウト画面はない。Autolayoutで配置し、全ての画面に対応するのが基本。
※Storyboardの画面下部、wAny hAnyと書かれた部分をクリックしてレイアウト切り替え可能。このレイアウトが新設されたSizeクラスと関係するらしい。各端末サイズをconpactWidth,conpactHeight、RegularWidth,RegularHieghtで分類するらしい。

・アシスタントエディタ>Previewで、各機種ごとのレイアウトが確認可能。

・Playground(Swift専用)
左側のように書くと、右側に変数や定数の値が表示されるインタプリタなウィンドウなんだけど、何のためにあるのかは出なかったような?(聞き逃した?)

スクリーンショット 2014-11-13 2.19.27

・変数はvarで定義できる。変数は値を設定するだけの型推論で書けるけれど、値を指定しないで定義するときには型指定が必要。
(例)var price:int

・定数はletで定義できる。定義時に値の代入が必須。
※Swiftは定数letを多用することで処理速度を上げている可能性もあるかも、とのこと。

・switch構文が大幅に変わっているらしい(breakが不要。逆に連続させる場合は、fallthroughを書くなど)
【参考】
Swiftの列挙型、switch文、網羅性チェックが素晴らしい!(リンクはセミナーで照会されたものではありません)

・タプル(Tuple)について。
【参考】構造体、列挙型、タプル(3/3):初心者のためのSwiftプログラミング入門
(リンクはセミナーで照会されたものではありません)

・レンジ演算子について。
【参考】Swift言語ガイド第2章基本演算子 – 前を向くために Part3
(リンクはセミナーで照会されたものではありません)

・Optional Valueについて。
【参考】Swift の Optional Value を便利だと思った話 – もくもくろぐ
(リンクはセミナーで照会されたものではありません)

だいたいこんな感じでした。資料は山のように用意されたようですが、15分延長も時間足らず…。是非、レジュメアップ希望します。

大重さんのSwift本(iOS8.1+Swift1.1対応)は、12月には出せるんじゃないかとのこと。

以上ざっとですが、覚えている限りのまとめです。参加された方で間違いなどあれば、ご指摘下さい。

————————————————————

大重さんの本も参考に、先日無事アプリがリリースされました。パチパチ。「アイコン顔カメラ/icon face camera」というiPhoneアプリです。無料なので是非試してみて下さい。

【Objective-C】iOSで音声認識サンプル(UIDictationController)

【Xcode5.1.1 + iOS 7.1 + MacOX10.9.5】

音声認識機能を調べていて、OpenEarsは日本語には今ひとつなので、非公式クラスらしけど、UIDictationControllerを使ってテストしてみました。

【参考】
iOS 5.1 の音声入力を使ってアプリケーションを操作してみる – 24/7 twenty-four seven
【iOS】【JPlayer】再生/停止の切り替えで音声認識をスタートして自動でストップする – The jonki

何故か1つ目のリンクのサンプルはうまく動かなくて、2つ目のリンクの方は音楽プレーヤーに組み込まれているので、音声認識だけを切り出してサンプルを作ってみました。

参考にしたリンクによれば、音声認識はキーボード経由でのみ行われ・・・

1.キーボードを表示。
2.音声入力ボタンを押す。
3.話す。
4.完了ボタンを押す。

という手順を踏んだ後、録音された音声がサーバ経由で文字列変換されて戻ってくるらしいです。

で、上記2.と4.を自動化するメソッドが、UIDictationControllerという非公開クラスに含まれています。

※キーボードは、UITextInputを紐付けた不可視のUIViewを用意して、becomeFirstResponderで表示する。
※UITextInputを使うので、必要なメソッドが定義されていないと、かなりの数のエラーがでます。警告だけど。

このサンプルでは、開始ボタンを押すと音声認識が開始(startDictation)され、timer(4.75秒)もしくは停止ボタンで音声認識が終了(stopDictation)するようになっています。画面はこんな感じ。

IMG_7121

認識率はさすがにいいです。コレ、早く公開APIにしてくれたらいろいろ使えそうなのになあ。iOS5.1からずっと非公開ってことは何かあるんですかね、問題が。

音声認識を使ったアプリのアイデアはあるんですが、OpenEarsで試してみるか、この方式で作っておいて公開APIになるまで寝かしておくか、悩みどころです。

一応、ソースをGitHubに上げてみました。初めてのGitHub(笑)。ご参考までに。