Swiftの広域変数

  • 1
    いいね
  • 4
    コメント

Swift初心者です。主にMac版のアプリケーションをつくり時々iOSなプチ開発者です。MacのAppStoreにひとつだけアプリを公開していて、なんとか中級者の域に進みたいと日々精進しています。

コードを書き始めてぶつかる課題の一つがクラス間での変数の共有でした。デフォルトのViewControllerにあるプロパティに他のクラスからアクセスするだけでも、解決するのに何時間もかかったりするビギナーです。Qiitaで見かけたAppDelegateに置いたプロパティを他のクラスで共有するTIPSは初めて見るテクニックで、「これだ」探していたものはと思って使い始めていました。(下記ひとつめの方法)

そんな中で、Swiftでもいわゆる広域変数のglobal的な変数が使えることを知り、クラス外に置いておくと簡単に異なるクラスの間で変数が共有できることを、今更ながら知ったわけです。しかし、Swiftに限らず広域変数を多用することはよろしくないことは理解しています。複数人数で開発しているときなどはその理由はぼんやり理解できます。しかし、私のように「ひとり開発者」の場合には、手っ取り早い広域変数にはつい手が伸びてしまうのです。

まず私が知り得たクラス間での変数の共有(今回はこの用途を広域変数と呼んでいます)を取り上げて、コメントにてなぜ広域変数はよろしくないのかを指導していただけるとうれしいです。

AppDelegateに設置する方法

下記のように、デフォルトで作成されているAppDelegate.swiftの中に変数を置いて、他のクラスからはread/writeすることができました。

AppDelegate.swift
import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    var globalVar = "Hello"

    func applicationDidFinishLaunching(_ aNotification: Notification) {
    }
}
ViewController.swift
import Cocoa

class ViewController: NSViewController {

    let fromAppDelegate: AppDelegate = NSApplication.shared().delegate as! AppDelegate

    override func viewDidLoad() {
        super.viewDidLoad()

        print(fromAppDelegate.globalVar)  // Helloと表示される

    }
}

クラス外に設置する方法

初心者にはありがたいシンプルな記述で広域で変数を共有できます。コードの文字数だけ見るとこれが一番簡潔に使えるのですが、ネット上の情報ではあまり推奨されているとは言い難く、できれば使用しない方が良いとの雰囲気です。

AppDelegate.swift
import Cocoa

var globalVar = "Hello"

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    func applicationDidFinishLaunching(_ aNotification: Notification) {
    }
}
ViewController.swift
import Cocoa

class ViewController: NSViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        print(globalVar)  // Helloと表示される
    }
}

シングルトンを使った方法

直感的に、この方法がデザインパターンにもあるように「玄人受け」しそうな気がします。現状ではこのテクニックを使うのが中級者への道を最短で走れるような希望を描いています。

AppDelegate.swift
import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    func applicationDidFinishLaunching(_ aNotification: Notification) {
    }
}


class GlobalVar {
    private init() {}
    static let shared = GlobalVar()

    var sampleString = "Hello"
}
ViewController.swift
import Cocoa

class ViewController: NSViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        var myVar = GlobalVar.shared
        print(myVar.sampleString)  // Helloと表示される
    }
}

ほかにもいろいろテクニックはあるのでしょうが、今のところ自分の頭のなかで整理して実用性のある方法を3つ取り上げました。異なる継承のないクラス間で変数をread/writeして共有するテクニックについてのスマートなやり方を模索中です。アドバイスをいただけると幸いです。

ちなみにこのポストが今回Qiitaではじめてのものです。これまで数多くここで知識を吸収できたので、自分でも情報発信や知識の共有に貢献したい考えの第一歩です。