Curious about NSButtonCell state - objective-c

I have a NSTableView with an NSTableColumn with an NSButtonCell (a checkbox) inside it, which generates a new instance of NSButtonCell each time a row is added, which I configured in IB. However, I'm curious why in the following chunk of code the second NSLog returns 0.
NSLog(#"%ld", (long)[[self.tableView preparedCellAtColumn:0 row:0]state]);
[[self.tableView preparedCellAtColumn:0 row:0]setState:1];
NSLog(#"%ld", (long)[[self.tableView preparedCellAtColumn:0 row:0]state]);
The fact that it returns 0 means that I am sending a message to an instance of NSButtonCell, right? So why doesn't setState: change the return value of the second NSLog?

If it was receiving nil it would also print 0, I would suggest trying this
NSLog(#"cell:%#", [self.tableView preparedCellAtColumn:0 row:0])
to ensure you are actually getting a valid cell object from the table view.
Where are you calling that code from? After the table is already being displayed? During initialisation?
If the former then there should be a cell available, if the latter then it may not have been created or reallocated from the pool yet.
Try the NSLog command above to ensure you are actually getting a cell back and not nil from the table view.

Related

OSX NSTableView insertRowAtIndexes

i already checked Using NSTableView insertRowsAtIndexes solution but It does not solve my problem.
i want insert row in nstableview at particular index(add dynamically)
index Set is valid, still it causes Program crash
NSIndexSet *indexSet=[NSIndexSet indexSetWithIndex:i];
[myTableView insertRowsAtIndexes:indexSet withAnimation:NSTableViewAnimationEffectFade];
1)is any thing wrong in my code?
2)Is there any another way to add row at particular index(add dynamically)?
The code is correct but first you have to insert the model object in the data source array to keep model and view in sync.
I got My mistake..... problem In other Code so This code is fine
But I want to add some points About insertRowsAtIndexes: method
Hope it will helps to other people
1)Dont called reloadData() because you are adding particular number of rows so calling reloadData() will reload all data and it will causes crash
2) Calling this method multiple times within the same beginUpdates and endUpdates block is allowed, and changes are processed incrementally
3)Most Important thing is indexSet must be within range
if you are Enter valid indexSet then The numberOfRows in the table view is automatically increased by the count of indexes.
4)you can select animation according to your need
Sample Code :
[yourTableView beginUpdates];
NSIndexSet* theIndexSet = [NSIndexSet indexSetWithIndex:[self.yourTableContents count]-1];
[yourTableView insertRowsAtIndexes:theIndexSet withAnimation:NSTableViewAnimationEffectFade];
[yourTableView endUpdates];

ARC deallocate my NSmutablearray before NSTableview reloaddata

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

How do you correctly get a row value from a table view?

