Swift転職なら=>【LevTech】
↑クリックして拡大
↑クリックして拡大
↑クリックして拡大
↑クリックして拡大

頭痛が減ったので共有です!

rebuild.fmを応援しています!

HOME > App Extensions #4

App Extensions #4(Today)

前回の記事Shareを説明していましたが、今回はTodayの実装方法を解説してみます。AppExtensionのShareでdidSelectPostの箇所のソース、上記のエラーが解決できない箇所まで進んでいました。


参考:Pro tip: Build a Today iOS 8 app extension using Xcode 6

まずは作成してみます。

Shareと同じように、New->TargetからAppExtensionのTodayを選択します。

todayサンプル0

todayサンプル1

プロジェクトに[Today]フォルダが生成されます

todayサンプル1

shareフォルダの中には、以下3つのファイルが含まれています

  • TodayViewController.swift: プログラム部分
  • MainInterface.storyboard:ビュー部分
  • Info.plist:設定部分

TodayViewController.swiftの中身はこんな感じです。見慣れないNCWidgetProvidingwidgetPerformUpdateWithCompletionHandlerが 追加されています。このあたりでイベントを取得設定できると思われます。


import UIKit
import NotificationCenter

class TodayViewController: UIViewController, NCWidgetProviding {
        
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view from its nib.
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    func widgetPerformUpdateWithCompletionHandler(completionHandler: ((NCUpdateResult) -> Void)!) {
        // Perform any setup necessary in order to update the view.

        // If an error is encountered, use NCUpdateResult.Failed
        // If there's no update required, use NCUpdateResult.NoData
        // If there's an update, use NCUpdateResult.NewData

        completionHandler(NCUpdateResult.NewData)
    }
    
}

completionHandlerで取得できるNCUpdateResultには以下の3つのパターンがあります。

  • Failed: 失敗した時場合
  • NoData:ウェジェット更新が必要ない場合
  • NewData:ウェジェット更新が必要な場合
  • RawData:生データ

参考:NCWidgetProviding

さて、プログラム側のイベントの取得はわかりましたが、どうやってビュー繋がるのかがイマイチわかりませんので、調査を続けます。

MainInterface.storyboardの中身は以下のような感じになっています。

todayサンプル3

ひとまず、サンプルを見本にプログラムからビューへ表示するコードを実行してみる

View部分とつなげる為に、IBOutletを登録します。


 import UIKit
import NotificationCenter

class TodayViewController: UIViewController, NCWidgetProviding {
    
    //IBOutletでnameLabelを追加する
    @IBOutlet weak var nameLabel: UILabel?

    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    
    func widgetPerformUpdateWithCompletionHandler(completionHandler: ((NCUpdateResult) -> Void)!) {
        //追加したnameLabelに文字をセットする
        self.nameLabel?.text = "swift-salaryman";
        completionHandler(NCUpdateResult.NewData)
    }
}

上記IBOutletを追加した状態だとStoryBoardのOutletにnameLabelが追加されますので、以下のようにnameLabelHelloWorldを関連づけてあげます。

todayサンプル4

この状態で実行すると、下のようにswift-salarymanが表示されました!

todayサンプル5

※わかりずらいですが、swift-salarymanの上に表示されている[today]が追加時に登録したToday拡張の名前になりますので可変です。

ウェジェットが表示されたタイミングで、viewDidLoadが実行されるようですので、メインのアプリで保存しているデータ等をNSUserDefault等で連携させて表示を切り替えることができれば 様々なことができそうです。コンパイルしても動作しない等のまだまだ不具合も多い新規の機能のようですので今後に期待しつつ、、、

検証(画像は追加できるのか)

読み込み部分で以下画像を追加して実行してみます。


    override func viewDidLoad() {
        
        let url = NSURL(string:"http://swift-salaryman.com/files/icon_1.gif");
        var err: NSError?;
        var imageData :NSData = NSData(contentsOfURL:url!,options: NSDataReadingOptions.DataReadingMappedIfSafe, error: &err)!;
        var img = UIImage(data:imageData);
        
        let iv:UIImageView = UIImageView(image:img);
        iv.frame = CGRectMake(0, 0, 100, 50);
        self.view.addSubview(iv);
        
        super.viewDidLoad()
    }

できました!

todayサンプル6

おまけ

Info.plist の Bundle display nameを変更すると、Widgetの名前を変更できるようです。(2014/12/17)

todayサンプル7

おまけ#2 画面左のスペースを削除する方法

todayサンプル7

デフォルトではTodayの画面左にはマージンスペースが20pxほど追加されていますが、以下の関数をTodayViewControllerに追加することで回避することができます。


    func widgetMarginInsetsForProposedMarginInsets(defaultMarginInsets: UIEdgeInsets) -> UIEdgeInsets {
        return UIEdgeInsetsZero;
    }

todayサンプル9

おまけ#3 Todayガジェットからホストアプリを立ち上げる場合

TodayガジェットからはUIApplicationのopenURLが使えないのですがextensionContextからホストアプリを起動することが可能です。以下の例は TodayガジェットからdemoAppアプリ(ホスト)を起動しています。


        self.extensionContext?.openURL(NSURL(fileURLWithPath:"demoApp://")!, completionHandler: nil)
        

さて、どうやってNSURLのURLスキームdemoAppを設定しているのでしょうか?ホストプロジェクトのTarget -> Info -> URL Types -> +(追加) -> URLスキームの入力を追加することで関連づけます。

todayサンプル10

続きをApp Extension #5に追加しました。次は[Actions]を説明しています。よかったらご確認下さい(2015/1/7)

↓こんな記事もありますよ!

NSThreadでスレッド処理を行う

タイマー処理と同様に利用できるスレッドの処理です。NSTimerではヒゲがのびたサンプルでしたので眉毛の濃くなるサンプルにしてみます。ただ、どうやらThread処理は 推奨されておらず、dispatch_queueを使用するべきのようです。

UIImage

中年サラリーマンが画像をローカルやURLやあんな所からアクセスして表示するサンプルを説明しております。

URLエンコードとデコード

サーバとデータのやりとりをしているとURLエンコードしないと文字化けしちゃったりと問題がでる場合があります。 phpのurlencodeやurldecodeと連携させる場合等、Swift側でどうやってエンコードすれば良いかの方法を記載しております
このエントリーをはてなブックマークに追加
右側のFacebookのLikeをクリック頂けると記事更新の際に通知されますので宜しければご利用下さい!