Problem with NSUndoManager - nsundomanager

I read the chapter on undo/redo in the Hillegass book. He only goes over document based applications though. I am using pretty much the same code that is in the book, but I get "appController may not respond to -undoManager" when I use the code below. I know that I have to create an Undo Manager explicitly, but exactly how do I do this. Please give me a step by step explanation. Thanks.
-(void)insertObject:(Accounts *)currentAccount inArrayOfAccountsAtIndex:(int)index
{
NSLog(#"Adding %# to %#", currentAccount, arrayOfAccounts);
NSUndoManager *undo = [self undoManager];
[[undo prepareWithInvocationTarget:self]
removeObjectFromArrayOfAccountsAtIndex: index];
if(![undo isUndoing]){
NSLog(#"After the if(![undo isUndoing]) statement");
[undo setActionName:#"Insert Account"];
}
[arrayOfAccounts insertObject:currentAccount atIndex:index];
}

I guess there is the initialization of the Undo-Manager missing.
Try
NSUndoManager *undoManager;
at the beginning of your class and
undoManger = [NSUndoManager alloc] init];
in the initialization of your class (for example in "viewDidLoad").

Related

iPhone zXing QR Scanner - didscanresult function never fires

I have loaded the zXing project into my own project.
It loads fine, the zXing scanner pops up after a button call.
I can dismiss the view controller on thezxingControllerDidCancel but when I scan a QR code, no codes are ever recognised and therefore the didScanResult function never fires.
Does anyone have any idea about this one?
The didScanResult function is below.
-(void)zxingController:(ZXingWidgetController *)controller didScanResult:(NSString *)result{
resultLabel.text = result;
NSLog(#"did scan!!!");
[self dismissModalViewControllerAnimated:NO];
}
Note: I'm not sure if this is relevant, but when the scanner comes up, I get this logged by the app: "wait_fences: failed to receive reply: 10004003"
That tutorial does not mention that you must add a QRCodeReader to the set of readers of your ZXingWidgetController.
ZXingWidgetController has a property called readers, which is an NSSet containing the instances of the readers (e.g. an instance of QRCodeReader). Roughly, the readers' task is to analyze the images your camera takes and to extract the encoded information. Your ZXingWidgetController has to know about the readers it should utilize, otherwise it has no chance to do anything meaningful. So you have to set the readers property before you present the ZXingWidget.
The ZXing project has a sample app which demonstrates this. If you use ARC, then
ZXingWidgetController *widController = [[ZXingWidgetController alloc] initWithDelegate:self showCancel:YES OneDMode:NO];
QRCodeReader* qRCodeReader = [[QRCodeReader alloc] init];
NSSet *readers = [[NSSet alloc] initWithObjects:qRCodeReader,nil];
widController.readers = readers;
[self presentModalViewController:widController animated:YES];
should do.

Default IBAction - UISegmentControl, Object-oriented design help

I have a UISegmentControl with my UITableView that sorts the data. I'd like to be able to do things:
(1) default sort (so when the user turns on the app for the first time, it would select the first segment, and sort by that action)
(2) remember where the user was between table loads. What I mean by this is, similar to Apple's coverflow, when I go to a different cover, the UITableView repopulates. So if the last time the user was there, the sort was on the 3rd segment, then it would remember that.
I'm a bit new to object-oriented design, and this was my best guess to not have the same redundant code everywhere: (MarkersList is a NSMutableArray)
- (NSArray *)sortByName:(NSArray *)sortDescriptors {
return [self.MarkersList sortedArrayUsingDescriptors:sortDescriptors];
}
- (NSArray *)sortByRSID:(NSArray *)sortDescriptors {
return [self.MarkersList sortedArrayUsingDescriptors:sortDescriptors];
}
- (void)setSortedMarkersList:(NSArray *)sortedArray {
if (self.MarkersList != nil) {
[self.MarkersList removeAllObjects];
}
[self.MarkersList addObjectsFromArray:sortedArray];
}
- (IBAction)sortButtonPressed:(UISegmentedControl *)segmentControl {
// Create sort descriptors
NSSortDescriptor *nameDescriptor = [[[NSSortDescriptor alloc] initWithKey:#"Name" ascending:YES selector:#selector(localizedCaseInsensitiveCompare:)] autorelease];
NSSortDescriptor *rsID = [[NSSortDescriptor alloc] initWithKey:#"ID" ascending:YES];
if ([segmentControl selectedSegmentIndex] == NAME) { // this is #define 0
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:nameDescriptor, rsIDDescriptor, nil];
NSArray *sortedArray = [self sortByGene:sortDescriptors];
[self setSortedMarkersList:sortedArray];
[sortDescriptors release];
}
else if ([segmentControl selectedSegmentIndex] == RS_ID) {
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:rsIDDescriptor, resultDescriptor, nameDescriptor, nil];
NSArray *sortedArray = [self sortByRSID:sortDescriptors];
[sortDescriptors release];
[self setSortedMarkersList:sortedArray];
}
[self.MarkersTableView reloadData];
}
I haven't implemented the third sort yet since it's not just an NSString or NSNumber like the other two yet. So far, I think it works correctly. However, the problem I have is to implement (1), I would need to call sortByName when my table is loaded. I could just create the NSSortDescriptors again, but that seems redundant. Is there a more OOD way to achieve this?
For (2), I'm guessing I could save that index for the table in a dictionary, and retrieve it when that table is loaded. Or something along those lines, not really sure.
Any help is greatly appreciated. Thanks!
This isn't so much an OO question, as iOS doesn't always let us use best practices to solve a problem. The best bet for your situation, I think, is to store the information on the selected sort in the NSUserDefaults. In your -viewDidLoad method, check if the selected sort object exists in NSUserDefaults, use it if it does, and if not choose a reasonable default value.
Don't worry about creating NSSortDescriptors with each load of the application, unless you have done profiling and determined that a large amount of time is spent building it. Serializing and deserializing the NSSortDescriptors would be far more inefficient than just recreating it when needed. Apple spends a lot of time optimizing frequently used classes like NSSortDescriptor.
Regarding #2, you can use indexPathsOfVisibleRows on the UITableView to get an array of visible indices, store the first one in UserDefaults, then on load (or pop from the next view controller if that occurs) call –scrollToRowAtIndexPath:atScrollPosition:animated:.
Once you're code is functioning, I recommend you watch the various videos on iTunes U regarding profiling and Instruments. It's a wonderful tool that is often overlooked, and really helps concentrate effort where it's needed.

question related to Iphone autorelease usage

Could someone help me please understand how allocation and memory management is done and handled in following scenario. i am giving a Psuedo code example and question thats troubling me is inline below:
interface first
{ NSDecimalNumber *number1;
}
implementation
.....
-(void) dealloc {
[number1 release];
[super dealloc];
}
=================================
interface second
{ NSDecimalNumber *number2;
}
implementation second
.....
- (First*) check
{
First *firstObject = [[[First alloc] init] autorelease];
firstObject.number1 = [[NSDecimalNumber alloc] initWithInteger:0];
**// do i need to autorelease number1 as well?**
return firstObject;
}
Your code is correct as is. If you autoreleased the object, its reference count would reach zero and it would be dealloced, and then if you later tried to use the value stored in number1 your app would crash.
The only enhancement I'd add is releasing any existing value. i.e.
[number1 release];
number1 = [[NSDecimalNumber alloc] initWithInteger:0];
If you don't do this, the previous object assigned to number1 will leak each time check is called.
As you're allocing the NSDecimalNumber, you need to release it. (As you're doing so in the dealloc.)
Whilst it's hard to provide a meaningful example based on your sample code (as "number1" isn't actually used), the general rule is that you're responsible for any object you alloc, copy or new. If the object was only required in the scope of a function, you could of course autorelease it.
There's a good blog article over at http://interfacelab.com/objective-c-memory-management-for-lazy-people/ that I'd recommend reading as it provides good examples (including some edge cases) and is easy to follow.

iPhone SDK NSInternalInconsistencyException

I'm hitting a wall over and over again, trying to solve a problem I've got in xcode. I'm a newbie and started coding just a while ago.
I'm trying to make a XML parser based on this tutorial: http://cocoadevblog.com/iphone-tutorial-creating-a-rss-feed-reader
which works fine separately, but when I'm implementing it into my own project, I get the 'NSInternalInconsistencyException' error, as a result of the following code:
----File: Parser.m----
- (void)parserDidEndDocument:(NSXMLParser *)parser {
if ([_delegate respondsToSelector:#selector(parsedInformation::)]){
[_delegate parsedInformation:information];
}else{
[NSException raise:NSInternalInconsistencyException
format:#"Delegate (%d) doesn't respond to parsedInformation:", _delegate];
}
}
I've tried to remove the if-phrase, and then it calls the correct function, but the data which is supposed to be overhanded, won't get through.
Project setup
The project is a tab-based application. I'm having three classes:
Parser
AlphaTab
RootDelegate
In RootDelegate I used the following code to initialize the tab-view, and then to initialiaze the AlphaTab as a tableView being part of a navigationView:
----RootDelegate.m ----
tabBarController = [[UITabBarController alloc] init];
alphaTab = [[AlphaTab alloc] initWithTabTitle:#"AlphaTab" navigationTitle:#"Exploring"];
UINavigationController *tableNavController = [[[UINavigationController alloc] initWithRootViewController:alphaTab] autorelease];
tableNavController.delegate = self;
[alphaTab release]; // creates your table view's navigation controller, then adds the created view controller. Note I then let go of the view controller as the navigation controller now holds onto it for me. This saves memory.
So good so far.. the problem comes when I use the Parser class, which parses a given XML file. This class is initialized and only implemented in the AlphaTab - therefore it has nothing to do with the RootDelegate class at all. The initialization is done as:
----File AlphaTab.m ----
- (void)loadData{
if(information==nil){
Parser *XMLParser = [[Parser alloc] init];
[XMLParser parseFeed:#"http://frederikbrinck.com/bodil/Example.xml" withDelegate:self];
[XMLParser release];
}else {
[self.tableView reloadData];
}
}
I'm suspecting the parameter withDelegate's value "self" to be the problem, which I think referres to the super class RootDelegate, but I'm not sure. Likewise, I don't know to pass the AlphaTab class' delegate to the function, which I think would solve the problem.
I'm ought to think, that the problem could be created from this line aswell:
----FILE: Parser.h ----
#protocol AlphaTab <UITableViewDelegate>
- (void)parsedInformation:(NSArray *)i;
#end
I've done some research about protocols and respondsToSelector, but honestly, I didn't understand much, since my code is seen from the programmatic perspective of view, without using the InterfaceBuilder at all, since I've been adviced to do that. It hasn't lead to the solution of the problem either.
For further understanding, I then want this function in AlphaTab.m to be called, when the information is parsed.
----FILE AlphaTab.m ----
- (void)parsedInformation:(NSArray *)i {
NSLog(#"The parser has completed parsing");
information = i;
NSLog(#"This is the information: %d", [[information objectAtIndex:0] objectForKey:#"tabTitle"]);
[self.tableView reloadData];
}
I've looked on the net, and I found some explications about the NSInternalInconsistencyException. I've tried to do them as well, for example by setting everybody with themselves as delegates. However, I had no luck. What wonders me most, is that when I use the Parser without having to subclass it's caller (this case: AlphaTab) to a main class, it works like a charm.
I hope you guys can give me a clue. If you need any more information please ask, and I'll be in disposition.
//Brinck10
Please see #warrenm and his comment.

Using the value of a string to determine the instance of a class

I have a switch statement similar to this one:
switch (number)
{
case 1:
if (imageView1.hidden == NO)
{
imageView1.hidden = YES;
} else
{
imageView1.hidden = NO;
}
break;
case 2:
if (imageView2.hidden == NO)
{
imageView2.hidden = YES;
} else
{
imageView2.hidden = NO;
}
break;
And so forth and so on.
My question is how do I use a string with a value say "imageView1" and use that to access the instance of my imageView class instead of having a different case for each instance of imageView? I know it muse be similar to creating an NSPath from a string or something like that, but I'm just not sure where to look or what it would be called.
Thanks in advance for any help!
I don't disagree with those who are concerned about the design, if this is actually the code. I will assume, however, that you are only posting a generalized version of your question. And since this is an important concept in Objective-C, so we should talk about it.
You can access an object's properties by name using Key Value coding, and the routine -valueWithKey:.
NSString *nameOfView = #"imageView1";
[[self valueForKey:nameOfView] setHidden:YES];
This will, in order, look for a method called -imageView1, an ivar named imageView1 and finally an ivar named _imageView1. This technique is very heavily used in Cocoa, and is important to understand. This is one of the many reasons we name things carefully, and yet another reason that we make accessors that handle memory management for us. Search the docs for "Key-Value Compliance" for more information.
Now for this specific case, I would tend towards something more like JimG's solution, using an NSArray of views, so I can loop through them and turn on or off the ones I want based on their index. But I can imagine a lot of cases where that wouldn't be appropriate, and KVC may be.
Why not put the instances in an NSArray and index into that?
NSArray *views = [NSArray arrayWithObjects: imageView1, imageView2, nil];
NSImageView *iview = [views objectAtIndex: number];
Also, you could consider something like:
iview.hidden = ! iview.hidden;
[Edit: missing asterisks, oops]