I have implemented code that returns 0 every time. I'm trying to remove a string from a mutable array with the row value selected after hitting a button.
Related code:
- (IBAction)remove:(id)sender {
NSIndexPath *selectedIndexPath = [_tableView2 indexPathForSelectedRow];
[names removeObject:[NSString stringWithFormat:#"%i",selectedIndexPath.row]];
testLabel.text=[NSString stringWithFormat:#"%i",selectedIndexPath.row];
[_tableView2 reloadData];
}
The test label shows 0 every time the button is pressed, no matter where the tableview is selected.
Let me know if there is other relevant code (like the tableView) that you want me to post.
For a UITableView, the selected row concept is only valid while the user is touching the row. For that reason indexPathForSelectedRow is documented as returning “An index path identifying the row and section indexes of the selected row or nil if the index path is invalid.”
My opinion is that you are obtaining a nil result, and later calling the row method in that nil results in the zero that your are seeing as your name.
The solution depends on the rest of your data source implementation, but probably will involve storing the tapped index in didSelectRowAtIndexPath: to later use it in your remove method.
(I supposed that you are not using the allowsMultipleSelectionDuringEditing option nor are you editing the table).
Instead of:
[names removeObject:[NSString stringWithFormat:#"%i",selectedIndexPath.row]];
Try:
[name removeObjectAtIndex:selectedIndexPath.row];
Also, instead of using #"%i", try using #"%d" as mentioned here
Hope this helps!

Unexpected behavior with NSMutableOrderedSet

Using an NSMutableOrderedSet, I'm getting unexpected behavior.
I set an object at index 0. In the next call, I read out the object at index 0. How is it that the pointer I get back is not the same as the one I just inserted?
- (void)setRecentObject:(SomeObject *)recentObject
{
// self.activeQueue is a viable instance of NSMutableOrderedSet
[[self activeTileQueue] insertObject:recentObject atIndex:0];
SomeObject *whatIJustInserted = [[self activeTileQueue] objectAtIndex:0];
DebugLog(#"set url at zero: %#, and read back url at zero: %#",[recentObject someDescription], [whatIJustInserted someDescription]);
}
To my thinking, at the end of this method, recentObject should == whatIJustInsereted -- and yet both in my logging statement and when I evaluate the pointers after setting a breakpoint, the objects are different instances of SomeObject. Is there something I don't understand about NSMutableOrderedSet?
The reason this did not behave as expected is because the receiver activeTileQueue (the NSMutableOrderedSet instance) already contained the member.
While I specifically sought the use of a set versus an array because I didn't want duplicates of any objects inserted, my assumption about how the insertion would work in this case was incorrect. I assumed that if the set already contained the member I was attempting to insert, that rather than be re-insereted, the member would be repositioned to the index passed in -insertObjectAtIndex. This was incorrect.
If the receiver already contains the member, it is not re-inserted or re-ordered. In short, nothing happens. To obtain the originally desired behavior, I would have to either remove the original member and re-insert it, or use another method on NSMutableOrdered set to reposition/exchange the index within the set, eg:
NSIndexSet *replacementSet = [NSIndexSet indexSetWithIndex:[[self activeTileQueue] indexOfObject:recentObject]];
[[self activeTileQueue] moveObjectsAtIndexes:replacementSet toIndex:0];

How do I set an uninitialized value in Objective C?

This question might be off base, but here's the problem I'm having:
I'm trying to run an example from the iPhone SDK, and I'm running into an access violation. I've traced down some behaviour that I think is suspicious.
Here's what the class looks like:
#interface TableViewCell : UITableViewCell {
#private
UILabel *_earthquakeLocationLabel;
UILabel *_earthquakeDateLabel;
UILabel *_earthquakeMagnitudeLabel;
UIImageView *_magnitudeImageView;
}
When I set a breakpoint in
- (id)initWithFrame:(CGRect)frame reuseIdentifier:(NSString *)reuseIdentifier
And look at "self" in the debugger, it shows that _earthquakeDateLabel is "0x12", _earthquakeMagnitudeLabel is 0x1000, and the other two are zero. If I try to assign to either of the nonzero ones, I get an access violation.
I'm guessing what's happening is that these have bogus values in them, and when I try to assign to them, that tries to decrement a reference on the bogus value and blows up. But as I said, I'm fairly new to Objective C, so I may be off base.
So my question is, is there anything special about initializing these values that I should be doing? Or any way to assign to the value when it has a bogus value in it?
Some additional information:
So if I assign nil to _earthquakeDateLabel and _earthquakeMagnitudeLabel in initialize, that fixes the problem. But I don't understand why the object is created with values in those fields; I expect them to be nil. The object is being created on the heap:
TableViewCell *cell = [[[TableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:MyIdentifier] autorelease];
It sounds like the self pointer is bogus. The values 0x12 and 0x1000 are integer constants; they're definitely NOT pointers to valid memory addresses. The fact that you are seeing those values indicates that something is wrong, and attempting to manipulate them in any way (reading or writing them) will result in badness. In this case, you're getting an access violation because you're trying to write to memory addresses 0x12 and 0x1000, which are invalid addresses.
How are you creating the TableViewCell objects? Are you doing TableViewCell *myCell = [[TableViewCell alloc] initWithFrame:...]? That is the correct way.
Now I'm going to invoke my psychic debugger: my guess is that you're forgetting to declare your TableViewCell object with a pointer, i.e. you're declaring it as TableViewCell myCell instead of TableViewCell *myCell (note the presence of the asterisk). This will create the object on the stack instead of the heap, and as a result, it will have garbage in its data members, instead of zeros. Objective-C objects, when properly allocated, will have all of their data members initialized to 0 (or NULL, nil or false, depending on the data type) after a successful call to alloc.