using a viewController to open another instance of the same viewController - iphone

I have a MasterViewController.h.m.xib (UIViewController) that is opening a TestDummy.h.m.xib (UIViewController) in the following way:
TestDummy *controller = [[TestDummy alloc] initWithNibName:#"TestDummy" bundle:nil];
[scrollView addSubview:controller.view];
I have two buttons in TestDummy: (Open), (Close) and one label: (windowDepth).
I'm trying to create a second instance TestDummy that is open by the first TestDummy. Then allow multiple TestDummy (UIViewController) to open to N depth and allow the close button to take them back to zero depth. Here's what i have for my Open button.
-(IBAction) btnOpen_Clicked{
TestDummy *newController = [[TestDummy alloc] initWithNibName:#"TestDummy" bundle:nil];
newController.isNotRoot = YES;
newController.windowDepth = self.windowDepth + 1;
//do stuff...
childDummy = newController;
// start the animated transition
[UIView beginAnimations:#"page transition" context:nil];
[UIView setAnimationDuration:1.0];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:self.view cache:YES];
//insert your new subview
[self.view addSubview:newController.view];
// commit the transition animation
[UIView commitAnimations];
[newController release];
}
When i do this i get an error in the debug console.
2010-10-07 00:59:12.549 OrionClient[5821:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFType btnOpen_Clicked]: unrecognized selector sent to instance 0x6a339a0'
Must be a memory management issue but i can't figure it out.
Thanks in advance.

'NSInvalidArgumentException', reason:
'-[__NSCFType btnOpen_Clicked]:
unrecognized selector sent to instance
0x6a339a0'
It means you are trying to call a non existing method on that instance. How have you defined the btnOpen_Clicked selector? I'm guessing it should look more like, but really need to see how you defined the selector.
-(IBAction) btnOpen_Clicked:(id)sender

It means that the application can't find your method btnOpen_Clicked.
First rename your method with :
-(IBAction) btnOpen_Clicked:(id)sender
Then make sure this method specification is in the .h file
And in InterfaceBuilder with your TestDummy.xib, make also sure that the link between the button and this method is correctly done with for example TouchUpInside event.

solved it removed the last line [newController release]; need to figure out where to actually call this correctly though.

Related

UINavigationController weird issue

In my app I have NavigationController as root, I have a navigation button as well.
When I'm pressed the button it flips to another controller.
the destination view code:
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *filePath = [[NSHomeDirectory() stringByAppendingPathComponent:#"Documents"]stringByAppendingPathComponent:#"favorites.plist"];
NSData *data = [[NSData alloc]initWithContentsOfFile:filePath];
NSKeyedUnarchiver *unArchiver = [[NSKeyedUnarchiver alloc]initForReadingWithData:data];
self.title = [unArchiver decodeObjectForKey:#"title"];
self.pubDate = [unArchiver decodeObjectForKey:#"pubdate"];
self.description = [ unArchiver decodeObjectForKey:#"description"];
}
Button code 1:
-(void)navFavoritesButton{
[UIView beginAnimations:#"flipview" context:nil];
[UIView setAnimationDuration:2];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft
forView:self.view cache:YES];
FavoritesView *fav = [[FavoritesView alloc]initWithStyle:UITableViewStylePlain];
UINavigationController *favNav = [[UINavigationController alloc]initWithRootViewController:fav];
favNav.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:favNav animated:YES];
}
button code 2:
-(void)navFavoritesButton{
[UIView beginAnimations:#"flipview" context:nil];
[UIView setAnimationDuration:2];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft
forView:self.view cache:YES];
FavoritesView *fav = [[FavoritesView alloc]initWithStyle:UITableViewStylePlain];
fav.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:fav animated:YES];
}
I'm having a weird problem;
If I'm using button 2 code all works good, the view is loaded, unArchived the data and display it on a tableView.
But if I'm using the button 1 code the app crash with the following log:
2013-04-21 16:51:56.714 YnetXML[21898:f803] -[__NSArrayM isEqualToString:]: unrecognized selector sent to instance 0x6b4fd30
2013-04-21 16:51:56.715 YnetXML[21898:f803] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayM isEqualToString:]: unrecognized selector sent to instance 0x6b4fd30'
*** First throw call stack:
(0x268c052 0x1a61d0a 0x268dced 0x25f2f00 0x25f2ce2 0xc312d1 0xc9830e 0x82123 0xc9764e 0xc96c1c 0xcbd56d 0xca7d47 0xcbe441 0xcbe4f9 0xeb5c68 0xc754a1 0xc7612b 0xeb54c7 0xc9e427 0xc9e58c 0x348c4 0xc9e5cc 0x34568 0x387d 0x268dec9 0xbd45c2 0xe0fd54 0x268dec9 0xbd45c2 0xbd455a 0xc79b76 0xc7a03f 0xc792fe 0xbf9a30 0xbf9c56 0xbe0384 0xbd3aa9 0x35a9fa9 0x26601c5 0x25c5022 0x25c390a 0x25c2db4 0x25c2ccb 0x35a8879 0x35a893e 0xbd1a9b 0x22ed 0x2215)
terminate called throwing an exception(lldb)
EDIT:
I deleted the line below and it works for both button 1 and 2 code.
What should cause the problem?
self.title = [unArchiver decodeObjectForKey:#"title"];
what could be the problem? Why it works well without the navigationController and crash with?
I'm trying to solve the problem for several hours, I tried all sorts of ways, I read online but nothing works. I just can not figure out what causes it to crash, help please!
I guess the problem lies with these three statements
self.title = [unArchiver decodeObjectForKey:#"title"];
self.pubDate = [unArchiver decodeObjectForKey:#"pubdate"];
self.description = [ unArchiver decodeObjectForKey:#"description"];
Try this:
//I guess problem with this, because only when you bring in a navigation controller , your app crashes so only when navigation controller comes into play the navigation bar appears and self.title is the text you see in the center of the navigation bar - so rename self.title to self.titlesArray or something
if([[unArchiver decodeObjectForKey:#"title"] isKindOfClass:[NSString class]])
{
//do not use self.title for other purposes, it is to set title of navigation bar.
self.title = [unArchiver decodeObjectForKey:#"title"];
}
self.pubDate = [unArchiver decodeObjectForKey:#"pubDate"];
self.description= [unArchiver decodeObjectForKey:#"description"];
Note: This is not the way to implement but this is just a way to find out whether these statements are the cause for your crash. Try this and tell me, we l figure out another way.

error after change rootviewcontroller +[NSNotificationCenter dictationViewClass]

I get the following error after I change the rootViewControler of my UIWindow.
2012-10-16 15:12:35.653 repdocApp[22898:c07] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[NSNotificationCenter dictationViewClass]: unrecognized selector sent to class 0x1d63914'
The strange thing is, it only occurs if I have a line in my code which will never be executed at this time.
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
AppDelegate *app = (AppDelegate *) [[UIApplication sharedApplication] delegate];
OverviewModel *model = [self.dataArray objectAtIndex:indexPath.row];
if (model.modelType == ModelTypeCatalog)
{
NSLog(#"HERE");
if (app.window.rootViewController == app.catalogViewController)
{
return;
}
// with this return no error but this branch is never executed
// return;
[UIView transitionFromView:app.window.rootViewController.view
toView:app.catalogViewController.view
duration:0.45f
options:UIViewAnimationOptionTransitionCrossDissolve
completion:^(BOOL finished){
app.window.rootViewController = app.catalogViewController;
}];
}
else
{
if (app.window.rootViewController == app.catalogViewController)
{
[app.navigationPopoverController dismissPopoverAnimated:NO];
[UIView transitionFromView:app.window.rootViewController.view
toView:app.splitViewController.view
duration:0.45f
options:UIViewAnimationOptionTransitionCrossDissolve
completion:^(BOOL finished){
app.window.rootViewController = app.splitViewController;
}];
}
}
}
I search the whole internet but I found nothing about +[NSNotificationCenter dictationViewClass] or what this can be.
EDIT:
I notice now, it only happens if I change the rootViewController in a transition, if I do it directly no error happens.
Your Error Log is 2012-10-16 15:12:35.653 repdocApp[22898:c07] Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[NSNotificationCenter dictationViewClass]: unrecognized selector sent to class 0x1d63914
You are calling wrong method .dictationViewClass does not exist in ios.
It's Simply mean you are trying to call a methods which is not exist for Corresponding Class (NSNotificationCenter).
You should Change set Notification as below
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(yourMethodWantToExcute:) name:#"NSNotificationName" object:nil];
I hope It'll be helpful to You.
unrecognized selector sent to class means that there is no such method defined for this class. Try:
Delete the line and try if it works.
Look for a category withn your sources if it contains this method
Write your own blank method with the same name
Try to figure ouy what this method meant to do and implement it
Its not a real answer on this but the same error happens on different actions again regardless of an animation.
The problem seems to be the change of the rootviewcontroller, I replace that with a hidden tabbarcontroller and switch between the tabs and the problem is gone.

Strange memory leak in Window:addSubView

first of all sorry for my English :-) not so good.
I have a strange memory leak with the following code (code after the explanation).
I have a class, FLWaitingView. It is a simple view with a waiting indicator (plus a view with background), used to say to the user "wait for the data to be loaded".
It has two simple methods: show and dismiss.
In the show method, I find the main Application Window and add the subviews (the waiting view and a background view, with different animations). In the dismiss method, I remove it from superview.
In every show, I verify that the view isn't already visible using a static bool var (is_visible).
The strange thing is this: In the dismiss method, I use:
[self.view removeFromSuperview];
[self.waitingView removeFromSuperview];
to remove the two views from the Window, to avoid them to be retained. They are correctly removed, I can verify this with NSLog (for cicle on each window subview). But, in INSTRUMENTS, using the "mark heap" function, I see that in every single reload (new instance of FLWaitingView, then show, then dismiss) the old instance remains in memory and continues to increase memory usage. Obviously is not a problem of the calling code, because I correctly release the object:
//CALLING CODE
//customWaitingView is a property retained
self.customWaitingView = [[[FLWaitingView alloc]init]autorelease];
[self.customWaitingView show];
Moreover, and I think that this is the most important information, if I move the view dismission in another method, called by a selector, the leak disappear!!!
Now I show the "wrong" code and, after, the "correction". I would like to understand why it happens.
- (void)show
{
if (!is_visible){
id appDelegate = [[UIApplication sharedApplication] delegate];
UIWindow *window = [appDelegate window];
self.waitingLabel.text = #"Attendere";
self.view.alpha = 1.0;
self.waitingView.alpha = 1.0;
[window addSubview:self.view];
[window addSubview:self.waitingView];
[self.waitingIndicator startAnimating];
self.view.frame = window.frame;
self.waitingView.center = window.center;
// "Pop in" animation for alert
[self doPopInAnimationWithDelegate:self];
// "Fade in" animation for background
[self doFadeInAnimation];
is_visible = YES;
} else {
NSLog(#"FLWaitingView %# already visible, do nothing", self);
}
}
- (void)dismiss
{
[UIView beginAnimations:nil context:nil];
self.view.alpha = 0.0;
self.waitingView.alpha = 0.0;
[UIView commitAnimations];
[self.waitingIndicator stopAnimating];
//here is the problem
[self.view removeFromSuperview];
[self.waitingView removeFromSuperview];
is_visible = NO;
}
the code above is the "wrong" one, but if I add
[self performSelector:#selector(alertDidFadeOut) withObject:nil afterDelay:0.5];
in the dismiss method and a new method (obviously removing the redundant code from dismiss method):
- (void)alertDidFadeOut
{
//here the memory is correctly released
[self.view removeFromSuperview];
[self.waitingView removeFromSuperview];
is_visible = NO;
}
the memory is correctly released.
Why??????
Thank you in advance
Fabio
Your view isn't getting released as you would be expecting because at the moment you're releasing it there are still animations linked to it. You can only properly release it after the animations are finished.
Your second method works because the animation lasts less than 0.5 seconds - the releasing code is called after view is freed of all the animations.
Proper way to animate the view would be to either create an animation and assign its delegate or maybe a bit more elegant soulution is to use block-based animation like this:
- (void)dismiss
{
[[UIApplication sharedApplication] beginIgnoringInteractionEvents];
[UIView animateWithDuration: 0.15
animations: ^{
self.view.alpha = 0.0;
self.waitingView.alpha = 0.0;
}
completion: ^(BOOL finished){
[self.waitingIndicator stopAnimating];
    [self.view removeFromSuperview];
    [self.waitingView removeFromSuperview];
    is_visible = NO;
[[UIApplication sharedApplication] endIgnoringInteractionEvents];
}];
}

When random number shows twice, my object crashes the iPhone app! :(

I'm working on a nice app as per usual and then this happens! You spin the wheel of fortune in my app, and when the spinning animation is finished, the app is supposed to randomize a number, and display the card matched as the number index.
The cards are stored in a NSMutableArray, working perfectly when called the first time. Eg. when the app randomizes number "1" card number 1 is called and displayed without problem!
But once the randomizer hits "1" again, the app crashes on the line specified below.
Here's the code, PLEASE help me :)
NSNumber *cardNumber;
cardNumber = [NSNumber numberWithUnsignedInt:arc4random()%[appDelegate.cardArray count]];
NSLog(#"%#", cardNumber);
SpinCard *selectedCard = [appDelegate.cardArray objectAtIndex:[cardNumber doubleValue]];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
[snurrKnapp setAlpha:100];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlDown forView:cardView cache:YES];
[UIView commitAnimations];
[snurrKnapp setEnabled:YES];
if(![cardTitle.text isEqualToString:selectedCard.cardTitle]) { //Crashes here
[cardTitle setText:selectedCard.cardTitle]; //If I remove the if-case it crashes here
[cardContent setText:selectedCard.cardContent];
}
[selectedCard release];
Here's the error I get:
2011-04-21 23:10:54.296 Snurra Flaskan[947:707] 0
2011-04-21 23:10:58.794 Snurra Flaskan[947:707] 2
2011-04-21 23:11:02.691 Snurra Flaskan[947:707] 1
2011-04-21 23:11:08.977 Snurra Flaskan[947:707] 2
warning: Unable to read symbols for /Developer/Platforms/iPhoneOS.platform/DeviceSupport/4.3.1 (8G4)/Symbols/Developer/usr/lib/libXcodeDebuggerSupport.dylib (file not found).
(gdb)
I'm very new in Obj-C, but here is what I think is happening.
You should not call [selectedCard release];
Because objectAtIndex does not allocate a new SpinCard for selectedCard. You should not release it. That explains the behaviour for the second use of that SpinCard: you can't use it, it has already been released.

delegate method throws runtime "unrecognized selector" error when switching back from one UIViewController to the main View Controller

Ok, I've spend like half day on this and it's killing me.
So I've got 3 view controllers transitioning from one another, something like this:
I call the UploadDecisionViewController after destroying the previous View Controller:
[self dismissModalViewControllerAnimated:YES];
[self performSelector:#selector(showUDModalView) withObject:nil afterDelay:0.5];
In my showUDModalView method:
- (void)showUDModalView
{
UploadDecisionViewController *udcontroller = [[UploadDecisionViewController alloc] initWithNibName:#"UploadDecisionViewController" bundle:nil];
udcontroller.delegate = self;
[self presentModalViewController:udcontroller animated:YES];
[udcontroller release];
}
The UploadDecisionViewController shows up no problem. The UploadDecisionViewController has a button, which when clicked I want it to transition to the FileUploadViewController. I setup a UploadDecisionDelegate, threw a method in there to handle the button clicking:
Inside UploadDecisionDelegate protocol (UploadDecisionViewController.h):
#protocol UploadDecisionDelegate
//let UOnliveViewController know that a button was selected
- (void)UploadDecisionViewController:(UploadDecisionViewController *)controller madeChoice:(NSString *)whichDirection;
#end
Then inside my IBAction method when the button is clicked, I have this:
- (IBAction)decisionSelected:(id)sender
{
[delegate UploadDecisionViewController:self madeChoice:#"upload"];//crashing at this line
}
When I run this, at this line above it is throwing a runtime exception:
2010-06-09 12:48:59.561 UOnlive[4735:207] *** -[UIView UploadDecisionViewController:madeChoice:]: unrecognized selector sent to instance 0x3b65420
2010-06-09 12:48:59.562 UOnlive[4735:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[UIView UploadDecisionViewController:madeChoice:]: unrecognized selector sent to instance 0x3b65420'
2010-06-09 12:48:59.563 UOnlive[4735:207] Stack: (
33502299,
2495698185,
33884219,
33453686,
33306306,
20618,
2982917,
3390286,
3399023,
3394235,
3087839,
2996168,
3022945,
40156505,
33287040,
33283144,
40150549,
40150746,
3026863,
11700,
11554
)
Let me throw in the delegate method implemented also:
- (void)UploadDecisionViewController:(UploadDecisionViewController *)controller madeChoice:(NSString *)whichDirection
{
NSLog(#"it got to here 245");
[self dismissModalViewControllerAnimated:YES];
if (yesOrNo) {
//open up the FileUploadViewController and proceed to upload
[self performSelector:#selector(showFUModalView) withObject:nil afterDelay:0.5];
}
}
Can someone tell me what the heck is going on? Thanks a bunch for the help...
The error says that you are trying to call the UploadDecisionViewController method on UIView.
My bet is that you set some view to the delegate instead of view controller.
Where the showUDModalView method is located?
Maybe you set the delegate in some additional places?
Your code is to lengthy and I dont want to go through this but just an advice, you can c if your object can/cannot perform a selector with this kind of statement:
if([myObj respondsToSelector:#selector(myFunc)])
{
//do something
}
else{
//do something else
}