MILLEN BOX

音楽好きの組み込みソフトエンジニアによるプログラミング(主にiOSアプリ開発)の勉強の記録

Status Barの表示を消す方法 [swift2.1]

Status Barの表示をしたくないアプリが出てきましてその設定方法について。
Status Barというのは、iOS機器の画面上部に日付やバッテリー残量、電波強度などの情報を表示しているBarのことです。

Xcodeでプロジェクトファイルの中を覗いていると、「Status Bar Style」という項目に「Hide status bar」というチェックボックスがありました。
ここの部分のチェックを付けたり外したりしながら設定を弄ってみましたが効果なし(シミュレーター上)。
んん〜?と思って調べたところ、Info.plistについても弄る必要がある模様。

▶︎iOS7でステータスバーを非表示に…奮闘記\(^o^)/|杏z 学習帳

自分ポイント1

XcodeでInfo.plistファイルを選択し、View controller-based status bar appearance を追加しましょう。
設定は NO にします。

f:id:anthrgrnwrld:20151116074633p:plain

自分ポイント2

本記事の頭で説明しましたプロジェクトファイルの「Status Bar Style」→「Hide status bar」のチェックボックスを入れます。

f:id:anthrgrnwrld:20151116074823p:plain

これでStatus Barの表示がされなくなりました。

UIImageの一部を切り取る方法 [swift2.1]

UIImageの一部を切り取る方法について。

表示している写真に対し、セグメントコントロールでクリップする/しないを切り替えるアプリを作成しました。
f:id:anthrgrnwrld:20151115103321g:plain

githubは以下です。

▶︎GitHub - anthrgrnwrld/clipImage

参考にしたページは以下です。

▶︎UIImageの一部を切り抜く方法 | 目くじら日記

▶︎画像をトリミングしてUIImageViewにセットする - Qiita

▶︎SwiftでUIImageを回転、リサイズ、クリッピング、塗りつぶし - Qiita

自分ポイント1

下の記載がクリッピング用のメソッドです。
parameterとしては対象のUIImageと切り取りRectを指定し、Returnは切りとり後のUIImageとなります。

    /**
     UIImageを切り取る
     
     - parameter image:切り取り対象(UIImage)
     - parameter rect:切り取る大きさと座標位置(CGRect)
     - returns: 切り取り結果(UIImage)
    */
    func clipImage(image: UIImage?, rect: CGRect?) -> UIImage? {
        
        guard let originalImage = image else {
            return nil
        }
        
        guard let rct = rect else {
            return image
        }
        
        // ソース画像からCGImageを取り出し、指定された範囲を切り抜いたCGImageを生成
        let cripImageRef = CGImageCreateWithImageInRect(originalImage.CGImage, rct)
        
        guard let imgrf = cripImageRef else {
            return image
        }

        //生成したCGImageをUIImageとする
        let crippedImage = UIImage(CGImage: imgrf)
        
        return crippedImage
        
    }

自分ポイント2

自分ポイント1で再生した関数をセグコントロールをタップした時に呼び出します。

    /**
     Clip用のSegControlを押下した時
     */
    @IBAction func pressClipSegControl(sender: AnyObject) {
        
        var rect :CGRect?       //切り取るrect値格納用
        
        //セグコントロールとclipTypeを紐付け。そしてその値がnilになる場合(= Non Clip)には元のイメージを表示する
        let clipValues : [clipType?] = [nil, .type100x100]
        guard let clipValue = clipValues[clipSegControl.selectedSegmentIndex] else {
            setImage()
            return
        }

        //セグコントロールが.type100x100(= Clip(100x100))の時、それに従ったrectの値を入れる
        switch clipValue {
        case .type100x100:
            let origin = CGPoint(x: 100, y: 250)        //座標位置(四隅の左上)は(100,100)
            let size = CGSize(width: 100, height: 100)  //切り取りサイズは100x100
            rect = CGRect(origin: origin, size: size)   //originとsizeからrectを割り出す
        }
        
        //上で作成したrectに従って指定したUIImageを切り取る。今回きりとるUIImageはimageViewFromLibrary.image
        let clippedImage = clipImage(imageViewFromLibrary.image, rect: rect)    //clippedImageには切り取り結果が入る

        //clippedImageがnilの場合には元のイメージを表示する
        guard let clpImg = clippedImage else {
            setImage()
            return
        }
        
        //きりとったUIImageを表示する
        imageViewFromLibrary.image = clpImg
    }

clipTyeについてはenumで以下のように定義しておきます。

    enum clipType :Int {
        case type100x100
    }

注意点

