[Django] WhiteNoiseを使って静的ファイルを配信する

WhiteNoiseとは?

WhiteNoiseとはWSGIアプリケーションのための静的ファイルを配信するのを簡単にしてくれるライブラリです。
少しの設定をするだけでAmazon S3やNginxに頼ることなく静的ファイルを配信できます。
本番サーバーで画像やcss等を参照できるようにするには色々と手順を踏まないといけなかったのですが、WhiteNoiseを使うとそのような手間が省けて大変便利です。

Install

$pip install whitenoise

settings.py

BASE_DIR = os.path.dirname(os.path.abspath(__file__))

STATIC_ROOT = 'staticfiles'
STATIC_URL = '/static/'
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),
)

STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage'

wsgi.py

from django.core.wsgi import get_wsgi_application
from whitenoise.django import DjangoWhiteNoise

application = get_wsgi_application()
application = DjangoWhiteNoise(application)

静的ファイルをSTATICFILES_STORAGEにコピーする

$python manage.py collectstatic

Done!

これで本番サーバーでも静的ファイルを参照できるようになります。

UITableViewCellがタップされた時の背景色を変更する

UITableViewCellのUITableViewCellSelectionStyleを変更すればよい。
標準では以下の4種類のスタイルが用意されてある。

  • UITableViewCellSelectionStyle.Default
  • UITableViewCellSelectionStyle.Blue
  • UITableViewCellSelectionStyle.Gray
  • UITableViewCellSelectionStyle.None

例えば、背景色を表示させないようにする場合は以下の実装になる。

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell            {

    let cell = tableView.dequeueReusableCellWithIdentifier("UniqCell") as! UITableViewCell
    cell.selectionStyle = UITableViewCellSelectionStyle.None

}

上の4種類に含まれていない背景色にするには、selectedBackgroundViewに任意の色のUIViewを代入すれば実現できる。
赤色にする場合は以下のようになる。

...
// selectionStyleを使用しないので、UITableViewCellSelectionStyleNoneを設定。
cell.selectionStyle = UITableViewCellSelectionStyleNone
let selectedView = UIView()
selectedView.backgroundColor = UIColor.redColor()
cell.selectedBackgroundView =  selectedView

録音している時の音量を可視化するAudioMeterViewを作った

AudioMeterViewというライブラリを作りました。

AudioMeterViewを使うと、録音している時の音量をプログレスバー形式で表示することができます。

上のgifアニメのコードは以下のようになります。


import UIKit
import AVFoundation

class ViewController: UIViewController,AVAudioRecorderDelegate {
    @IBOutlet var audioMeterView: AudioMeterView! = AudioMeterView()
    var timer:NSTimer!
    var loaded:Bool = false
    var fname:String!
    var currentPath:NSURL!
    var soundRecorder:AVAudioRecorder!


    override func viewDidLoad() {
        super.viewDidLoad()
        self.setupRecorder()
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        if self.loaded == false {
            // setup audiometerView  
            self.audioMeterView.setup(0.4, backgroundColor: UIColor.lightGrayColor(), overLayColor: UIColor.redColor())
        }
    }

    func record(path:NSURL){
        let audioSession:AVAudioSession = AVAudioSession.sharedInstance()
        try! audioSession.setCategory(AVAudioSessionCategoryRecord)
        try! audioSession.setActive(true)
    }


    func setupRecorder(){
        self.fname = NSUUID().UUIDString + ".caf"
        let documentDirectoryURL = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0]
        let fileDestinationUrl = NSURL(string: documentDirectoryURL)!.URLByAppendingPathComponent(fname)
        self.currentPath = fileDestinationUrl
        self.record(self.currentPath)

        let recordSettings:[String:AnyObject] = [
            AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
            AVEncoderAudioQualityKey: AVAudioQuality.Max.rawValue,
            AVEncoderBitRateKey: 320000,
            AVNumberOfChannelsKey: 2,
            AVSampleRateKey: 44100.0
        ]


        self.soundRecorder = try! AVAudioRecorder(URL: self.currentPath, settings: recordSettings)
        self.soundRecorder.updateMeters()
        self.soundRecorder.delegate = self
        self.soundRecorder.prepareToRecord()
        self.soundRecorder.meteringEnabled = true


    }





    @IBAction func onToggleRecord(button: UIButton) {
        // Record/Stopボタンが押された時の挙動
        if button.titleLabel!.text == "Record" {
            button.setTitle("Stop", forState: .Normal)
            self.timer = NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: "updated", userInfo: nil, repeats: true)
            self.soundRecorder.record()
        }else{
            button.setTitle("Record", forState: .Normal)
            self.soundRecorder.stop()
            self.timer.invalidate()
        }




    }


    func updated(){
        //0.4秒ごとに音量を取得してself.audioMeterViewに反映させる
        self.audioMeterView.updateRecorderMeter(self.soundRecorder, duration: 0.4, channel: 0)
    }


AudioMeterViewのGitHubのリンクからサンプルプロジェクトをダウンロードできます。

[iOS] AVAudioSessionで再生するときの音量を大きくする


AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayAndRecord)
で録音した音源を再生すると、音量を最大にしても小さすぎたのでいろいろ調べてみたところ、 録音するときは
let audioSession:AVAudioSession = AVAudioSession.sharedInstance()
try! audioSession.setCategory(AVAudioSessionCategoryRecord)
に、再生するときは
let audioSession:AVAudioSession = AVAudioSession.sharedInstance()
try! audioSession.setCategory(AVAudioSessionCategoryPlay)
にAVAudioSessionのCategoryを切り替えれば音量を大きくすることができた。