Swift,Objective-Cプログラミング ~ iOS ~

Objective-C,Swift,Apple Watchなどのプログラミング

【iOS Swift入門 #240】セマフォ(semaphore)を使って排他制御するサンプル

排他制御したいとき、GCDで関数が用意されている関数を使う。

下記3つである。
①dispatch_semaphore_create
②dispatch_semaphore_wait
③dispatch_semaphore_signal

使ってみる。

■例
①非同期で画像をダウンロードする
②ループのindex * 共有変数numを共有変数numにセット

①と②を11回繰り返す。

順番に実行されていけば、
1 * 2 * 3 …… *10
としていき、
最終的にnumは3628800となる。

まず、セマフォを使わなかった場合にどうなるか?

セマフォを使わない場合

import UIKit

class ViewController: UIViewController {
    var num = 0

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)

        // 画像のURL
        let url = NSURL(string: "http://cdn-ak.f.st-hatena.com/images/fotolife/f/fjswkun/20150723/20150723224720.png")!

        for i in 0...10{

            // 非同期処理開始
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)){

                // 画像をダウンロード
                let data = NSData(contentsOfURL: url)
                dispatch_async(dispatch_get_main_queue()){
                    // 共有リソースの変数numを更新
                    if i <= 1{
                        self.num = i
                    }else{
                        self.num = self.num * i
                    }
                    println("i : \(i) num : \(self.num)")
                }
            }
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

◯実行結果
非同期処理が同時に動くので、想定どおりに値にならず、
numは最終的に0になってしまった。
実行したときによって、numの値は変わってしまう。

f:id:fjswkun:20150725150556p:plain


セマフォを使わなかった場合

import UIKit

class ViewController: UIViewController {
    var num = 0

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)

        // 画像のURL
        let url = NSURL(string: "http://cdn-ak.f.st-hatena.com/images/fotolife/f/fjswkun/20150723/20150723224720.png")!

        // 同時に実行できるのはひとつとする
        let semaphore = dispatch_semaphore_create(1)

        for i in 0...10{
            // 実行中の処理があるときはここで待機させる
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)

            // 非同期処理開始
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)){

                // 画像をダウンロード
                let data = NSData(contentsOfURL: url)
                dispatch_async(dispatch_get_main_queue()){
                    // 共有リソースの変数numを更新
                    if i <= 1{
                        self.num = i
                    }else{
                        self.num = self.num * i
                    }
                    println("i : \(i) num : \(self.num)")
                }

                // 処理が終わったことを通知
                dispatch_semaphore_signal(semaphore)
            }
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

◯実行結果
同時実行されないようにセマフォを使って、
排他制御したので想定通りの結果を得た。

f:id:fjswkun:20150725150615p:plain


■おわりに
ハゲタカシリーズの新しいのがでてた!

ハゲタカ外伝 スパイラル

ハゲタカ外伝 スパイラル



【参考情報】
iOSアプリ開発未経験の人向け
iOSアプリ開発をはじめたとき最初に買った書籍
【アプリ作成未経験の人向け】
Storyboardを使って画面を作成していく。
手順にしたがって操作していくと、ボタンの作成やWebViewの作成などができる。
アプリって、こんな感じで作るんだというのを体験できる。

Swiftではじめる iPhoneアプリ開発の教科書 【iOS 8&Xcode 6対応】

Swiftではじめる iPhoneアプリ開発の教科書 【iOS 8&Xcode 6対応】

・わかりやすくていい、と聞いた本
立ち読みした感じだと【アプリ作成未経験の人向け】

絶対に挫折しない iPhoneアプリ開発「超」入門【Swift & iOS8.1以降 完全対応】

絶対に挫折しない iPhoneアプリ開発「超」入門【Swift & iOS8.1以降 完全対応】

②を終えたくらいの知識の方向け
・アプリ開発独学中に2冊めに購入した書籍
プログラミング知識はなくても、若干理解するのに時間がかかる程度で、
読み進められるわかりやすさがある。

iPhoneアプリ開発塾

iPhoneアプリ開発塾

③中級者、上級者向け

詳解 Swift

詳解 Swift