今回の方法の場合、切り取り座標と切り取りサイズの指定はあくまでUIImageに対して指定してあげないといけません。
スクリーンの座標で考えると「思ってたんと違う」ということになってしまうので注意してください。

(関連記事を書きました!)

anthrgrnwrld.hatenablog.com

実行中の実機がどのRetinaのタイプか判断する方法 [swift2.1]

備忘録代わりに小ネタ記事を投稿します。

2015/11/15現在の最新iOSがサポートしている実機の解像度はNon Retina, Retina(2x), Retina(3x)の3種類存在します。

アプリが動いている実機のRetinaのタイプを知りたい時には、以下の方法で知ることができます。

let scale = UIScreen.mainScreen().scale 

上記scale内に1.0, 2.0, 3.0いずれかの数値が入ります。
そしてその値によってどのRetinaのタイプかを判断可能です。

実機の判断方法については色んな方法がありますが、今回の方法についても手段の一つとして覚えておきます。

関数の説明文を書こう Xcode7 対応版 [Xcode7.1]

また間が空きましたが久々の更新です。
ちょっとハマってしまったことがありまして間隔が空いてしまっています。
ハマるとブログに書きたいネタは増えるんだけど、ハマりの解消作業もしたい。というようなジレンマ中です。

今日もちょっと小ネタです。
以前関数の説明文についてこんな記事を書きました。

anthrgrnwrld.hatenablog.com

ルールに沿って関数ヘッダの説明文を書けば、すごくおしゃれで便利だよ〜という内容です。

で、時は流れまして、、、
本日、この記事の通りに関数の説明文を書いたんですが、option+Clickで関数の説明が思ったのと違う風になっていました。
具体的にはparameterやreturnsなどが分かれて表示されていたのが、Description内に全ての記述が記載されるようになってしまっていたのです。
ん〜??と思って調べたところ、やっぱりXcode7(Swift2?)で記述ルールに変更があったんですね。

qiita.com

自分ポイント

Xcode6までは

/**
説明

:param: a: 引数a
:param: b: 引数b
:returns: 返り値
*/

というような記載をしていました。
それがXcode7からは以下のような書き方に変更になった模様です。

/**
説明

- parameter a: 引数a
- parameter b: 引数b
- returns: 返り値
*/

また何とMarkdown記法にも対応しています!

具体的な関数を例として、以下に使用例を書いておきます。

    /**
    sizeとcenter座標の指定からorigin座標を算出する(_=rectを算出する_)関数
     
    - parameter size:算出するrectのsize
    - parameter center:算出するrectのcenter座標
    - returns: sizeとcenterから算出されたorigin座標を含めたrectを返す
    */
    func makeRectFromSizeAndCenter(size :CGSize, center :CGPoint) -> CGRect {
        
        let origin = CGPoint(x: center.x - (size.width) / 2, y: center.y - (size.height) / 2)   //sizeとcenterから座標位置を特定
        let rect = CGRectMake(origin.x, origin.y, size.width, size.height) //blurView用Rect
        
        return rect
    }

この書き方で今まで通り、関数の呼び出しの部分で option + Click すると、自分で追加した説明文が参照されるようになりました!
Markdown対応なので"=rectを算出する"の部分が斜字体になっているのもポイントです。

f:id:anthrgrnwrld:20151112075009g:plain

やっぱり説明文をちゃんと書いていると落ち着きますね。

新しいメソッドを作ったら取り敢えずすること [swift2.0] [print]

前回ぶつかった問題に関連してほぼ初めてオープンソースライブラリを使ってみています。
んん?と思うところがあっても、ブラックボックスでないので、中の動作を追えておもしろいです。
しかし本来の目的を忘れてどっぷりハマってしまうこともしばしば...。
気を付けないといけないです。

本日は新しいメソッドを作成した時に私が個人的にやっていることを残しておきます。

自分ポイント

私は新規でメソッドを作成した場合、その頭で以下のようなprintを初めに書いてしまいます。

func testFunc() {    //新規作成したメソッド
    print("\(__FUNCTION__) is called!")    //いつも書くprint文
}

__FUNCTION__という記載ですが、その時実行しているメソッド名(String型)です。 つまり上記ソースコードの場合の出力結果は以下のようになります。

testFunc is called!

これを書いておけば、空メソッドであっても、少なくとも呼び出されているということだけは確認することができます。
役に立つかどうかについて「?」の方も多いかとは思いますが、小心者の私にとってはこれだけでも大きな安心材料になってます。
ログがうるさくなればコメントアウトするだけですし。

