Transfer NSMutableArray between classes [duplicate] - objective-c

This question already has answers here:
Passing data between view controllers
(45 answers)
Closed 7 years ago.
I've looked at other posts and none of them make any sense. I have an AppController (for a NSCollectionView), and I have a table in it called filePaths. File paths is an #property. MY object file (for the collection view), needs those paths. How do I transfer the filePaths from AppController to my file class? Singletons and other things are confusing to me, even though I've read a lot about them. If you have an answer involving singletons or something similar, please explain it, because I have no idea what is going on.

Simply assign it to a property.

If you're using storyboards, you'll want to use the "prepare for segue" method typically found at the bottom of your view controllers.
You'll create a property in the destination view controller like this in your header:
#property (nonatomic) NSMutableArray *recievedArray;
and in your origin view controller's m file (the m file where the mutable array originally is) you'll import the destination view controller at the top like so
#import "DestinationViewController.h"
Now we'll populate "prepareForSegue" :
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"segueToDestinationViewController"]) {
DestinationViewController *vc = [segue destinationViewController];
[vc setRecievedArray:theMutableArray];
}
}
Where "segueToDestinationViewController is what you set in storyboard like this (I reused this image from something else but you want to click on the segue arrow and fill in "Identifier" with "segueToDestinationViewController")
Now you're all set and the property will be properly assigned upon segue!
Edit: You can also set up singletons easily by creating your singleton class and adding this method to it:
+ (id)sharedManager {
static MyManager *sharedMyManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMyManager = [[self alloc] init];
});
return sharedMyManager;
Then you will invoke the single instance of the singleton using the class method like this
MyManager *mySingleton = [MyManager sharedManager];
Going through the GCD like this is pretty fool proof so you should be fine. Now all you have to do is get the properties from the singleton instance.

Related

One NSDictionary visible everywhere in application

