how is it possible to save an array in multiple locations ie. different view controllers in order to save the data in the arrays and allow it to be used afterwards by a table?
edit
objective c i have an ibaction with code
[[NSMutableArray alloc] init];
[favoritesArray addObject: #"one"];
//and in the fav table view this code//
favoritesArray = [[NSMutableArray alloc]init];
didContain = [[NSMutableArray alloc]init];
if ([favoritesArray contains:#"one"]);
{ [didContain addObject:#"trial"]; }
however its crashing at the if part...
[[NSMutableArray alloc] init];
[favoritesArray addObject: #"one"];
I assume you actually have the “favoritesArray =” in the original code, and simply missed it when copying. Otherwise, you're dropping the array on the floor and favoritesArray still holds nil.
if ([favoritesArray contains:#"one"]);
{ [didContain addObject:#"trial"]; }
however its crashing at the if part...
There are two problems with your if statement:
NSArray does not respond to contains:, which is what the crash is telling you. You need to send your array a message it does respond to, such as containsObject:, which is listed in the documentation.
As I indicated through the formatting I applied to your code, the if statement does not relate to the { [didContain addObject:#"trial"]; } statement that follows it.
That's because you put a semicolon after the if condition. An if statement does not take a semicolon between the condition and the statement; the statement must directly follow the condition (i.e. be immediately after the )). Moreover, a semicolon by itself is a valid, empty statement.
So, you have an empty statement subject to the if (if the favorites array contains #"one", do nothing), and you have the statement you meant to have controlled by the if standing on its own, unconditional.
Cut out the semicolon after the if so that the { … } binds to the if instead of being a separate statement.
Alx, are you trying to access the data in favouritesArray from multiple objects? This is what I think you are trying to do, but without more context it is difficult to suggest a solution. Here is one possible approach:
Declare favouritesArray as a property in your controller class. (You could use #property and #synthesize to achieve this.)
Then, in your views, add your controller as an IBOutlet (called, say, myController). Then make connections in Interface Builder between your view and the controller. You will then be able to access the array from your view classes by writing:
[[myController favouritesArray] objectAtIndex:3], for example.
In general, it is a bad idea to 'copy' data between different objects in your program. Unless there's a very good reason to do this, use references instead. Try to think about what object is the 'owner' for that array, and put it in that class.
Related
My NSMutableArray lOfSegments, declared as IVAR, get populated correctly. During the debug it shows 4 object in the array.
for (int x=0; [arrayOfSegmentsTcIn count]>x; x++) {
NSDictionary *segmentDic=[[NSDictionary alloc] initWithObjectsAndKeys: [arrayOfSegmentsNumbers objectAtIndex:x],#"segment",[arrayOfSegmentsTcIn objectAtIndex:x],#"tc_in",[arrayOfSegmentsTcOut objectAtIndex:x],#"tc_out", nil];
[lOfSegments addObject:segmentDic];
[myDMXML.segments addObject:segmentDic];
}
[self.xmlTCLable setStringValue:[myDMXML startTimeCode]];
[self.xmlDurationLable setStringValue:[myDMXML duration]];
[self xmlValidationCheck];
NSLog(#"arrayController:%#",[lOfSegments valueForKey:#"segment"]);
[self.tableViewOutlet reloadData];
NSLog list the array correctly but when reloadData is executed the code jumps to
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
return [lOfSegments count];
}
The array is null.
The Object is initialised in viewDidLoad as
lOfSegments = [[NSMutableArray alloc]init];
Please Help!
First, I recommend making your code more clear here by using self.lOfSegments rather than directly accessing an ivar. (The fact that the ivar lacks a leading _ is very suspicious as well, and raises the question of whether this is even the variable you think it is.)
On the assumption that this is the variable you think it is, and that you have overridden the standard behavior to make the ivar match the property or created explicit ivars (neither of which you should do), there are several common causes for this kind of problem:
The most likely cause is that you called your initialization code prior to viewDidLoad and then viewDidLoad blew away the array. Many things can run prior to viewDidLoad, and viewDidLoad can run more than once (at least this used to be true; I'd have to study whether the view-loading changes in iOS 6 made it guaranteed to be run once.)
You have some other way reset lOfSegments between the time your initialization code ran and the time reloadData ran. If you would reliably use self. then you could override setLOfSegments: so you could log this. Or you could mark this property readonly so you could prevent it. Thats one of many reasons that you should use properties, not ivars.
The setting code failed to run before reloadData. Ensure that the log statement actually printed prior to getting to reloadData and is on the same queue (the queue identifier will be part of the NSLog output in brackets). I don't think this is likely given your description, but it is a common problem.
There are two instances of this object. Make sure that the object that ran your initialization code is the same object that ran reloadData. This is a more common mistake then you may think. Log self and make sure the memory address is the same in both cases.
looks like you have variable with same name lOfSegments in method viewDidLoad. So in viewDidLoad you use stack variable, in numberOfRowsInTableView - instance variable.
Or maybe tableViewOutlete.dataSource pointing on different viewController
for now i am creating my NSMutableArray using:
#define ARRAY_OF_ORDER_SOURCE [NSArray arrayWithObjects:DICTIONARY_OF_ORDER_SOURCE_ALL,DICTIONARY_OF_ORDER_SOURCE_ECOMMERCE,DICTIONARY_OF_ORDER_SOURCE_PHYSICAL,DICTIONARY_OF_ORDER_SOURCE_INVOICE,DICTIONARY_OF_ORDER_SOURCE_RECURRING,DICTIONARY_OF_ORDER_SOURCE_SALESVU,DICTIONARY_OF_ORDER_SOURCE_RESERVATION,nil]
i want to do some thing like:
if(somethingIstrue)
[ARRAY_OF_ORDER_SOURCE addObject:DICTIONARY_OF_ORDER_SOURCE_ALL]
if(somethingElseIstrue)
[ARRAY_OF_ORDER_SOURCE addObject:DICTIONARY_OF_ORDER_SOURCE_ECOMMERCE]
i am doing this as i need this array in my whole project, i have this in constant.h file.
how can i acheive this using macro??
Thanks.
If you really want to have a macro for this you can have a multiline macro and placed there the logic you want. It is not totally clear to me what you want to achieve but instead of macro I would prefer to have a category on NSMutableArray returning the array or some kind of Util class doing so.
There are numerous things wrong with your question. For starters, you claim you are creating an NSMutableArray, but you are in actuality creating an NSArray. You then try to addObject on the immutable array, which you cannot do.
In your line (note I modified it to add a comment):
if(somethingIstrue) {
// The NSArray isn't assigned to anything and tries to addObject to an NSArray
[ARRAY_OF_ORDER_SOURCE addObject:DICTIONARY_OF_ORDER_SOURCE_ALL]
}
you are not assigning the array to anything (as I already noted it won't work because it is trying to add to an NSArray).
I think you want to do something like:
NSMutableArray *orderedSource = [NSMutableArray array];
if (somethingIsTrue) {
[orderedSource addObject:addObject:DICTIONARY_OF_ORDER_SOURCE_ALL];
}
if (somethingElseIsTrue) {
[orderedSource addObject:addObject:DICTIONARY_OF_ORDER_SOURCE_ECOMMERCE];
}
The question you have to ask yourself is why do you insist on using a macro? You have no real design/approach here, which is why your ideas are coming across as scattered.
If you need to consistently create an array based on a set of constraints, one approach would be to create a class which can vend for you the array you want based on criteria. Or you can just do it where you need to using the approach above.
I am learning Objective-C, and as one of the lessons, we create a class Employee, and its superclass Person, along with an Asset class, whose instances are owned by Employee. To test the classes, and their instance functions, I wrote the following code
int main(int argc, const char *argv[]){
#autoreleasepool{
NSMutableArray *employees = [[NSMutableArray alloc] init];
for (int i = 0; i < 10; i++){
Employee *person = [[Employee alloc]init];
[person setWeightInKilos:90 + i];
[person setHeightInMeters:1.8 - i/10.00];
[person setEmployeeID:i];
[employees addObject:person];
}
.../*code continues from here, to assign [person]
's at random indexes in *employees, instances of the Asset class */
}
}
I was wondering what are the benefits or disadvantages to setting the [person] with one method, which in turn calls the other methods, like so:
main.m:
....
for (int i = 0; i < 10; i++){
Employee *person = [[Employee alloc]init];
[person setWeightInKilos:90 + i withAHeightOf:1.8 - i/10.00 andId:i];
[employees addObject:person];
}
....
Thanks.
Basically there isn't any right and wrong here, objective-c syntax and coding conventions allow you to have long messages with multiple parameters.
There are a couple of options here:
Setting these parameters on init (e.g. initWithId: height: weight:)
Creating a property for each of them
Creating an individual function for each of them
Creating a setProperties function
To decide this you should first ask yourself:
Does these triplets (Height, Weight, Id) belong together logically?
Does it make sense to set just one of them?
Does it makes sense that this object is missing these values?
Is there a need to make setting these parameters an atomic action?
Does Immutability of the object matters?
Most of the time I choose to make my object immutable, which means I create a readonly property for them, and set them via init function.
Your Person class has several properties including weightInKilos, heightInMeters, and employeeID.
You can, of course, set each property individually. As a convenience, you can provide special "helper" methods that make it easier to set several properties in one call. This is completely optional. Whether you choose to add these extra methods is strictly a matter of personal taste and style.
One consideration for such "helper" methods is where to draw the line. Which properties should be parameters to such methods? What happens if you later add another property? Do you update the "helper" methods to take another parameter and then update all code calling those methods?
In many cases it's better to just set each one individually. One guideline I use for deciding on whether to create such a "helper" method is if the object requires a certain set of properties to be set to be valid. If there is such a case then I usually create a special init method that takes the required properties as parameters. Then all of the optional ones can be set individually.
You neglected to show how you've defined the Employee object. Are weight, height and identification held as properties? If so, they generally will have accessor methods automatically generated for them so you will not need to write those routines. Properties have nice conveniences associated with them.
As to why you would use one method over another, the most compelling reason is a matter of personal style. Something to consider -- what happens if you choose to change the stored weight of a person; do you have a method to set only that parameter, or do you need to set everything about them?
It's common to have an initializer that receives the information to be initialized about an object, but something like - (id)initWithWeight:andHeight:andId:andSomethingElse:andMoreStuff: gets ugly far sooner than I've stretched it out. To solve this, the NSDictionary class can be helpful, where the dictionary contains all the fields you choose to include and the method becomes - (id)initUsingDictionary:(NSDictionary *)dictionary;. A nice benefit to this is you can easily make fields optional and a single method signature handles it.
I do not understand the Objective-C in the following method taken from Apple's Master Detail Template:
- (void)insertNewObject:(id)sender
{
if (!_objects)
{
_objects = [[NSMutableArray alloc] init];
}
[_objects insertObject:[NSDate date] atIndex:0];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0
inSection:0];
[self.tableView insertRowsAtIndexPaths: #[indexPath]
withRowAnimation: UITableViewRowAnimationAutomatic];
}
The code is in the MasterViewController.m file. The points of confusion for me are:
- what does #[indexPath] mean? Is this a syntax for making something an array. I have only run into the '#' as the character denoting a string. Clarification: I understand what an NSIndexPath is and how it functions. I am not familiar with the syntax for putting an object in brackets preceded by the # character. Does this make something an array? What if I had several NSIndexPaths? Can I load all of them into an array in this manner #[indexPath1, indexPath2, indexPath3] Does this work with anything derived from NSObject? Is the result always an array? Where is this documented in the language - what is this language feature called (so I can look it up)?
The method insertRowsAtIndexPaths:withRowAnimation seems to specify the locations to put something into the table but not exactly what to put. How does the method know what object to use as the data source when inserting items into the table. The delegate and data source relationships are specified in the xib so it is apparent that the MasterViewController will handle the association of data with the table, but there does not seem to be any relationship with the NSMutable *_objects; array and the table specified anywhere.
Thanks for the help in explaining this as it is apparent I am missing some pretty basic stuff.
Is this a syntax for making something an array
Yes. In modern Objective-C, as understood by the latest clang compiler, there are some more # directives for easily creating hard-coded objects:
#[object1, object2]
creates an NSArray;
#{#"key1": value1, #"key2": value2}
creates an NSDictionary,
#"hello world"
creates an NSString, as usually, and
#1, #2, #YES, #3.1415927
create NSNumber instances, respectively.
How does the method know what object to use as the data source when inserting items into the table.
It uses the data source currently set on the table view it is called on.
I'm sure I'm doing something silly, but this is driving me crazy.
I'm trying to loop through database results, create objects from those results, and add the objects to an NSMutableArray. I've verified via NSLog calls that the data is being correctly read from the database and copied to the object, but the count for the NSMutableArray always returns 0.
Here's the essence of the code:
while ([rs next]) {
Kana *htemp = [Kana alloc];
htemp.content = [rs stringForColumn:#"hiragana"];
[hiragana addObject:htemp];
}
NSLog(#"Hiragana contains %d objects", [hiragana count]);
Kana is derived from NSObject, and hiragana is an instance of NSMutableArray.
I'm sure this is a rookie mistake, and I hope someone can set me straight. TIA! :)
My guess, judging from the code you posted, is that you probably aren't allocating your array properly. When creating objects, you need to initialize them as well. Therefore, this:
Kana *htemp = [Kana alloc];
Should be:
Kata *temp = [[Kana alloc] init];
All objects need to be initialized this way. Thus, if I'm correct and you haven't initialized your array, then your creation needs to go from this:
NSMutableArray *hiragana = [NSMutableArray alloc];
to this:
NSMutableArray *hiragana = [[NSMutableArray alloc] init];
For optimization reasons, you should probably also specify an initial capacity as well if you have any idea how many objects you might hold:
[[NSMutableArray alloc] initWithCapacity:someNumber];
Another common cause (not in your case, as it turns out, but generally) is forgetting to even allocate the array. If you haven't created an array yet, you're sending that count message to nil, so the result will always be 0.
A few things:
What happens if you put an NSLog call inside of the while loop? Verify that loop iterations are actually happening before blaming it on the array.
Where are you creating the array hiragana? If you are doing it incorrectly for some reason and the array is nil, it might cause problems like this.
If you do not have garbage collection on, be sure to do [htemp release] after adding it to the loop. addObject retains and each added item will leak from the loop. Again, this is only relevant if garbage collection is off.
It's most likely either you aren't created the array correctly or rs doesn't contain what you expect it to contain, and so [rs next] isn't getting called ever (if rs is nil, for example, no iterations of this loop would execute and you wouldn't have any sort of error).