Bernard
Bernard

Reputation: 4580

How to share data between number of ViewControllers?

I know one way to share data is segue. But in my application I have multiple tabs which contain number of VCs. For instance userName and address. I want to show in some of the VCs these infos. Every time I query the cloud is not right way. I am following this answer first part: answer. But as a newbie I am not sure how MyDataModel is defined. Is it a NSObject class? I appreciate if anyone can define this class as example with two NSString fields. And how to access these fields in VC and AppDelegate.

Inside AppDelegate

@interface MyAppDelegate : NSObject <UIApplicationDelegate, UITabBarControllerDelegate>
{

    MyDataModel *model;
    AViewController *aViewController;
    BViewController *bViewController;
    ...
}

@property (retain) IBOutlet AViewController *aViewController;
@property (retain) IBOutlet BViewController *aViewController;

@end

@implementation MyAppDelegate

...

- (void)applicationDidFinishLaunching:(UIApplication *)application
{
...

    aViewController.model = model;

    bViewController.model = model;

    [window addSubview:tabBarController.view];
    [window makeKeyAndVisible];
}

Inside VC:

@interface AViewController : UIViewController {
    MyDataModel *model;
}

@property (nonatomic, retain) MyDataModel *model;

@end

@interface BViewController : UIViewController {
    MyDataModel *model;
}

@property (nonatomic, retain) MyDataModel *model;

@end

The only thing I need is where to define MyDataMode and how to access its fields?

Upvotes: 1

Views: 165

Answers (4)

Maksud Ali
Maksud Ali

Reputation: 121

You can create a class and use it in your tab controller.

#import <Foundation/Foundation.h>



@interface UserModel : NSObject <NSCoding>

@property (nonatomic, strong) NSString *lastName;
@property (nonatomic, strong) NSString *firstName;

+ (instancetype)modelObjectWithDictionary:(NSDictionary *)dict;
- (instancetype)initWithDictionary:(NSDictionary *)dict;
- (NSDictionary *)dictionaryRepresentation;

@end

implementation file

#import "UserModel.h"


NSString *const kUserModelLastName = @"LastName";
NSString *const kUserModelFirstName = @"FirstName";


@interface UserModel ()

- (id)objectOrNilForKey:(id)aKey fromDictionary:(NSDictionary *)dict;

@end

@implementation UserModel

@synthesize lastName = _lastName;
@synthesize firstName = _firstName;


+ (instancetype)modelObjectWithDictionary:(NSDictionary *)dict
{
    return [[self alloc] initWithDictionary:dict];
}

- (instancetype)initWithDictionary:(NSDictionary *)dict
{
    self = [super init];

    // This check serves to make sure that a non-NSDictionary object
    // passed into the model class doesn't break the parsing.
    if(self && [dict isKindOfClass:[NSDictionary class]]) {
            self.lastName = [self objectOrNilForKey:kUserModelLastName fromDictionary:dict];
            self.firstName = [self objectOrNilForKey:kUserModelFirstName fromDictionary:dict];

    }

    return self;

}

- (NSDictionary *)dictionaryRepresentation
{
    NSMutableDictionary *mutableDict = [NSMutableDictionary dictionary];
    [mutableDict setValue:self.lastName forKey:kUserModelLastName];
    [mutableDict setValue:self.firstName forKey:kUserModelFirstName];

    return [NSDictionary dictionaryWithDictionary:mutableDict];
}

- (NSString *)description 
{
    return [NSString stringWithFormat:@"%@", [self dictionaryRepresentation]];
}

#pragma mark - Helper Method
- (id)objectOrNilForKey:(id)aKey fromDictionary:(NSDictionary *)dict
{
    id object = [dict objectForKey:aKey];
    return [object isEqual:[NSNull null]] ? nil : object;
}


#pragma mark - NSCoding Methods

- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super init];

    self.lastName = [aDecoder decodeObjectForKey:kUserModelLastName];
    self.firstName = [aDecoder decodeObjectForKey:kUserModelFirstName];
    return self;
}

- (void)encodeWithCoder:(NSCoder *)aCoder
{

    [aCoder encodeObject:_lastName forKey:kUserModelLastName];
    [aCoder encodeObject:_firstName forKey:kUserModelFirstName];
}