Now I am developing an iOS application which works like this:
User scans QR code,
App searches for a specific key - > value,
it gives out a value to the user.
Currently I have two ViewControllers - the main and "value" ViewController, which is inherited from main. The problem is that if I create NSDictionary in main VC it is not visible in "value" VC. Main VC gives only the string (QR code, the key) through the segue. So, the value VC has to search for key and display the value.
What I ask is some kind of global variable or one DataSource visible across the whole app. Of course, I can implement NSDictionary initialisation inside value ViewDidLoad method and it will work, but this is not the point. New modules are to be added there and the variable has to be global. I googled a lot and got the idea that singleton pattern can be helpful here. I tried to implement it, but no idea how to do. Do I need it, or it is too complex for this kind of DataSource?
Thank you!
The basic idea is, you will still need to #include the header file of the place where this dictionary will be. The solution that Naveen proposes means that you will be including the header for the app delegate wherever you want to access it. Whether to use the app delegate for this purpose or not is kinda grayish. Some people often do this, some say its a bad use of it.
The singleton approach means that you will create a class, that will always contain the same information since the init method will return object that was previously created.
For the singleton aproach, imagine I have a database manager class. So in the header of this class (the DatabaseManagerSingleton.h) ill have this:
#interface DatabaseManager : NSObject
+ (DatabaseManager*)sharedInstance;
// Your dictionary
#property (nonatomic,strong) NSMutableDictionary* someDictionary;
The implementation will look like this: (check how "sharedInstance" initializes the object)
#implementation DatabaseManager
#pragma mark - Singleton Methods
+ (DatabaseManager*)sharedInstance {
static DatabaseManager *_sharedInstance;
if(!_sharedInstance) {
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
_sharedInstance = [[super allocWithZone:nil] init];
});
}
return _sharedInstance;
}
+ (id)allocWithZone:(NSZone *)zone {
return [self sharedInstance];
}
- (id)copyWithZone:(NSZone *)zone {
return self;
}
- (id)init
{
self = [super init];
if (self != nil)
{
// Custom initialization
_someDictionary = [[NSMutableDictionary alloc] init];
}
return self;
}
Now, a VERY important thing is that, any place you want to use this object should first include the header:
EDIT: To use it in your code:
1) add the header
#import "DatabaseManager.h"
2) initialize the object
DatabaseManager *databaseManager = [DatabaseManager sharedInstance];
3) do whatever you need
// Initialize the dictionary
databaseManager.someDictionary = [[NSMutableDictionary alloc] initWithObjectsAndKeys:#"OBJECT",#"someKey", nil]; // In this case the object is just a NSString.
// Access
[databaseManager.someDictionary objectForKey:#"someKey"];
Put as a property on Appdelegate
#property (nonatomic,strong) NSDictionary * sharedData;
Access anywhere like
NSDictionary *sharedData= ((APPDelegate *) [UIApplication sharedApplication].delegate).sharedData;

How to use a variable from one class in another to show up on my next storyboard scene

I guess this has been asked before but I can't find something that I can use to answer my question and get this to work. So, here's what I have. In once class, I have the following:
IBOutlet UILabel *totalAmountLabel;
and I've also setup the following the score the total in:
#property (nonatomic, strong) NSString *finalTotal;
So I've set my amount to that String in one class, but how exactly do I get at it in another class? I assume I import my class, but once I've done that, what do I type to get at this variable? How would I declare an instance of my class to get at this variable, and even then, would I have access to it? Or do I go via the getters and setters that are done for me - if so how do I know what they're called?
I hope that makes sense, thanks in advance so your help.
I assume I import my class, but once I've done that, what do I type to get at this variable?
Unfortunately, it is not that simple: you need an object instance in order to set its instance variables. It does not matter if you go through properties or not, you need an instance either way.
The way you get that instance differs depending on how your classes interact. Since you are using ARC and IBOutlets, I am assuming that the totalAmountLabel is located in a view controller that you open using a segue. In this case, you need to import the destination controller's header in the starting controller's .m file, and add this code:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"goToMyNextController"]) {
// Change the ID to match the one that you are using ^^^^^^^^^
MyNextViewController *nvc = [segue destinationViewController];
[nvc.totalAmountLabel setTitle:finalTotal forState:UIControlStateNormal];
}
you can use NsUser default
set you object with your keyword
[[NSUserDefaults standardUserDefaults]setObject:#"Ajay" forKey:#"name"];
than get that object any where in you project
NSString *name = [[NSUserDefaults standardUserDefaults]objectForKey:#"name"];

Updating view with a data from the method of another class

I am trying to update my UIProgressView with some data from a method of my utility class.
Now, just because for updating my UIProgressView, i am holding that method in my view controller class and everything works fine. Because i can reach the loop in that method with a global variable so i can update my progress. But if i want to move this method to my utility class, what am i supposed to do to keep informed my UIProgressView. Thanks.
What I would suggest is to redesign your utility class to be a singleton
Here is an example of code of your utility class:
UtilityClass.h file:
#interface UtilityClass : NSObject
+ (UtilityClass *)sharedInstance;
- (CGFloat)awesomeMehod;
#end
UtilityClass.m
#implementation UtilityClass
+ (id)sharedInstance
{
static UtilityClass *_instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [[UtilityClass alloc] init];
});
return _instance;
}
- (id)init
{
self = [super init];
if (!self) return nil;
// Regular initialization, however keep in mind that it will be executed just once
return self;
}
- (CGFloat)awesomeMethod
{
return 42.0f
}
#end
Now from your view controller you will call
CGFloat progress = [[UtilityClass sharedInstance] awesomeMethod];
[self.progressView setProgress:progress];
keep in mind several things:
It's one of possible approaches and I would go and read about various
design patterns that might come in handy one day
Probably a good idea to refresh knowledge on view controllers and the way they interact
For class to become a proper singleton, you also should override
methods such as alloc, init, initWithZone, dealloc, release
etc (list of methods to override will vary if you use ARC), here is
an example of doing that, although dispatch_once takes care of
#synchronize() call. For now, as long as you "instantiate" you class only
through calling sharedInstance class method you will be fine.

How to pass values between 2 View Controllers without protocol?