いいところとしては、何も考えずにコレを書いとくだけで、どこで出力されたprintかが大体分かることです。
print("test001")みたいなのを複数に書いちゃうと、テスト用とはいえどこでの出力かがわからなくなってきます。

ちなみに同一メソッド内の複数箇所に記載した場合、差異は出ません。
そこの部分についても差異を確認したいという場合、\(__LINE__)というのを追加して上げて下さい。
そのprintを記載した行数が追加表示されるので、どこのprintかを一意に判別できます。

ソース

func testFunc() {    //新規作成したメソッド
    print("(\(__LINE__)) \(__FUNCTION__) is called!")    //いつも書くprint文
    print("(\(__LINE__)) \(__FUNCTION__) is called!")    //いつも書くprint文
}

出力

(29) testFunc is called!
(30) testFunc is called!

他にもswiftでは違うパターンの同様の記載方法(マクロといいます)に対応しています。
下記リンクをご参考頂ければと思います。

▶︎Swiftでデバッグ出力(日時、メソッド名、行番号) - 定食屋おろポン

以上です。ありがとうございました。

UIVisualEffectViewを使ったblur効果が環境によって動かないぞ?と思ったら [UIVisualEffectView] [UIBlurEffect]

こんにちは。AppleTVが欲しいです。
こんなん見せられたらたまらんです。

今日は前回投稿した iOS8で追加されたUIVisualEffectViewを使ったBlur効果 の続きです。
前回どのようなことをやったのかについては以下を参照して下さい。

anthrgrnwrld.hatenablog.com

作成後ぶつかった問題

シミュレーターで動作確認 → 動く
実機(iPhone6)で動作確認 → 動かない
という現象が発生しました。
こんな感じになります(イメージ)↓
f:id:anthrgrnwrld:20151030080531p:plain

はじめは実装部分を疑い、表示Viewの順番を変えたり、EffectViewの作成方法を変えたりしましたが、解決に至らず。
あたまの中は「?」マークだらけでした。

解決に至ったきっかけ

以下のページを見たことでピンときました。

http://506506.ntt.com506506.ntt.com

"It seems like UIVisualEffectView is meant for toolbars and similar, " のところ。
「あ〜そうか。アノ設定に引っ張られているのかも」と思いましたね。

現象が発生する理由

ところで私のiPhone6はiOS9にアップデートしています。 そしてアップデート後、動作が重くなった感じ、色々設定を弄っています。
この時に変更した設定 [設定→一般→アクセシビリティコントラストを上げる→透明度を下げる] をONにしたことが、今回の環境による動作差異に現れているのではと疑いました。
以下はシミュレーターでの設定箇所です↓
f:id:anthrgrnwrld:20151030081353p:plain
一旦この設定をOFFに戻し、アプリを立ち上げ直して確認してみると、 想定通りのBlur効果がかかることが確認できました。
またシミュレーターで同設定をONにした場合、Blur効果がかからないことも確認しました。

Appleの立場にたってよく考えたら「そりゃそうか」ってところなんですが、画像編集アプリを作ろうと考えていた私にとっては、なかなかいい勉強となった次第です。
画像編集アプリなどのblur効果は恐らく違う方法をとってやってるんでしょうね。
また調査しなければいけないことが増えました!

iOS8で追加されたUIVisualEffectViewを使ってBlur効果を作成する [UIVisualEffectView] [UIBlurEffect]

こんにちは。つくりたいものがもくもくもくもく出てきて困ります。

