Currently whenever I want to save a custom object called List I use
(Core Date + Magical Record)
List *list = [List MR_createInContext:_managedObjectContext];
Now I'm wondering whether I could instantiate a List item like this
List *localList = [[List alloc] init];
// set some properties
localList.name = #"foobar";
List *newList = [List MR_createInContext:_managedObjectContext];
newList = locaList
Will this cause any problems with Core Data/memory issues?
No, for a couple of reasons:
You can't use init with managed objects. The designated initializer is initWithEntity:insertIntoManagedObjectContext:. There's also a convenience constructor on NSEntityDescription called insertNewObjectForEntityForName:inManagedObjectContext:. If you don't use one of those, you'll have problems.
When you assign newList = localList, you throw away the previous object in localList with all of its data. All that's left after this point is the one you originally assigned to newList. Your assignment to localList.name, for example, disappears with the localList object.
Since you've defined List it's hard to say whether you're creating a List instance correctly in both cases. At the very least your code leaks the second List that you create, and it seems unlikely that that code does what you think it does.
Your code is equivalent to:
List *localList = [[List alloc] init];
// set some properties
localList.name = #"foobar";
List *newList = localList;
Related
I've realized that several of my list view controllers behave in the same way, and now I want to abstract them into a generic one called ListVC. The plan is to create an instance of ListVC when its needed, and pass into it all of the specific things needed for that instance of it.
For example, if I need a list of customers I would do something like:
ListVC *customersVC = [[ListVC alloc] init];
customersVC.tableArray = self.customersList
In ListVC, there are times when I need to know certain object's class type. In my example, the objects in the array self.customersList are from the class CustomerClass. I know I can convert strings to class names but that doesn't help when I have a method inside ListVC that needs to return the object's type. For example, in ListVC, this old non-abstracted method:
- (CustomerClass *)customerAfterFilter
should be something like:
- (self.objectClass *)objectAfterFilter
And I'd set objectClass after it was instantiated like so.
ListVC *customersVC = [[ListVC alloc] init];
customersVC.tableArray = self.customersList
customersVC.objectClass = [CustomerClass class];
How do I do something like this? Or if my approach is just wrong, please suggest the correct approach. I'm a beginner in programming.
You can't change the return type like that. What you can do is return an id, which is a pointer to an object of any class.
- (id)objectAfterFilter
EDIT:
Customer *c = [customersVC objectsAfterFilter];
[c duCustomerStuff];
Alternatively:
[((Customer *)[customersVC objectsAfterFilter]) doCustomerStuff];
I have an object list according to a tree structure.Here is the sample code.
Model model1 = [[Model alloc]init];
model1.name = #"ABC";
Model *model2 = [[Model alloc]init];
model2.name = #"DEF";
Model *model3 = [[Model alloc]init];
model3.name = #"GHI";
Model *model4 = [[Model alloc]init];
model4.name = #"JKL";
[model3.arr addObject:model4];
[model2.arr addObject:model3];
[model1.arr addObject:model2];
Is there any way to get a particular object without looping each and every other object.
Thanks in advance.
Rather than using a array (I assume that is what Model.arr is) to hold the sub-models, use a dictionary as this provides fast look-up of objects without the need to trawl through the complete collection.
However in order to use a dictionary, you are going to need to supply a unique key in order to access the object.
I would also recommend not exposing arr as that means implementation changes will break dependent code; instead provide methods to add, fetch and remove sub-models:
- (void)addModel:(Model *)model forKey:(NSString *)key;
- (Model *)modelForKey:(NSString *)key;
- (void)removeModelWithKey:(NSString *)key;
I have an Array comprised of further sub-Arrays
I want to display a summary of the contents of the sub-arrays into a TableView with the count of occurrences of each entry. I have determined that the best and easiest way is through a NSMutableDictionary as an intermediate step.
I declare the dictionary in my implementation
#implementation ReviewViewController
{
NSMutableDictionary *dict;
}
and down in my methods I initialise and use it like so:
dict = [NSMutableDictionary new];
[dict setObject:[Observation entryCount] forKey:[observedItem species]];
The swapping of key and object is deliberate as its the count I want. I'm using the fact that values are retained, but keys are overwritten, so if i swap them round i get the curation for free.
It works!, but every time the method is invoked, the Dictionary is clobbered by the re-initalization so I only get the last thing entered. Anywhere else and it falls out of scope.
if I pass it as an arguement in the method name instead, I get the message "Local declaration of 'dict' hides instance variable ". The code is already an irreducable set of parts, so
so, where is the correct place for the instantiation?
I'd love to make my contribution here as a meaningful thanks, but before I can do that I'm going to look silly with such questions.
You would usually initialise it in your init method. For a view controller this is usually the following:
- (id)initWithNibName:(NSString*)nibName bundle:(NSBundle*)bundle {
if ((self = [super initWithNibName:nibName bundle:bundle])) {
dict = [NSMutableDictionary new];
}
return self;
}
I don't understand what you mean by "Anywhere else and it falls out of scope.". It's an instance variable. It is therefore in scope in any method in the class.
By the way, I would name your instance variables with an underscore prefix, e.g. _dict. This is common convention and it helps you to remember when using it that it's an instance variable.
I have an iPhone application and I do this in my MyView1Controller:
MyView2Controller *myV2C = [[MyView2Controller alloc] initWithNibName:#"MyView2" bundle:nil];
myV2C.shareObject = self.shareObject;
[self.navigationController pushViewController:myV2C animated:YES];
[myV2C release];
So I push shareObject to the next ViewController. There, in viewDidLoad, I set a property of shareObject like this:
self.shareObject.myText = #"Test String";
So in MyView2Controller, everything is okay, the String is set. But going back to the previous MyView1Controller with the left upper "back" Button, the value of shareObject.myText is not set to Test String.
So, how can I do this? I want to give the View2Controller an object which can be modified, and the modifications I want to have in the View1Controller.
Does anyone know? Thank you in advance & Best Regards, Tim.
OR you can even try using the Singleton pattern
http://www.cocoadev.com/index.pl?SingletonDesignPattern
You can use delegation pattern and/or key value observations
EDIT:
You can achieve this my creating a single object, and then use that object in all classes, wherever you want. For this you can use singleton class, Or you can create a class method. For ex:If I have class A, and I want to push some values in B class, So if I modify the values in B, the newly updated value can be retrieved in a too, or in any other class. In that case, you can create a different class (usually subclass of NSObject),and then write the getter/settor methods in that.
Suppose the name of this newly created class is Manager, then in Manager. m create getter/setter methods, like
NSString *strGlobal;
+(void)setString:(NSString *)strTemp
{
if(!strGlobal)
{
strGlobal = [[NSString alloc] init];
}
//point to same location
strGlobal = strTemp;
}
+(NSString *)getMySavedString
{
return strGlobal;
}
Now In you class A , where you want to send the value to Class B controller, call the setter method to set the value, like: -
-(void)navigateto_ClassB
{
//Setting the value, that should be sent to the other controller
[ManagerClass setString:#"Hello"];
[self.navigationController pushViewController:[[[ClassB alloc]init] autorelease] animated:YES];
}
Now In class B (Or wherever you want to get the saved value, use getter method, like:-
NSString *strSavedValue = [ManagerClass getMySavedString];
No you will have the value, If you want to update the value from anywhere, the again call the setter method, with new value. For ex, i want to update the value in class B, then
[ManagerClass setString:#"Hello Upadted"];
Now this value is updated to same memory location, retrieve it from anywhere using getter method created in Manager class.
As I stated earlier, this is the easiest but not the best approach. Alternatively, you can achieve same functionality with delegate patterns, KVOs (Key value observations) and/or singleton class.
tia was right: "You did it right already, so there must be something wrong somewhere".
It was my fault, so the source code in my question is correct.
OK, maybe I'm not seeing clear anymore and hope you can help.
I'm trying to select an Object from a NSMutableArray using:
if([car.seat isEqualToString:#"fancyOne"]){
fancyThings = [[NSMUtableArray]init];
[fancyThings addObjects: car];
}
Now I forgot to tell you I'm new at this Objective-C, so maybe I'm thinking the wrong way.
What I'm basically trying to do is to get an Object from one array by selecting a value of it's components.
This is the way to do it, I am however keep having trouble with my if-statement.
If I leave out the IF-statement it does fill my other NSMutableArray with the exact same object (thisCar) but if I put in the IF-statement it doesn't pick up that the string is the same in thisCar.seat.
I next example it puts everything in the normalThings but there are some aCar.seats which contain the string FANCYONE. I checked the XML file on spaces and that sort of things but everything is in order as far as I can see.
Shall I build it using NSScanner instead of IsEqualToString?
- (void)viewDidLoad {
appDelegate = (XMLAppDelegate *)[[UIApplication sharedApplication] delegate];
appDelegate.fancyThings = [[NSMutableArray alloc]init];
for (CARS *aCar in appDelegate.someCars) {
if ([aCar.seats isEqualToString:#"FANCYONE"]){
[appDelegate.fancyThings addObject:aCar];
}
else {
[appDelegate.normalThings addObject:aCar];
}
}
self.title = #"Cars";
super viewDidLoad];
}
EDIT:
My BAD!! The code supplied was in fact in order!
There was a mistake in my XMLParser, which added blank lines to the strings, so I couldn't get an equal string!
Hopefully this will give you some guidance:
//init new array
NSMutableArray *fancyThings = [[NSMutableArray alloc] init];
//walk your array
for (SomeCarObject *thisCar in arrayOfCars) {
//is thisCar a qualifying object
if ([thisCar.seat isEqualToString:#"fancyOne"]) {
//yes, add thisCar object
[fancyThings addObject:thisCar];
}
}
You'll want to create that NSMutableArray outside of the for loop (assuming you're iterating through a collection). Then you can add to that NSMutableArray like you did.
Hope this helps!
BTW, you should edit your question with the comment you made to elaborate on it..
It's depends from volume of objects, which u deal with. If there is 1000 objects or less, this method looks good. But if there is more objects, u have risk to freeze u application and have a big memory leaks.
Also if u will need concurrency code later, u have to keep in u mind some
other solutions.
U can using not just a string objects in u array, u can try to fill u array after application startup in objects, which response if string is same or not. Or using nsdictionary with appropriate keys.
Please read my post multithread search design