如何使所有视图控制器都可以看到数据?

时间:2015-07-23 16:19:51

标签: ios objective-c swift uiviewcontroller

让我们考虑以下情况:

我有一个标签栏应用程序,其中点击每个标签栏项目将用户带到由不同视图控制器(典型模式)处理的其他视图。

在我的一个控制器中,我有下载重要数据的方法,我希望它们在整个应用程序中是全局的。我应该使用什么设计模式?

这样做的一种方法是使用核心数据等持久性来存储这些数据,但这是使所有视图控制器都能看到数据的唯一方法吗?也许app delegate能够执行此类操作?

一般情况下,如何处理项目中所有视图控制器都应该看到的数据或变量的情况?

请注意,我并不是要求在应用程序的启动过程中持久保存数据,我只是想知道如何根据整个项目制作一些全局数据。

5 个答案:

答案 0 :(得分:2)

不要(强调不要)使用以下内容:

  • 单身
  • AppDelegate(只是另一个Singleton)
  • NSUserDefaults的

相反不要:

  • 核心数据

执行:

  • 在实例化期间或通过属性传递

为什么?

不要弄乱你的记忆 相反不要与SOLID的几个原则混淆。

你会如何正确地做到这一点:

  • 创建一个基本视图控制器,它具有一个可以获取数据的属性,使所有视图控制器都可以从中继承。

  • 子类UITabBarController

  • 如果选择了新的视图控制器,请将数据设置为视图控制器

实现有点棘手,这是来自真实世界的应用程序

class ContentTabBarController : UITabBarController {

    private var kvoSelectedViewControllerContext: UInt8 = 1

    required init(coder aDecoder: NSCoder) {


        self.addObserver(self, forKeyPath: "selectedViewController", options: .New | .Old | .Initial , context: &kvoSelectedViewControllerContext)
    }

    deinit{
        self.removeObserver(self, forKeyPath: "selectedViewController")
    }

    override func observeValueForKeyPath(keyPath: String, ofObject object: AnyObject, change: [NSObject : AnyObject], context: UnsafeMutablePointer<Void>) {
        if context == &kvoSelectedViewControllerContext {
            var targetVC : UIViewController?

            if let viewController = change["new"] as? UIViewController{
                if let oldViewController = change["old"] as? UIViewController{
                    if viewController != oldViewController {
                        targetVC = viewController
                    }
                }
            } else {
                targetVC = self.viewControllers![0] as? UIViewController
            }
            self.configureTargetViewController(targetVC)
        }
    }

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        self.navigationController?.navigationBar.translucent = false
    }

    func configureTargetViewController(viewController: UIViewController?){

        //setup data
    }
}

标签栏控制器如何获取数据。

嗯,这取决于你。它可以获取核心数据,它实际上可以将获取管理器作为数据传递。它可以从光盘或网络中读取。但是对于一个理智的设计它不应该自己做,而是使用另一个类。并且应该从标签栏控制器外部,即从App Delegate设置此fetcher类的实例。

答案 1 :(得分:1)

一种简单的方法是创建一个结构并使其保存变量。然后,您可以随时编辑它。例如:

struct Variables {
   static var number = 4
}

然后,您可以通过执行此代码在任何视图控制器中编辑变量内的数据。

Variables.number = 6 //or any other number you want

答案 2 :(得分:0)

更清洁,更有效,但不一定不同的方法是创建一个单一类,例如list,您可以通过多种方式访问​​,并且可供所有其他课程使用。它具有将应用程序特定的东西与应用程序委托内容分离的好处。您可以这样定义类:

AppData

您可以为AppData类定义ivars,然后管理AppData的单例实例。使用类方法,例如 + sharedInstance ,以获取您可以调用mehods的单例句柄。例如,

@interface AppData : NSObject

// Perhaps you'll declare some class methods here & objects...

@end

+ sharedInstance 的实现可以是您管理单例的实际创建的位置,该方法最终会返回。

答案 3 :(得分:0)

Singleton模式在这里很有用。在Swift中,它可以像这样创建:

class SomeManager {
    static let sharedInstance = SomeManager()

    var someData: NSData?
}

稍后在视图控制器中以SomeManager.sharedInstance.someData

访问它

有关Swift中的单身人士的更多信息以及Objective-C here

中的一些信息

答案 4 :(得分:0)

试试这个简单的方法,

1)在appdelegate.swift中创建一个对所有viewcontroller都可见的变量。

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

 ...
 ...
 var Check:String!="" // to pass string
 ...
 ...    
}

2)在任何视图控制器中创建appdelegate实例

<强> viewcontroller1.swift

import UIKit

class ViewController: UIViewController {

    let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate

   ...
   ...

    override func viewDidLoad() {
        super.viewDidLoad()
        ...
    var tmp = "\(appDelegate.Check)"
    appDelegate.Check="Modified"
    }
}

<强> Viewcontroller2.swift

import UIKit

    class ViewController: UIViewController {

        let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate

       ...
       ...

        override func viewDidLoad() {
            super.viewDidLoad()
            ...
        var getdata = "\(appDelegate.Check)"
        println("Check data : \(getdata)") // Output : Check data : Modified
        }
    }