磨りガラスを通したような視覚効果が入ったアプリってありますよね。
iOS7以降、非常に多く見るエフェクトです。
これBlur効果って言います。(Girls and Boysが頭で流れた私はおっさんですね。。。
これ、iOS7時代は皆さん試行錯誤して実装されていたようなのですが、iOS8になってAppleBlur効果を実現できるAPIを公開してくれました。
それがUIVisualEffectView。
今回はUIVisualEffectViewのUIBlurEffectを使用して、blur効果を適用できる画像アプリを作成してみました。
こんな感じになります↓
f:id:anthrgrnwrld:20151029200126p:plain

Githubは以下です。前回の記事で作成したアプリをfolkして作成しました。

https://github.com/anthrgrnwrld/blurEffect/tree/da8f81c21a7d5bc65336acaf0fb89f9326379d2drEffectgithub.com

そして参考にしたページは以下です。

▶︎035 UIViewにBlurエフェクトを適用させる - Swift Docs
▶︎鯱ログ: iOS8で追加されるUIVisualEffectViewの使い方
▶︎[iOS8][Swift]UIVisualEffect (blur effect) - Qiita
▶︎[iOS 8] UIVisualEffectViewを使ってすりガラス効果を実現する | Developers.IO

では行きましょう。

自分ポイント1

先ほども書きましたが、今回のアプリは前回の記事で作成したアプリをfolkして作成しました。
そこからの続きとしてみて頂くと幸いです。
で、今回のアプリはEffectの切り替えに UISegmentedControl を使用します。
このブログでは初めて使用するパーツです。
使用するのは暫くぶりで色々忘れてました...。
以下のページで復習しました。

▶︎切り替えをする「Segmented Control」の使い方をマスター | iPhoneアプリ開発大百科

class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

    ...

    @IBOutlet weak var effectSegControl: UISegmentedControl!    //Effect選択用SegControl

    ...
    
    /*
    blur Seg ControlによってEffectを変更するメソッド
    
    :param: effectIndex:effect用Index
    */
    func onClickMySegmentedControl(effectIndex: Int){
        
        var effect : UIBlurEffect!
        
        switch effectIndex {
            
        case 0:
            print("No effect")
            
        case 1:
            // LightなBlurエフェクトを作る.
            //今から作るよ
            
        case 2:
            // ExtraLightなBlurエフェクトを作る.
            //今から作るよ
            
        case 3:
            // DarkなBlurエフェクトを作る.
            //今から作るよ

        default:
            print("Error")
        }
        
        //今から作るよ
    }

    /*
    EffectSegControlを押したら呼ばれるメソッド
    */
    @IBAction func pressEffectSegControl(sender: AnyObject) {
        
        onClickMySegmentedControl(effectSegControl.selectedSegmentIndex)    //blurEffect実行
        
    }

}

自分ポイント2

Effect適応を実行するメソッドを作成します(addVirtualEffectView)。
以下のソースでそこまで悩むようなことはないかなと思います。
このメソッド呼び出し時にUIBlurEffect型のeffectを引数として指定してあげる必要があります。

class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

    @IBOutlet weak var imageFromCameraRoll: UIImageView!        //写真表示用のUIImageView
    
    private var effectView : UIVisualEffectView!                //Effect用View
    
    ...
    
    /*
    エフェクトを適用する.
    */
    internal func addVirtualEffectView(effect : UIBlurEffect!){
        
        if effectView != nil {
            effectView.removeFromSuperview()
        }
        
        // Blurエフェクトを適用するEffectViewを作成.
        effectView = UIVisualEffectView(effect: effect)
        effectView.frame = CGRectMake(0, 0, 360, 200)
        effectView.center = imageFromCameraRoll.center
        effectView.layer.masksToBounds = true
        effectView.layer.cornerRadius = 20.0
        imageFromCameraRoll.addSubview(effectView)
    }
    
    ...

}

自分ポイント3

自分ポイント1の未実装部分が残っています。
Segmented Controlで選ばれた値によって、適応させるエフェクトを変更する部分です。
以下のソースのように実装しました。

class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

    ...

    
    /*
    blur Seg ControlによってEffectを変更するメソッド
    
    :param: effectIndex:effect用Index
    */
    func onClickMySegmentedControl(effectIndex: Int){
        
        var effect : UIBlurEffect!
        
        switch effectIndex {
            
        case 0:
            print("No effect")
            
        case 1:
            // LightなBlurエフェクトを作る.
            effect = UIBlurEffect(style: UIBlurEffectStyle.Light)    //追加
            
        case 2:
            // ExtraLightなBlurエフェクトを作る.
            effect = UIBlurEffect(style: UIBlurEffectStyle.ExtraLight)    //追加
            
            
        case 3:
            // DarkなBlurエフェクトを作る.
            effect = UIBlurEffect(style: UIBlurEffectStyle.Dark)    //追加
            
        default:
            print("Error")
        }
        
        self.addVirtualEffectView(effect)    //追加
    }

    /*
    EffectSegControlを押したら呼ばれるメソッド
    */
    @IBAction func pressEffectSegControl(sender: AnyObject) {
        
        onClickMySegmentedControl(effectSegControl.selectedSegmentIndex)    //blurEffect実行
        
    }

}

結果、以下のgifのようなアプリができました。(画像が荒いのはご了承下さい...)
f:id:anthrgrnwrld:20151029204111g:plain

細かい効果の調整ができないのは残念ですが、かなり簡単そしてお手軽にblur効果を実装できますね。
ただし、この方法、ちょっと難点がありまして...。 それについては次回更新予定です。

(追記) Githubにソースをあげていたところプルリクを頂きました。
swift2.0的にguardやdeferを使用する方法です。
この部分の説明は割愛しますが、とても見やすくなりました!
@akio0911 さん、ありがとうございます。

github.com