Import this class where you are setting or initializing data or values. and do below code.

    NSDictionary *dicUserModel = [[NSDictionary alloc]initWithObjectsAndKeys:@"Moure",@"LastName",@"Jackson",@"FirstName", nil];

    UserModel *userModel = [[UserModel alloc]initWithDictionary:dicUserModel];
    //NSUserDefault save your class with all property. and you can simply retrieve your UserModel from NSUserDefault.
    //Below code save this model into nsuserdefault.
    [[NSUserDefaults standardUserDefaults]setObject:[NSKeyedArchiver archivedDataWithRootObject:userModel] forKey:@"UserModel"];
    [[NSUserDefaults standardUserDefaults]synchronize];

You can retrieve you class object using below code.

    UserModel *savedUserModel = (UserModel *)[NSKeyedUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults]objectForKey:@"UserModel"]];
    NSLog(@"%@",savedUserModel.firstName);
    NSLog(@"%@",savedUserModel.lastName);

Upvotes: 0

Sonu
Sonu

Reputation: 957

You can use singleton class for that,

----------
SharedManages.h
----------

#import <Foundation/Foundation.h>
#import "Reachability.h"
#import "Reachability.h"

@interface SharedManager : NSObject
{

}
+(SharedManager *)sharedInstance;

// Create property of your object which you want to access from whole over project.

@property (retain, nonatomic) User *loginUser;
@property (assign, readwrite) BOOL isNetAvailable;

@end

----------

----------
SharedManages.m
----------

#import "SharedManager.h"

static SharedManager *objSharedManager;

@implementation SharedManager

@synthesize
isNetAvailable  = _isNetAvailable,
loginUser    = _ loginUser;

+(SharedManager *)sharedInstance
{
    if(objSharedManager == nil)
    {
        objSharedManager = [[SharedManager alloc] init];
        objSharedManager. loginUser = [User alloc]] init];

        Reachability *r = [Reachability reachabilityForInternetConnection];
        NetworkStatus internetStatus = [r currentReachabilityStatus];
        // Bool

        if(internetStatus == NotReachable)
        {
            NSLog(@"Internet Disconnected");
            objSharedManager.isNetAvailable = NO;  // Internet not Connected
        }
        else if (internetStatus == ReachableViaWiFi)
        {
            NSLog(@"Connected via WIFI");
            objSharedManager.isNetAvailable = YES; // Connected via WIFI
        }
        else if (internetStatus == ReachableViaWWAN)
        {
            NSLog(@"Connected via WWAN");
            objSharedManager.isNetAvailable = YES; // Connected via WWAN
        }

    }

    return objSharedManager;
}


@end

Access from other Class...

[SharedManager sharedInstance].isNetAvailable ;

[SharedManager sharedInstance].loginUser ;

Hope, This will help you..

Upvotes: 3

Mujib Saiyyed
Mujib Saiyyed

Reputation: 158

Easiest way i could think of is using NSUserDefaults. Save your name and address string in NSUserDefaults like

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setValue:YourNameString forKey:@"NameString"];
[defaults setValue:YourAddressString forKey:@"AddressString"];
[defaults synchronize];

and access it in any ViewController as

 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
 NSString *name = [plistContent valueForKey:@"NameString"];
 NSString *address= [plistContent valueForKey:@"AddressString"];

Hope this helps.

Upvotes: 1

R Menke
R Menke

Reputation: 8391

I don't have "local" copies of the values. I set them in the delegate and fetch them from there. That way you don't have to hard code it for all UIViewController's in the delegate.

Assigning values is best done on the first view, or with default values. I personally use viewDidLoad for those kind of things. Since it is only called once on the first view once and pertains until the app is terminated.

Then I get the delegate from inside the VC, call the instance and from there the values.

Swift

Inside AppDelegate:

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    var globals : GlobalValueClass?

First VC:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let delegate = UIApplication.sharedApplication().delegate as! AppDelegate
        delegate.globals = GlobalValueClass()
        delegate.globals!.numbers = [1,2,3]
    }
}

Other VC's:

class ViewControllerTwo: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

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

        print(delegate.globals!.numbers)
        // Do any additional setup after loading the view.
    }
}

Objective C ( don't have the full method in obj-c, but easy to find)

MainClass *appDelegate = (MainClass *)[[UIApplication sharedApplication] delegate];

how to get the delegate in obj-c

Upvotes: 2

Related Questions