IOS/Objective-C: call of another class(VC) method not working - ios

I've searched and searched for the answer to this issue and the solutions i've found doesn't seem to work, so I guess i'm doing something wrong: i want to call this method
-(void)customFade:(UILabel *)theLabel withDelay:(float)delayAmount {
[UIView animateWithDuration:0.5
delay:delayAmount
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
[theLabel setAlpha:1.0f];
[theLabel setAlpha:0];
}completion:nil];
}
from a VC called View Controller to another but it isn't being recognized despite the imports... here's what i'm trying on the desired VC:
- (void)viewDidLoad {
[super viewDidLoad];
ViewController *ViewController = [[ViewController alloc] init];
[ViewController customFade:_label withDelay:0.3];
}
the warning says "no visible #interface for "ViewController" declares the selector alloc
Can someone help me out? I'm kind of new at this, thank you

such an error usually happens when you have mistyped the name of the method, or that method doesn't belong to that class at all and doesn't exist in your class.
and ensure once your VC is subclass with UIViewController
#interface ViewController : UIViewController
change your instance object type and check once
ViewController *vc = [[ViewController alloc] init];
[vc customFade:_label withDelay:0.3];
and change the animation like
[UIView animateWithDuration:0.5
delay:delayAmount
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
[theLabel setAlpha:1.0f];
}completion:{
[theLabel setAlpha:0];
}];
for more information you can get the reference from here

Related

Release subview and manage memory

