2016年7月28日木曜日

Automatic Preferred Max Layout Width before iOS 8.0のWarningを消す

iOS7以前に作り始めたアプリを久しぶりに直そうとしたら、
Automatic Preferred Max Layout Width before iOS 8.0
というWarningが出た。
これは

  • UILabelでLinesが2以上
  • AutoLayoutを使用
  • iOS7以前をサポートしている
という場合に出るようだ。
UILabelは中に表示するLabel.textの内容次第である程度幅を変えてくれるわけだが、AutoLayoutがいろいろ厳密になってるために、横幅の最大値のWidthを設定して欲しいと言っているようだ。

Warningを消すには、当該のUILabelを探し、SizeインスペクタのPreferred Widthに値を入れるか、横のExplicitにチェックを入れて現在のサイズを適用してやればいい。

ただ、Labelがいっぱいあってもどのラベルが対象なのかXcode様は教えてくれない。
そういう時は裏技。
  1. 左端のプロジェクトナビゲータのStoryboardを右クリック
  2. Open As でSource Codeを指定
  3. Storyboardの実態のXMLの中身が開く
  4. 「numberOfLines」で検索
  5. 部品がLabelで値が2以上のものを探す
  6. そこのID("R1P-1c-DQj"みたいなの)をFindナビゲータで検索
StoryboardのXMLを表示

Linesが2以上のLabelのIDを検索

#importの記述を簡略化(@importで書く)

Objective-Cのヘッダファイルで、例えば
#import <GoogleMobileAds/GoogleMobileAds.h>
などと長々と書いていたものが、最近では
@import GoogleMobileAds;
などと短く書けるようになったようだ。

Xcode5あたりからはデフォルトで書けるようだが、それ以前に作ったプロジェクトでは設定がONになってないので、もし新しい方で書きたい場合は設定をONにしてやる必要がある。

場所はプロジェクト名のBuild SettingsのApple LLVM 7.1 - Language - Modulesの中の、Enable Modules (C and Objective-C)だ。
これをNoからYesに。
Yesにしたところで、古い書き方も書けるのでそんなに問題はないと思うけど、新しい書き方だけで説明されてるとわからないよね。

参考サイト:frameworkのimportを簡略化する(@importについて)

2016年7月19日火曜日

iPhoneやiPadにしゃべらせる!

iPhoneやiPadに簡単にしゃべらせることができる。

AVFoundationをimportし、(最近はプロジェクトのGeneralのところでFrameworkをAddしなくてもいいんだっけ?)
import AVFoundation
(ちなみに入力途中に表示されたAVFoundationという候補が赤線引かれてた。なんでだ?)

以下のコードでしゃべってくれる。超簡単♪

//テキスト読み上げ
let speech = AVSpeechSynthesizer()
let utterance = AVSpeechUtterance(string: "わたしはうちゅうじんをみた!")
utterance.voice = AVSpeechSynthesisVoice(language: "ja-JP")
utterance.rate = 0.5 //速度 0.0 ~ 1.0 デフォルト0.5
utterance.pitchMultiplier = 0.3 //声の高さ デフォルト1.0
speech.speakUtterance(utterance)

utteranceってのは「言葉」とか「発言」とかいう意味の単語。
他にも前後のdelayやvolumeのプロパティ、発音のタイミングなどを管理するAVSpeechSynthesizerDelegateもある。
詳しくは公式のこの辺で。