I have two view controllers, call them viewA and ViewB
All the action happens in main view - ViewA
A menu button is hit, brings up ViewB, all is well and the menu comes up
Now, the user touches one IBAction button, which programmatically just needs to:
change the value of a BOOL, call it myBOOL to YES
dismiss ViewB
pass the myBOOL variables current state of YES back to ViewA
I have declared the same BOOL, set property, synthesized on both Views, but per my NSLog upon dismissal of ViewB and loading back up ViewA, it reverts back to NO
So I know I'm going off on a tangent, I just want to know if you can send the value of a BOOL between two controllers and if so, please show me an example... as searches have found Protocols and Delegate examples with NSString's, and when I attempt with a BOOL I get stuck in an import loop, however I've read that its possible to make a global BOOL, as bad design as it is, I just need to get over this block for now.
A question on this topic should really be focused more on NSNotificationCenter rather than NSUserDefaults, taking note that both are singletons.
NSUserDefaults:
The purpose of this class is NOT to pass variables between classes. It's purpose is, well, to store user's defaults. (ie preferences, settings, ... etc).
NSNotificationCenter:
This class is very handy, and has many different uses, one of which is to broadcast a variable for any class to receive. The receiving class is called the observer. This pattern is known as the Observer Pattern.
NOTE: The NSUserDefaults approach has the advantage of allowing you to set the variable before the other class is initialized, and can be retrieved at anytime. However, that's really sloppy (IMHO) and considered bad practice.
Quick and Dirty code sample on NSNotificationCenter:
// upon initializing the class that wants to observe the changes, we add it as an observer.
// So, somewhere in the A.m, upon being initialized (init, maybe?).
- (id)init {
if (self = [super init]) {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(calledUponNotif:)
name:#"MyObserveKey"
object:nil];
}
return self;
}
// the selector should look something like this:
- (void)calledUponNotif:(NSNotification *)notif {
id sentVar = [notif object];
}
// Somewhere in the B.m
[[NSNotificationCenter defaultCenter] postNotificationName:#"MyObserveKey"
object:varToSend];
Another note: After calling the postNotification method, the registered selector in the other class will be called synchronously, so you don't have to worry about that.
This is not a good encapsulation answer but without being able to use protocols or delegates I don't believe it will have good encapsulation.
You can also create a global variable that you can set in one view controller and access in another.
ViewControllerOne.h
extern NSString *globalVariable;
#interface ViewControllerOne
#end
ViewControllerOne.m
#import "ViewControllerOne.h"
#implementation ViewControllerOne
NSString *globalVariables = #"Some String in the variable to access in second controller";
#end
ViewControllerTwo.m
#import "ViewControllerTwo.h"
#import "ViewControllerOne.h"
#implemetation ViewControllerTwo
- (void)viewDidLoad
{
NSLog("%#", globalVariables);
}
#end
This will print out into the console
****CONSOLE****
Some String in the variable to access in second controller
There is View-independent value keeping tool. You can use:
[[NSUserDefaults standardUserDefaults]setObject:<#(id)#> forKey:<#(NSString *)#>]
For example, you inputs strings or datas in A view, you can store them in above variables. And then, in B view, you can use them by below code:
[[NSUserDefaults standardUserDefaults]objectOrKey:<#(NSString *)#>]
These are a example of NSUserDefaults data using:
View A:
- (void)textFieldDidEndEditing:(UITextField *)sender
{
if (sender == homepage) {
[[NSUserDefaults standardUserDefaults]
setURL:[NSURL URLWithString:homepage.text] forKey:Ever5secHomepagePrefKey];
if( [homepage canResignFirstResponder] ) {
[homepage resignFirstResponder];
}
} else if (sender == userId) {
[[NSUserDefaults standardUserDefaults]
setObject:userId.text forKey:Ever5secUserIdPrefKey];
objectForKey:Ever5secUserIdPrefKey]);
if( [userId canResignFirstResponder] ) {
[userId resignFirstResponder];
}
} else if (sender == password) {
[[NSUserDefaults standardUserDefaults]
setObject:password.text forKey:Ever5secPasswordPrefKey];
if( [password canResignFirstResponder] ) {
[password resignFirstResponder];
}
}
}
View B:
userId.text = [[NSUserDefaults standardUserDefaults]
objectForKey:Ever5secUserIdPrefKey];
password.text = [[NSUserDefaults standardUserDefaults]
objectForKey:Ever5secPasswordPrefKey];
homepage.text = [[[NSUserDefaults standardUserDefaults]
URLForKey:Ever5secHomepagePrefKey]
description];
You don't need to use NSNotificationCenter, NSUserDefaults or global variables.
As long as the view controllers are related (and looking at the OP's question, they certainly seem to be) you can simply set the view controllers up to hold a reference to each another (with one of the references being weak of course in order to avoid a "retain", or "strong reference", cycle). Then each view controller can set the property on the other view controller as needed. Example follows...
NB: This concept is valid for any two related view controllers. However, the following code assumes that:
The view controllers in question are related via a navigation controller and the second view controller is attached to the first via a push segue.
iOS 5.0 or above is in use (as it makes use of storyboards).
FirstViewController.h
#interface FirstViewController : UIViewController
/* Hold the boolean value (or whatever value should be
set by the second view controller) in a publicly
visible property */
#property (nonatomic, assign) BOOL someBooleanValue;
/* Provide a method for the second view controller to
request the first view controller to dismiss it */
- (void)dismissSecondViewController;
#end
FirstViewController.m
#import "FirstViewController.h"
#import "SecondViewController.h"
#implementation FirstViewController
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
/* Get the reference to the second view controller and set
the appropriate property so that the secondViewController
now has a way of talking to the firstViewController */
SecondViewController *vc = [segue destinationViewController];
vc.firstViewController = self;
}
- (void)dismissSecondViewController
{
// Hide the secondViewController and print out the boolean value
[self.navigationController popViewControllerAnimated:YES];
NSLog(#"The value of self.someBooleanValue is %s", self.someBooleanValue ? "YES" : "NO");
}
#end
SecondViewController.h
#import "FirstViewController.h"
#interface SecondViewController : UIViewController
// Create a 'weak' property to hold a reference to the firstViewController
#property (nonatomic, weak) FirstViewController *firstViewController;
#end
SecondViewController.m
#implementation SecondViewController
/* When required (in this case, when a button is pressed),
set the property in the first view controller and ask the
firstViewController to dismiss the secondViewController */
- (IBAction)buttonPressed:(id)sender {
self.firstViewController.someBooleanValue = YES;
[self.firstViewController dismissSecondViewController];
}
#end
Of course, the most correct way to handle this sort of inter-viewController communication is to use protocols/delegates/data sources so that the SecondViewController doesn't need to know the specifics of its parent/owner object. However, sometimes it is quicker/simpler to build a solution like this just to prove the concept. Then if all is well and the code is worth keeping, refactor to use protocol(s).
In the case where view controllers don't - and shouldn't - know about each other, it may be necessary to use NSNotificationCenter. Don't use global variables or NSUserDefaults for communication between view controllers.
There are two options available storing and retrieving data in different view controllers.
1)NSUserDefaults is best option for storing data and accessing in any other view controllers.
The NSUserDefaults class provides convenience methods for accessing common types such as float, double, integer, Boolean.
A default object must be a property list, that is, an instance of (or for collections a combination of instances of): NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary.
This is very easy and best method for storing and retrieving data.
if you want to read about NSUserDefaults, here I am sharing document.
NsuserDefaults Document.
2) You would create properties when you want them to be accessible outside the class or other view controllers.
Create property in this way. #property (nonatomic, retain) NSArray *arrayData; and then you can use this array value in other view controllers also.
Properties replace the accessor methods for objects.
You can see my answer here. Pass value from one view controller to another
There are two options available storing and retrieving data in different view controllers.
1)NSUserDefaults is best option for storing data and accessing in any other view controllers.
The NSUserDefaults class provides convenience methods for accessing common types such as float, double, integer, Boolean.
A default object must be a property list, that is, an instance of (or for collections a combination of instances of): NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary.
This is very easy and best method for storing and retrieving data.
if you want to read about NSUserDefaults, here I am sharing document.
[NsuserDefaults Document.][1]
2) You would create properties when you want them to be accessible outside the class or other view controllers.
Create property in this way. #property (nonatomic, retain) NSArray *arrayData; and then you can use this array value in other view controllers also.
Properties replace the accessor methods for objects.
I think best way to use powerful features of blocks in below ways.
In ViewB.h
typedef void (^CompletionHandler)(BOOL myBool);
#interface ViewB : UIViewController {
CompletionHandler completionHandler;
}
- (void)dismissHandler:(CompletionHandler)handler;
In ViewB.m
- (void)dismissHandler:(CompletionHandler)handler {
completionHandler = handler;
}
- (IBAction)dismiss:(id)sender {
completionHandler (YES); // your yes no logic here
}
In ViewA.m
- (IBAction)showPopup:(id)sender {
ViewB *vc = [[ViewB alloc] init];
[self.view addSubview:vc.view];
[vc dismissHandler:^(BOOL myBool) {
if (myBool) {
//Do your work;
}
}];
}