I've the following code in the main.m class file
-(void)switchView:(UIView *)view1 toView:(UIView *)view2{
[UIView beginAnimations:#"Animation" context:nil];
[UIView setAnimationDuration:0.75];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.window cache:YES];
[window addSubview:view2];
[UIView commitAnimations];
[view1 release];
}
I call this method from external files in this way:
-(IBAction)menuChangeLanguage:(id)sender{
main *delegate = (main *)[[UIApplication sharedApplication] delegate];
viewController *newView = [[viewController alloc] initWithNibName:#"newController" bundle:nil];
[delegate switchView:self.view toView:newView.view];
}
In this way I create a new view and switch with the existing one. Even if I've put the [view1 release] command in the method I call, I can see that the allocation of memory increases as I switch between the 2 views. What am I doing wrong?
If I use the analyze instrument it says Potential leak of an object stored into 'newView'. How can I avoid this?
The problem is that you are trying to remove the view from its viewcontroller. UIviewController has a strong reference to its view, so even if you remove from its superview, the view is retained by the viewcontroller.
take a look at the Apple UIViewController Class reference

Custom Segue without presentViewController doesn't unwind correctly

I'm implementing a custom segue using controller containment API, e.g.
#implementation CustomSegue
- (void)perform {
UIViewController *sourceViewController = self.sourceViewController;
UIViewController *destinationViewController = self.destinationViewController;
[sourceViewController addChildViewController:destinationViewController];
destinationViewController.view.alpha = 0.0;
[sourceViewController.view addSubview:destinationViewController.view];
[UIView animateWithDuration:0.3 animations:^{
destinationViewController.view.alpha = 1.0;
} completion:^(BOOL finished) {
[destinationViewController didMoveToParentViewController:sourceViewController];
}];
}
#end
View controller hierarchy is trivial: sourceViewController → destinationViewController
When unwinding from the destinationViewController to the sourceViewController, app crashes in [UIStoryboardUnwindSegueTemplate _perform:] with exception Could not find a view controller to execute unwinding for <…>
I did not implement custom -[UIViewController viewControllerForUnwindSegueAction:fromViewController:withSender: or
-[UIViewController canPerformUnwindSegueAction:fromViewController:withSender: which means framework returns correct values (although I implemented it once to check).
When replacing my custom addChildViewController:… code with presentViewController:… in the segue, it works fine: unwinding performs like expected.
The question: is it possible to have a custom segue that creates a custom view controller hierarchy?
Test case project: https://bitbucket.org/zats/unwind/
I think that George Green's comment is relevant, and the way you have your controllers set up is the cause of the crash. I think to do what you want, you should have ZTSFirstViewController added as a child to a custom container controller which will do the unwinding, and the (forward) segue will exchange the children of that custom container controller (switch from ZTSFirstViewController to ZTSSecondViewController). The viewControllerForUnwindSegueAction:fromViewController:withSender: method needs to be implemented in the custom container controller (ViewController in my example). I tested this by adding a container view in IB to ViewController, and changed the class of the embedded controller to ZTSFirstViewController. I added a segue from a button in ZTSFirstViewController to ZTSSecondViewController, and connected the unwind segue from a button in that controller. The unwind: method is in ZTSFirstViewController. The code in the custom segue was this,
- (void)perform {
UIViewController *destinationViewController = self.destinationViewController;
UIViewController *sourceViewController = self.sourceViewController;
if (!self.unwind) {
[sourceViewController.parentViewController addChildViewController:destinationViewController];
destinationViewController.view.alpha = 0.0;
[sourceViewController.parentViewController.view addSubview:destinationViewController.view];
[UIView animateWithDuration:0.3 animations:^{
destinationViewController.view.alpha = 1.0;
} completion:^(BOOL finished) {
[destinationViewController didMoveToParentViewController:sourceViewController.parentViewController];
}];
} else {
[self.sourceViewController willMoveToParentViewController:nil];
[UIView animateWithDuration:0.3 animations:^{
sourceViewController.view.alpha = 0.0;
} completion:^(BOOL finished) {
[sourceViewController.view removeFromSuperview];
[sourceViewController removeFromParentViewController];
}];
}
}
I kept this segue close to your implementation -- it doesn't actually switch the controllers, it just adds the second one as a second child and hides the view of the first.

How to show UIViewController in other UIViewController?

This is typical question and possibly duplicated, but..
There is iPad app which has UINavigationBar and UITabBar. I have created a button on navigationBar which must show appinfoViewController.
When I present it navigationBar and tabTab are still available to tap. But I would like to show appinfoViewController to full app's main screen size (like modal)
This is my code:
- (void)showInfo
{
AboutViewController *about = [[AboutViewController alloc] init];
[about.view setFrame: self.view.frame];
[about.view setAlpha:0.0];
[UIView animateWithDuration:0.5
delay:0.0
options: UIViewAnimationOptionCurveLinear
animations:^{
[about.view setAlpha:1.0];
[self.view addSubview:about.view];
[self addChildViewController:about];
[about didMoveToParentViewController:self];
}
completion:^(BOOL finished){
}];
}
How to present appinfoViewController to full screen?
May be it's possible to present it modally but without BLACK background?
As suggested in the comments, using
[self presentViewController:about animated:YES completion:nil]
would get rid of the nav bar and the tab bar. If you need to keep them, you need to use
[self.navigationController pushViewController:about animated:YES];
EDIT:
In order to have the user interaction disabled everywhere except for your about view, it's slightly trickier: first off, you need to have all of your UI elements embedded in a view that is not the main view of your presenting view controller.
Let's say you have only a button (the "show about" button), you wouldn't just place it in your main view, but you would use another view (let's call it "outer view") that is just as big as the view controller's view and where you place the button (along with any other ui element you might have). You also need an outlet to this outer view. Then write a method such as:
-(void)userInteractionEnabled:(BOOL)enabled
{
self.navigationController.navigationBar.userInteractionEnabled = enabled;
self.tabBarController.tabBar.userInteractionEnabled = enabled;
self.outerView.userInteractionEnabled = enabled;
}
Alternatively you could simply disable every "interactive" outlet instead of outerView. So if, for example, you have 2 textviews, 3 buttons and one UIPickerView, you would set userInteractionEnabled = enabled for each of those outlets (instead of doing it only for the parent view).
Now, in your showInfo method you can have:
CGRect frame = CGRectMake(50, 50, 200, 200); //Use whatever origin and size you need
about.view.frame = frame;
[self.view addSubview:about.view];
[self userInteractionEnabled:NO]
And in your btnClose method you can just put:
[about.view removeFromSuperview];
[self userInteractionEnabled:YES];
I hope this helps, let me know if this is what you needed!
P.S. Maybe you're already aware of this, but there is a class UIPopoverController, only available for iPad's apps, that would pretty much do all of this for you. You can find a tutorial on how to use it here.
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:nil];
AboutViewController *about = (AboutViewController *)[storyBoard instantiateViewControllerWithIdentifier:#"about"];
[self.navigationController pushViewController:about animated:YES];
You can add viewcontroller view layer directly to presenting viewcontroller view.
Code should be look like --
AboutViewController *about = [[AboutViewController alloc] init];
[about.view setFrame: self.view.bound];
[about.view setAlpha:0.0];
[self.view addSubview:about.view];
[UIView animateWithDuration:0.5
delay:0.0
options: UIViewAnimationOptionCurveLinear
animations:^{
[about.view setAlpha:1.0];
}
completion:^(BOOL finished){
}];

Quartz animation error

I have included the <QuartzCore/QuartzCore.h> framework.
On an IBAction I have this:
- (IBAction)searchOptions:(id)sender {
FilterViewController *ctrl = [[FilterViewController alloc] initWithNibName:#"FilterViewController" bundle:nil];
[UIView transitionFromView:self.view toView:ctrl.view duration:1 options:UIViewAnimationOptionTransitionCurlUp completion:nil];
[self.navigationController pushViewController:ctrl animated:NO];
}
When I click the button, the page curls up as you would expect:
When I click the next button (which should curl the page back down) I get this error:
Thread 1: EXC_BAD_ACCESS(code=2, address=0x8)
I think the problem is with the above action (not with the action to uncurl).
What has gone wrong?
EDIT: After a further hour of reading - could it be a memory problem?
I'm not sure but I don't think UIView retains the controller you're passing into it. Assuming you're using ARC, you could try making the FilterViewController into a property.
i.e. In the header add this:
#class FilterViewController;
#interface YourViewController : UIViewController {
FilterViewController *_filterViewController;
}
Then in the implementation change it to:
_filterViewController = [[FilterViewController alloc] initWithNibName:#"FilterViewController" bundle:nil];
[UIView transitionFromView:self.view _filterViewController duration:1 options:UIViewAnimationOptionTransitionCurlUp completion:nil];
[self.navigationController pushViewController:_filterViewController animated:NO];
To make sure it gets retained.
Isn't really mandatory for you to do Page curling effect?
[Try this first]
- (IBAction)searchOptions:(id)sender {
FilterViewController *ctrl = [[FilterViewController alloc] init];
ctrl.modalTransitionStyle = UIModalTransitionStylePartialCurl;
[self presentModalViewController:ctrl animated:YES];
}

conceptual or technical issue with Cocoa programming

I find myself in need of access to a viewcontroller from its view.
Here is the method
-(void)changePageView:(UIViewController*)newviewcont withtransitiontype:(int)t andtransitionspeed:(int)s
{
//Remove whatever view is currently loaded at index 0, this index is only to be used by "page" views
UIView *oldview = [self.view.subviews objectAtIndex:0];
[UIView beginAnimations:#"View Flip" context:nil];
[UIView setAnimationDuration:s];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.view cache:YES];
[newviewcont viewWillAppear:YES];
//[oldview viewWillDisappear:YES];
[oldview removeFromSuperview];
[self.view insertSubview:newviewcont.view atIndex:0];
//[oldview viewDidDisappear:YES];
[newviewcont viewDidAppear:YES];
}
Basically, I am trying to write a generic view switch method that is called by the root controller to swap out subviewcontorllers views from the rootcontrollers view.
I pass in a subviewcontroller and am able to remove the current subview. But in order to do proper view switching animation i need access to the current views view controller. Is this the wrong approach and can it be done?
I added a member to the rootcontroller that hold onto the current sub view controller (currentController) and refers to it when a controller swap is done
-(void)changePageView:(UIViewController*)newviewcont withtransitiontype:(int)t andtransitionspeed:(int)s
{
[UIView beginAnimations:#"View Flip" context:nil];
[UIView setAnimationDuration:s];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.view cache:YES];
[newviewcont viewWillAppear:YES];
[self.currentController viewWillDisappear:YES];
[self.currentController.view removeFromSuperview];
[self.view insertSubview:newviewcont.view atIndex:0];
[self.currentController viewDidDisappear:YES];
[newviewcont viewDidAppear:YES];
[UIView commitAnimations];
self.currentController = newviewcont;
}
The changeView() method belongs in the viewcontroller. It would solve you problem of having the view knowing about it's controller (which it shouldn't) and it makes more sense.
Also unless you are doing something fancy in changeView() that can't be done using the methods in a UIViewController object then you should just use it instead, if it is neccesary to implement your own view switching method then you can extend UIViewController instead of implemtning part of the view controlelr in your view.
my 2 cents :)
I believe your approach is wrong. You should look into UINavigationController I believe.

Resources