My appDelegate class contains an NSMutableArray called blocks, which is an array of custom block objects.
My viewcontroller class has another NSMutableArray called blockViews, which is an array of custom blockView objects. In its init method, it sets it backgroundcolor to a color passed in the parameter, and does some fancy stuff with the border.
Whenever an object is added to my blocks array, I would like to also add a corresponding object to my blockViews array in my viewcontroller, which shares the same location as the location passed to the block object in the blocks array, and adds itself as a subview to the viewcontroller.view.
I would preferably like to use KVO to check whenever an object is added to the blocks array, and then add an object to the blockViews.
I'm relatively new to objective-c programming, but how might someone accomplish this?
Peter Hosey's answer to another question will tell you what you need to know about KVO with NSMutableArray.
In your case, the thing observing the NSMutableArray should be your view controller.
Related
Im passing a NSManagedObject to a UIView. So Im showing a UITableView of meetings brought from CoreData, if you tap on one of the meetings you will be able to see, on another view, more info of that meeting, info that is contained in a NSManagedObject. I want to pass that NSManagedObject to the view that will show its info.
So I created a init method of that view like this:
-(id)initWithMeeting:(NSManagedObject *)aMeeting{
_theMeeting = aMeeting;
return self;
}
Then I use the info in the _theMeeting object to show it in the view that I just created in the ViewDidLoad. The problem is that whenever I try to access any of the values of the NSManagedObject it crashes, it has values in the init but not in the ViewDidLoad.
I believe it has something to do with the Managed Oriented Context, but the Managed Oriented Context never disspears, is an attribute of the AppDelegate.
So I dont know how to pass that Object and keep it.
I also declared theMeeting:
#property(nonatomic, copy)NSManagedObject *theMeeting;
Hope you can help me.
Are you using the accessor to assign theMeeting? I think you're just bypassing it so aMeeting is not retained or copied, and therefore the crash.
I have a bit of a problem in my code, and i'm beginning to wonder if it's a design issue..
I'm treating my appDelegate class as the primary model for my application. With the appDel class, I have a viewcontroller. In my appdelegate class I store an NSMutableArray called blocks which has all of my block object models. Similarly, in my viewcontroller I have an identical NSMutableArray called blockViews which stores all of my block object views. The way I update the view after receiving notifications from the model is through KVO. In my viewcontroller, I observe each location property of each block in my blocks array (in the app delegate), and update the corresponding blockView in blockViews.
I also have it set up so that whenever I add an object to my blocks array in the appDel, it adds an object to the end of the blockViews' array. Now, my problem arises when I try to remove an object from my blocks array (in the appDel class). I will not always be removing the last object, and so I am stuck as to how to get the actual index of the object I am trying to remove so that I can remove the corresponding index in my blockViews NSMutableArray.
In my observeValueForKeyPath method, the object being passed is the appDelegate class because I am observing the entire blocks array from my viewcontroller (I implemented the Indexed Array Accessors to allow for KVO notifications to occur), and because of this the object being passed into observeValueForKeyPath is in fact a reference to my appDelegateClass (which makes sense).
But, from this, I cannot obtain the index of which object was removed from the blocks array. Does anybody have any suggestions as to how I could alter this to provide an index, or a way to get the correct index?
Is there any way to observe an array for additions or removals, AND have the object being passed into my observeValueForKeyPath method be the block that was added/removed itself, instead of the appdelegate class?
Can't you use indexOfObject... (several variations) to get the index, and then remove it in both arrays? (You realize that NSMutableArray implements all the methods of NSArray, right?)
I have a controller class that store a list of contact and I need to share this list to objects that will implement KVO on such array.
The most obvious solution is to use a NSArray instead of NSMutableArray, in order that everyone can use the same instance variable of the controller and it's not possible modify the content of the array.
Now, let's image that this list can change every 3 minutes and only the controller can update the content of the array.
If I dealloc and re-init the contact list array, all my KVO objects will lost the reference to my array.
Finally:
NSArray PRO: No one can alter the content of the array
NSArray CON: The controller can not modify the array without a dealloc, so other objects lost the reference.
NSMutableArray PRO: Controller can modify array content, all the object can easily share the same reference of the array
NSMutableArray CON: Everyone can modify the array.
Any suggestion?
NSArray in my opinion, given that it isn't being updated very often.
The object that owns and modifies the array exposes it through a property of type NSArray*. The observers observe this property. Whenever the object that owns the array recreates it, it sets the property to the new NSArray which then triggers KVO on all of the observers.
Alternatively, you can implement the indexed accessor patterns for the property.
I have four views, with four arrays. As soon as I navigate from one view, I add that particular array to my master array.
Initially this master array has nothing, and is allocated when the app runs using 'init' method. It does not have a view and it is an array from a subclass of NSObject.
Finally the master array should consist of {viewarray1, viewarray2, viewarray3, viewarray4}.
Each array is added to the master array when navigating to the next view.
So is there anything wrong in my implementation ? Is it okay to allocate masterArray in the init method? Each time I add an object to masterArray, I NSLog it and it displays (null)
How can I have the master array retain values for the whole app??
Some Information on the Code:
I initialize my master array in another class, in the -(init) method
masterArray = [[NSMutableArray alloc] init ];
While adding an object to MasterArray from another view, I reference that class, and I create an object for the class, and add it as a property and synthesize it. I then use
[self.thatClassObject.masterArray addObject:self.viewArray1];
There are two ways you could go about initializing it that I can think of offhand. First, you could alloc/init the array in the app delegate. This will ensure it's created before the rest of the views get a chance to add to it.
EDIT: There's only really one way I can think to do this as Josh Caswell pointed out a good fact that class initializations won't work for this situation. You're best off calling alloc/init for the array either in the app delegate or whichever view is made key window first. You'll have to reference it to the other classes from there
I'm going through a simple Objective-C/Cocoa program to try and learn the language and am getting a little confused about how some things are linked from the code I write to the interface builder.
For example, I have a simple NSString:
#property (assign) NSString *letters;
And in my interface builder, I have a text field and I use the text field's bindings to connect it to letters.
However, the example also has this:
#property (assign) IBOutlet NSArrayController *wordsController;
In the view I have a table that continuously changes and shows different words and those words are stored in an NSMutableArray. I suppose I can understand that I just can't bind the array to the the table because there are some more complexities. So in the Interface Builder I create an Array Controller and bind it to the table. In the Array Controller's bindings, I bind the Array Controller to the array of words.
I understand that the last thing I have to do is also bind the Array Controller to my NSArrayController object as well. I don't understand why I do this through the main controller object by making a connection between this outlet and the wordsController. In the Array Controller's bindings section there's a greyed out option, Content Object, which says "An NSArrayController that the NSArrayController treats as its content." Why wouldn't I set the binding here? What is the significance of it being an outlet and why is it different than my NSString letters?
Thanks
You are confusing bindings and IBOutlets. This is not unreasonable -- it's a lot of Control-dragging of connections and it can be hard to keep clear what's going on. Let me try to explain:
Bindings are a way to let Cocoa handle the mechanics of keeping a model (some collection of data, even something as simple as a single NSString) and a view (an object which displays on the screen) in sync. When you "bind" your NSString to a text field's value, you are asking the framework to communicate changes to the string or the text field "behind the scenes"; your object which owns the string gets notified to change the string's value when the text field changes, and vice versa.*
A similar situation applies to your mutable array, array controller, and table view. You're essentially right about the complications: the mutable array and the table view don't know how to talk to each other; the array controller stands in between and facilitates: ("Okay, tableView wants to know what to put in row i. Array, give me your object at index i." :) In the past, you would've had to write that code manually, and it looked very similar every time you did so.
That's what the bindings do. They are a way to reduce boilerplate code. The IBOutlet to the array controller gives your object a way to send messages to the array controller, if necessary. One simple example of why you might need to do this is to allow a menu item to trigger a method in the array controller; a document object or another controller might handle the action from the menu item and call the appropriate message on the array controller. You can also ask the array controller for its arrangedObjects to get, for example, the sorted and filtered version of its content array.
* One side note here is that your NSString property should almost certainly use retain, not assign. The object that contains this variable should be responsible for its memory.