Singleton - Reading from a Data Store

I'm trying to do the right thing by not using global variables in my Xcode project. I've successfully created a singleton. I have a simple data store which I named "myContactsStore" that contains an array, with each object in the array having only 3 instance variables (name, phoneNum, and eMail). I have no problem creating, modifying, saving etc. the data in the array when I'm executing the view controller that created the array.
My problem is trying to access the data store from another view controller. I'm halfway there, as proven by my ability to print the contents of the entire test array from another view controller by using the following code in a for loop:
NSLog(#"%#", myContactsStore.description);
Here's the output:
"Mary, 0938420839, PaulDoe#Mac.com",
"John, 9932097372, PaulDoe#Mac.com",
"Mary, 0726756893, RedCat#iwon.com",
"Mary, 8556327199, xxxbct#mac.com",
"John, 0640848317, xxxbct#mac.com"
How do I access just one instance variables? For example, I want to create a read-only array in another view controller that contains just the email addresses of every contact in the "myContactsStore" array. I've tried several things, but I'm new at this and I must be missing something very basic.
Thanks for you help and any code example you might have the time to include.
While Singletons are an easy way to share data across classes they cause cohesion problems in your overall design where your classes start to "import the world". The issue is coming up with exactly the right dependency for a given class and this is very easily missed when you try to design from classes instead of designing from use cases. You want to ask yourself, "what data does this class use?" You then create a protocol (abstraction) that gives the class the view of the data it wants. In your case one class writes to the data store. It doesn't need to create the data store nor does either class need to know that the data is maintained in an array. Follow these steps exactly in order and follow directly or you'll miss my point. Try a protocol in a separate .h file like the following:
#protocol MyDataStore <NSObject> {
}
Import this header in your 1st class that creates the contacts and declare a property of the protocol's type.
#import "MyDataStore.h"
#interface MyContactCreator : UIViewController
#property (nonatomic, retain) id<MyDataStore> dataStore;
-(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil dataStore:(id<MyDataStore>)aDataStore;
#end
I threw in a custom init method in case you are currently instantiating your view controllers programmatically instead of via InterfaceBuilder. In your implementation you would do something like this:
#implementation MyContactCreator
//other methods...
-(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil dataStore:(id<MyDataStore>)aDataStore
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.dataStore = aDataStore;
}
return self;
}
//other methods...
#end
If you are using Interface Builder to create your view controller you can drag a custom object into play and call it something like "MyDataStoreImpl". The idea here is that you are giving the datastore to the view controller instead of it creating it directly and knowing about it. Also you want to defer worrying about how the data store works until you really need to. Later in your view controller where you create the contacts you would use the data store to create them. Assuming the info comes from standard screen elements you would write code like this:
-(void) addContactTapped:(id)sender
{
[self.datastore createContactWithName:txtNameField.text phoneNumber:txtPhoneField.text email:txtEmailField.text];
}
Your editor would scream at you (with little red marks like what your 2nd grade teacher would use on your spelling homework) because the datastore doesn't respond to the message you are sending. You go back and add that method to the protocol:
#protocol MyDataStore <NSObject> {
-(void) createContactWithName:(NSString*)aName phoneNumber:(NSString*)aPhoneNumber email:(NSString*)anEmail;
}
In your other view controller class that wants the list of email addresses you would import the same data store protocol. You would also declare a datasource property identical as what we did above using a complimentary custom init method or Interface Builder to pass the datasource in. This view controller (assuming it's a table view controller) would probably have some methods like:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.datasource numberOfContacts];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *email = [self.datasource emailForContactNumber:indexPath.row];
UITableViewCell *cell = //create tableview cell with the email string
return cell;
}
Your editor will start screaming with the little red lines and all. This is where you go and add more methods to the protocol.
#protocol MyDataStore <NSObject> {
-(void) createContactWithName:(NSString*)aName phoneNumber:(NSString*)aPhoneNumber email:(NSString*)anEmail;
-(NSInteger) numberOfContacts;
-(NSString*) emailForContactNumber:(NSInteger)index;
}
The little red lines go away and finally you can begin thinking about how the contacts are stored and retrieved. Create a separate class called MyDataStoreImpl which extends NSObject and imports and follows the "MyDataStore" protocol. Fill out implementations of all of the methods and you should be up and running. It could be as simple as storing NSDisctionary objects containing the contact info in an internal NSMutableArray property.
- (id)init {
self = [super init];
if (self) {
self.allContacts = [NSMutableArray array];
}
return self;
}
-(void) createContactWithName:(NSString*)aName phoneNumber:(NSString*)aPhoneNumber email:(NSString*)anEmail;
{
NSDictionary *newContact = [NSDictionary dictionaryWithObjectsAndKeys:
aName, #"name", aPhoneNumber, #"phone", anEmail, #"email",
nil];
[self.allConstacts addObject:newContact];
}
-(NSInteger) numberOfContacts;
{
return [self.allContacts count];
}
-(NSString*) emailForContactNumber:(NSInteger)index;
{
[[self.allContacts objectAtIndex:index] valueForKey:#"email"];
}
The advantages here are many. You can later re-implement the datasource to read/write from a plist file, network server, or database without touching any of your controllers. Also, your app will be easier to optimize for performance because you can design the read write methods to pull directly from a source instead of naively copying data from one array to another as you would if you were worrying about how it is managed too early. All of the above thrown together without testing and likely has errors but given to illustrate a point of how to properly share data between controllers without Singletons while maintaining a testable and easily maintainable codebase.
You can stick this to any class to make it a singleton:
+(MySingleton *)singleton {
static dispatch_once_t pred;
static MySingleton *shared = nil;
dispatch_once(&pred, ^{
shared = [[MySingleton alloc] init];
shared.someVar = someValue;
});
return shared;
}
-(void) dealloc {
abort();
[someVar release];
[super dealloc];
}
Better yet, you can add the class as an ivar of the application delegate, which is a singleton you already have. You can get a reference to it like this:
// AppDelegate or whatever name
AppDelegate *delegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
Then you access the datastore as an ivar on that delegate, and optionally implement one of the several persistence technologies available on iOS, basically plist files through direct file access or NSCoding or even NSUserDefaults (which you shouldn't but it's handy for small tasks), Core Data, or SQLite.
If you are using this data store class only to pass data between controllers, you can do so directly instead. Example:
CitySelectionVC *citySel = [[CitySelectionVC alloc] initWithCities:self.cities];
[self.navigationController pushViewController:citySel animated:TRUE];
[citySel release];
I always use SynthesizeSingleton.h by Mike Gallagher. He has a really informative article relating to this topic here. You should really check it out. It makes the creation of Singleton classes really easy.
Assuming your myContactsStore object has a method contactsArray which returns the internal NSArray object, you can do this:
NSArray *emails = [myContactsStore.contentsArray valueForKey:#"email"];
NSLog(#"output: %#", emails);
Which should output:
output: (
"PaulDoe#Mac.com",
"PaulDoe#Mac.com",
"RedCat#iwon.com",
"xxxbct#mac.com",
"xxxbct#mac.com"
)
You simply have to enumerate through the array and retrieve the data you want. Like so:
NSMutableArray *emails = [[NSMutableArray alloc] initWithCapacity:myContactsStore.count];
for (ContactClassName *contact in myContactsStore) {
NSString *email = contact.eMail; // I'm assuming your ivar eMail is also a property
if (email) [emails addObject:email];
}
You now have an NSMutableArray containing just the list of emails. If you want to make this list immutable simply do:
NSArray *emailList = [emails copy];