うちの環境でデフォルトの声は女性だった。
声そのものを変更する方法はまだよくわかんないが、picthMultiplierの値を変えるとかなり印象変わるよ。
Siriの声は男性と女性と2種類あるけど、その設定を変更してもこちらの声が変更されることはなかった。
ただ、たとえば AVSpeechSynthesisVoice(language: "en-US"とかに変えると英語の音声になるよ。(アメリカ英語の場合。イギリス英語は"en-GB")
日本語のテキストは読んでくれないんで、アルファベットで書かないといけないけど。

読み上げるテキストの設定はインスタンスを作る時にしか設定できないようなので、何回も使う場合は関数にしといたほうがいい。
インスタンスを複数作っても、重ねて同時読み上げっていうのはできないようだ。(できると書かれたページもあったが、間違いではないのか?)

2016年7月12日火曜日

実行中のファイル名、関数名、コードの行数を得る

実行中のファイル名、関数名、ソースコード上の行数(何行目を実行してるか)を得ることができる。
それぞれ
#file
#function
#line
で取得することができる。
元々は__FILE__、__FUNCTION__、__LINE__だったのがSwift3から廃止になるんで、#〜に書き換えろってさ。

使い方としてはこんな感じ。
print("\(#file) \(#function) \(#line)")

/Users/xxxxx/Dropbox/Develop/Swift開発/CoreImageStudy/CoreImageStudy/ViewController.swift colorFunc 165 
こんな感じで表示される。
#lineは数値なので、String化したければ#line.descriptionも使える。

2016年7月7日木曜日

CoreImage Filterの種類

iOS9、OS X 10.11現在のフィルター一覧。
元情報はアップルのフィルタリファレンス
よくわからないのや、言葉で言い表しにくいのもあるが、いろいろOSで用意してるのだな。

CICategoryBlur

ブラー(ぼかし)関係

CICategoryColorAdjustment

色調関係の変更

CICategoryColorEffect

カラーエフェクト

CICategoryCompositeOperation

Photoshopのレイヤーの合成にある合成処理がだいたいあるみたい。

CICategoryDistortionEffect

PhotoBoothとかで使われてる感じのエフェクト
  • CIBumpDistortion
    • 凹凸エフェクト
  • CIBumpDistortionLinear
    • びろーんって伸びる
  • CICircleSplashDistortion
    • 光のトンネル。中央を残して周辺が放射状にびろーん
  • CICircularWrap
    • 二次元的に円形に曲げる。(文字の変形とかでよくあるやつ)
  • CIDroste
    • 合わせ鏡のような
  • CIDisplacementDistortion
    • 2枚を合成して複雑な画像に(グレースケール?)
  • CIGlassDistortion
    • ガラス窓エフェクト
      • こんな感じのテクスチャー画像が必要なことまではわかった。(参考サイト)ただ、自分でPhotoshopのフィルターで似たような画像を作って試してみても、なかなかきれいなエフェクトがかからない。できるだけランダムで均一にばらけた画像がいいんじゃないかとは思うのだが…。
  • CIGlassLozenge
    • 菱形ガラス窓?(中央に形に沿った歪みを?)
  • CIHoleDistortion
    • ブラックホールみたいのを表示
  • CILightTunnel
    • PhotoBoothでの「光のトンネル」。中心を残して、周囲を伸ばしてトンネル状に見せたり、らせん状にぐるぐる歪める
  • CIPinchDistortion
    • つまんだような歪み
  • CIStretchCrop
    • 縦横にストレッチし、クロップも
  • CITorusLensDistortion
    • 丸いレンズ状の歪み
  • CITwirlDistortion
    • 渦巻き?
  • CIVortexDistortion
    • 渦巻き

CICategoryGenerator

バーコードやQRコード、画像パターンを作る

CICategoryGeometryAdjustment

画像の傾きやサイズ、回転など?

CICategoryGradient

グラデーション関係

CICategoryHalftoneEffect

パターン作成
  • CICircularScreen
    • 同心円状のパターン作成
  • CICMYKHalftone
    • 画像を、CMYKの印刷網掛けしたような画像に変換
  • CIDotScreen
    • スクリーントーンのような網掛けパターン作成
  • CIHatchedScreen
    • もっと細かいスクリーントーンのような網掛け作成
  • CILineScreen
    • 直線のスクリーントーンのような網掛け作成

CICategoryReduction

画像解析関係?

CICategorySharpen

シャープ処理

CICategoryStylize

Photoshopなどにあるようなフィルターの一部

CICategoryTileEffect

タイルパターンを作る処理

CICategoryTransition

トランジション(場面転換)処理いろいろ

CoreImageの使い方基礎

CoreImageの機能と概要

  • フィルタ(リファレンスにリンク)
    • ぼかしとか、画像にかけるエフェクト
  • フィルタグラフ
    • フィルタの組み合わせで複雑なエフェクトを実現(?)
  • プラグインアーキテクチャ
    • システム提供のフィルタと、ユーザー自作フィルタを組み合わせて機能を拡張できる
  • ほとんどのハードウェア上で動作するように書かれてる
  • 必要とされる時までできるだけ実行を遅らせるので、メモリ確保が直前とかがある
  • コンテキスト( context)というオブジェクトが必要
    • 必要なメモリ割当、フィルタのカーネルをコンパイルして実行など、いろいろ使えるらしい
  • 座標は左下が0,0で、右上に行くに従って増える。SpriteKitなんかと一緒で、UIImageとは上下が逆になる。

フィルタのかけ方

  1. フィルタの作成と設定
  2. ソースイメージをフィルタに渡す
  3. フィルタ処理した画像を得る
コードは以下。
思ったよりも難しくないね。フィルタ名とパラメータの扱いがわかればどんどんいけそう?

//元画像作成
let uiInputImage = UIImage(named: "イメージ名") //UIImage作成
let ciInputImage = CIImage(image: uiInputImage!) //CIImageに変換
        
//*******フィルタの作成と設定(例:モノクロフィルタ)*******
let filter = CIFilter(name: "CIColorMonochrome"//フィルタ作成
filter!.setValue(image, forKey: kCIInputImageKey) //フィルタに画像渡す
filter?.setValue(CIColor(red: 1.0, green: 1.0, blue: 0), forKey: kCIInputColorKey) //フィルタパラメータ設定
filter?.setValue(1.0, forKey: kCIInputIntensityKey) //フィルタパラメータ設定

//フィルタ処理した画像を得る
//******CIContext作成*******
//これ使って一度CGImageに直した方がいろいろいいらしい
let ciContext = CIContext(options: nil) //nilで作成
let cgImage = ciContext.createCGImage((vignetteFilter?.outputImage)!, fromRect: ciInputImage!.extent)
//最後のextentってのはUIImageでいうboundsみたいな値らしい?
        
//*******CGImageからUIImageに変換******
let uiImage = UIImage(CGImage: cgImage) //UIImageに変換
myImageView.image = uiImage

フィルタ処理後のイメージを得る

monochromeFilter!.outputImage
でCIImageが得られるので、それをUIImageに再変換して表示したり、そのまま次のフィルタ処理に回したりする。

Context使ったほうがいいらしい

直接CIImageをUIImageに変換した場合、UIImageに設定してたものが無視されたりするんだそうな。
それを回避するため、一度CIContextを使ってCGImageに変換してからのほうがいいんだそうな。

パラメータはkeyを使って設定

フィルタの設定はkeyによってどのパラメータをいじるかを指定するわけだが、多くのkeyに対してはkCIで始まるStringが定義されているので、それを使えばいいし、定義されていないKeyがあれば" "で囲んだStringで指定してやればいい。
  • 以下はどちらでも可
    • monochromeFilter?.setValue(1.0, forKey: kCIInputIntensityKey)
    • monochromeFilter?.setValue(1.0, forKey: "InputIntensityKey")
数値は厳密にはNSNumberの値なのだが、そのまま直接数値を指定する分には問題なさそう。
乱数とか、事前に計算の要素を入れた場合は、以下のように型に気をつけないといけない。
    let scale = NSNumber(double: Double(arc4random() % 40) / 10) //0〜4までの整数値
    filter?.setValue(scale, forKey: kCIInputScaleKey)

    フィルタ作成時にパラメータを一度に並べて指定することもできる
    let monochromeFilter = CIFilter(name: "CIColorMonochrome",
                           withInputParameters:
                           ["inputColor" : sepiaColor,
                            "inputIntensity" : 1.0])

    座標は元画像の大きさを、CIVectorで指定

    パラメータで座標を指定する場合があるが、その場合は最終的に表示されるUIImageの大きさを基準にするのでなく、元画像の大きさで指定する。
    出力先が640x480のサイズでも、オリジナル画像が1000x500だったら、中心部分を指定するには500,250の位置を指定する。
    sourceImage.size.widthと.heightを使って求められるわな。

    指定時はCIVector(x, y)でやらないといけない。
    filter?.setValue(CIVector(x: centerX, y: centerY), forKey: kCIInputCenterKey)

    2016年7月1日金曜日

    All interface orientations must be supported〜とか出る

    以前リリースしたアプリをアップデートしようとしたら、以下の2つのWarningが出てしまった。

    warning: All interface orientations must be supported unless the app requires full screen.
    warning: A launch storyboard or xib must be provided unless the app requires full screen.

    ネット翻訳したら、
    アプリがフルスクリーンを必要としない限り、すべてのインターフェースの向きがサポートされなければなりません。
    アプリがフルスクリーンを必要としない限り、ラウンチストーリーボードまたはxibは提供されなければなりません。

    だそうだ。よくわからん。
    どうも、iOS9になってSplitViewとかいろいろ対応したせいで、原則的にすべての向き(ポートレート、ランドスケープ)の画面をサポートしなければいけないらしい。
    しかしあくまでもフルスクリーンを必要としない限り。
    というわけで、TARGETSのところのRequires full screenをチェックして再ビルドしたら消えてくれたよ。
    めんどくせぇな。