view's frame not releasing its memory - ios

I'm not able to rectify the situation which is arising in
customTabView.view.frame = CGRectMake(0, self.view.frame.size.height-49, self.view.frame.size.width, 49);
where, memory assigned every time and not releasing after dismissing the view.
Well, the situation is that, I have created a simple login screen as rootviewcontroller, then through a button (login button) presenting a tabviewcontroller where, I have added a view as subview on tabviewcontroller, on that subview four buttons are there, through delegate I'm controlling the tabIndex, everything is working fine, but when I check about the leaking memory, above view.frame keeping the memory.
I'm posting the image, please look at this,
Here is my TabView Controller with custome tabbar.
Any help will be appreciable.
UPDATE:
Here is my complete code.
From Login Page:
- (IBAction)clickLoginBtnAction:(id)sender {
tabControler = [self.storyboard instantiateViewControllerWithIdentifier:#"TabBarController"];
[self presentViewController:tabControler animated:YES completion:nil];
}
From Tabbar Controller:
#import "TabBarController.h"
#interface TabBarController ()<TabBarIndexProtocol>{
// CustomTabViewController *customTabView;
}
#property (strong) CustomTabViewController *customTabView;
#end
#implementation TabBarController
#synthesize customTabView;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
customTabView = [self.storyboard instantiateViewControllerWithIdentifier:#"CustomTabViewController"];
self.tabBar.hidden = YES;
[self frameCustomTabViewOnTabBar];
customTabView.tabBarIndexDelegate = self;
}
-(void)viewDidDisappear:(BOOL)animated{
// customTabView.view.frame = nil;
}
// For Screen Rotation
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
[coordinator animateAlongsideTransition:nil completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
[self frameCustomTabViewOnTabBar];
}];
}
-(void)frameCustomTabViewOnTabBar{
customTabView.view.frame = CGRectMake(0, self.view.frame.size.height-49, self.view.frame.size.width, 49);
[self.view addSubview:customTabView.view];
}
# pragma mark - TabBarIndexProtocol from CustomTabBarClass
-(void)tabBarIndexSelected :(int)tabNumber{
NSLog(#"%d",(int)tabNumber);
[self setSelectedIndex:tabNumber];
}
In My CustomeTab.h File:
#import <UIKit/UIKit.h>
#protocol TabBarIndexProtocol <NSObject>
#required
-(void)tabBarIndexSelected :(int)tabNumber;
#end
#interface CustomTabViewController : UIViewController
#property(weak) id <TabBarIndexProtocol> tabBarIndexDelegate;
#end
and from its .m file
#import "CustomTabViewController.h"
#interface CustomTabViewController ()
#end
#implementation CustomTabViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (IBAction)tabNumberOne:(id)sender {
[self.tabBarIndexDelegate tabBarIndexSelected:0];
}
- (IBAction)tabNumberTwo:(id)sender {
[self.tabBarIndexDelegate tabBarIndexSelected:1];
}
- (IBAction)tabNumberThree:(id)sender {
[self.tabBarIndexDelegate tabBarIndexSelected:2];
}
- (IBAction)tabNumberFour:(id)sender {
[self.tabBarIndexDelegate tabBarIndexSelected:3];
}
Thats all, where I'm mistaking :( .

Related

Objective C-Custom Delegate not working

I am trying to get a string from a view controller to another using delegate method.But the delegate method is not getting called.Below is the code
#protocol CustomDelegate<NSObject>
-(void)didDataRecieved;
#end
#interface CustomController:UIViewController
#property id<CustomDelegate>delegate;
#property(retain,nonatomic)NSString *string;
#end
#implementaion CustomController
-(void)viewDidLoad
{
string=#"hello";
if([self.delegate respondsToSelector#selector(didDataRecived)]) {
[self.delegate didDataRecieved];
}
}
-(IBACTION)gotoViewController
{
ViewController *view=[self.storyboard instantiateViewController:#"View"];
[self.navigationController pushViewController:view aniamted:YES];
}
#end
#interface ViewController:UIViewController<CustomDelegate>
#property (nonatomic,retain)CustomController *cust;
#end
#implementation ViewController
-(void)viewDidLoad
{
self.cust=[[CustomController alloc]init];
self.cust.delegate=self;
}
-(void)didDataRecieved
{
NSLog(#"data %#",self.cust.string);
}
#end
Can anyone point out where am going wrong...plz help.
edited the code..tried this way too.
if([self.delegate respondsToSelector#selector(didDataRecived)]){
[self.delegate didDataRecieved];
}
I will give you the sample coding.Customize the below code.
Here we have two view controllers.
ViewController
and
SecondViewController
in SecondViewController
.h
#import <UIKit/UIKit.h>
#class SecondViewController;
#protocol SecondViewControllerDelegate <NSObject>
- (void)secondViewController:(SecondViewController *)secondViewController didEnterText:(NSString *)text;
#end
#interface SecondViewController : UIViewController
#property (nonatomic, assign)id<SecondViewControllerDelegate> delegate;
#property (nonatomic, strong) IBOutlet UITextField *nameTextField;//It must connect as outlet connection
- (IBAction)doneButtonTapped:(id)sender;
#end
.m
#import "SecondViewController.h"
#interface SecondViewController ()
#end
#implementation SecondViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
//Either use NSNotification or Delegate
- (IBAction)doneButtonTapped:(id)sender;
{
//Use Notification
[[NSNotificationCenter defaultCenter] postNotificationName:#"passingDataFromSecondViewToFirstView" object:self.nameTextField.text];
//OR Custom Delegate
[self.delegate secondViewController:self didEnterText:self.nameTextField.text];
[self.navigationController popViewControllerAnimated:YES];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
in ViewController
.h
#import <UIKit/UIKit.h>
#import "SecondViewController.h"
#interface ViewController : UIViewController<SecondViewControllerDelegate>
#property (nonatomic, strong) IBOutlet UILabel *labelName; //You must connect the label with outlet connection
- (IBAction)gotoNextView:(id)sender;
#end
.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
//addObserver here...
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(textFromPreviousViewControllerNotificationReceived:) name:#"passingDataFromSecondViewToFirstView" object:nil];
// Do any additional setup after loading the view, typically from a nib.
}
//addObserver Method here....
- (void)textFromPreviousViewControllerNotificationReceived:(NSNotification *)notification
{
// set text to label...
NSString *string = [notification object];
self.labelName.text = string;
}
- (IBAction)gotoNextView:(id)sender;
{
//If you use storyboard
SecondViewController *secondViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
//OR If you use XIB
SecondViewController *secondViewController = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
secondViewController.delegate = self;
[self.navigationController pushViewController:secondViewController animated:YES];
}
//Calling custom delegate method
- (void)secondViewController:(SecondViewController *)secondViewController didEnterText:(NSString *)text
{
self.labelName.text = text; //Getting the data and assign the data to label here.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
For your understanding the code I create a simple passing data from one second view controller to first view controller.
First we navigate the view from first view controller to second view controller.
After that we send the data from second view controller to first view controller.
NOTE : You can either use NSNotification or Custom Delegate method for sending data from One View Controller to Other View Controller
If you use NSNotification, you need to set the postNotificationName for getting data in button action method.
Next you need to write addObserver in (sending data to your required View Controller) ViewController and call the addObserver method in same View Controller.
If you use custom delegate,
Usually we go with Custom Protocol Delegate and also we need to Assign the delegate here.
Very importantly we have to set the Custom Delegate Method in the Second View Controller.Because where we send the data to first view controller once we click the done button in second view controller.
Finally we must call the Custom Delegate Method in First View Controller, where we get the data and assign that data to label.Now you can see the passed data using custom delegate.
Likewise you can send the data to other view controller using Custom Delegate Methods
how you pushing your second controller? i cant see.
but your code working for me.
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
ViewController1 *vc = [ViewController1 new];
vc.delegate = self;
[self presentViewController:vc animated:YES completion:nil];
}
-(void)didDataRecieved
{
NSLog(#"recieved");
}
#end

Pushing UIViewController fails with "Application tried to push a nil view controller on target"

So I'm using a NavigationController to do all the navigation of my iOS App. On the main screen there is a 'plus button' to take an image, and on pressing this button the NavigationController pushes the 'CameraViewController' with the method 'displayCamera:'. There the user can take an image and it is supposed to be previewed by another UIViewController which is pushed by the function 'picTaken:'. However overtime I try to push this view controller I get the error "Application tried to push a nil view controller on target". I have no idea what is going wrong. Below is the NavigationController.h and the corresponding .m file
NavigationController.h
#import <UIKit/UIKit.h>
#import "CameraViewController.h"
#import "MainViewController.h"
#import "PictureCheckViewController.h"
#interface NavigationController : UINavigationController {
CameraViewController *camView;
MainViewController *mainView;
PictureCheckViewController *checkView;
}
- (void)displayCamera:(id)sender;
- (void)picTaken:(id)sender;
#end
NavigationController.m
#import "NavigationController.h"
#interface NavigationController () {
}
#end
#implementation NavigationController
- (void)viewDidLoad
{
[super viewDidLoad];
camView = [[CameraViewController alloc] init];
mainView = [[MainViewController alloc] init];
checkView = [[PictureCheckViewController alloc] init];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)displayCamera:(id)sender {
[self pushViewController:camView animated:YES];
}
- (void)picTaken:(id)sender {
[self pushViewController:checkView animated:YES];
}
#end
If you need anymore information please tell me.
I appreciate your time and help :)
I would recommend you use a lazy instantiation method.
Add a property :
#Property(nonatomic,strong) MainViewController *mainView;
#Property(nonatomic,strong) PictureCheckViewController *checkView;
and override the getters yourself:
-(MainViewController*) mainView {
if(!_mainView) {
_mainView = [[MainViewController alloc] init];
}
return _mainView;
}
And like wise for checkView.
-(PictureCheckViewController*) checkView {
if(!_checkView) {
_checkView = [[PictureCheckViewController alloc] init];
}
return _checkView;
}
then access using:
self.checkView
self.mainView
Aside from I believe fixing your problem, it would also avoid creation unless the resource is actually used.

UIImagePickerController Overlay takePicture method

I am calling an camera overlay using a xib file by doing the following:
Camera.h
#import <UIKit/UIKit.h>
#import "ControlsViewController.h"
#interface CameraViewController : UIViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate,ProcessDataDelegate>
#property (nonatomic, strong) UIImagePickerController *imagePicker;
#end
Camera.m
#import "CameraViewController.h"
#import "ControlsViewController.h"
#interface CameraViewController ()
#end
#implementation CameraViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
//Get the camera
self.imagePicker = [[UIImagePickerController alloc] init];
self.imagePicker.delegate = self;
self.imagePicker.allowsEditing = NO;
self.imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
self.imagePicker.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:self.imagePicker.sourceType];
self.imagePicker.showsCameraControls = NO;
//set our custom overlay view
ControlsViewController *overlayViewController = [[ControlsViewController alloc] initWithNibName:#"ControlsViewController" bundle:nil];
[self addChildViewController:overlayViewController];
self.imagePicker.cameraOverlayView = overlayViewController.view;
[self presentViewController:self.imagePicker animated:NO completion:NULL];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)didClickCameraButton {
[self.imagePicker takePicture];
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#end
This calls the xib and .m .h files for ControlsViewController Within those file I have a button for taking the picture but not sure how to call that method in the overlay. I was thinking of something like:
Overlay.H
#import <UIKit/UIKit.h>
#protocol ProcessDataDelegate <NSObject>
#end
#interface ControlsViewController : UIViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
{
id <ProcessDataDelegate> delegate;
}
- (IBAction)cameraButton:(id)sender;
- (IBAction)kennedyButton:(id)sender;
#property (retain) id delegate;
-(void)didClickCameraButton;
#end
Overlay.M
#import "ControlsViewController.h"
#import "CameraViewController.h"
#interface ControlsViewController ()
#end
#implementation ControlsViewController
#synthesize delegate;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
[self.view setBackgroundColor:[UIColor clearColor]];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
- (IBAction)cameraButton:(id)sender {
NSLog(#"this button works");
[self.delegate didClickCameraButton];
}
- (IBAction)kennedyButton:(id)sender {
NSLog(#"this button works");
}
#end
but obviously the imagePicker property is not being carried over the the overlays .m file. Anyone know how to go about this? I imported the cameras .H file on the overlays .m file as well but no luck. Thanks.
In your overlayViewController, is the button linked to cameraButton:? You have several layers of controls, and ultimately you want the main controller (the one you're showing viewDidLoad for) to call [self.imagePicker takePicture]. You can add a delegate to overlayViewController, so that when cameraButton: is called, it just tells the delegate.
Obviously you'll have to create a protocol, set a delegate, etc.
Edit: usual patterns for delegates are that the delegate is weak. You may have to have the overlayController not be transient if you're using arc.
ControlsViewController.h
#interface ControlsViewController : UIViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
{
// don't need the delegate declared in here
}
#property (weak) id delegate;
ControlsViewController.m
- (IBAction)cameraButton:(id)sender {
NSLog(#"this button works");
[self.delegate didClickCameraButton];
}
YourMainViewController.h
#interface YourMainViewController : UIViewController <ControlsViewDelegate>
{
ControlsViewController *overlayController;
}
YourMainViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
...
overlayViewController = [[ControlsViewController alloc] initWithNibName:#"ControlsViewController" bundle:nil];
overlayViewController.delegate = self;
self.imagePicker.cameraOverlayView = overlayViewController.view;
[self presentViewController:self.imagePicker animated:NO completion:NULL];
}
-(void)didClickCameraButton {
[self.picker takePicture];
}

Change UILabel text from subview using delegate

I have a view with a label in it. The lower side of this view is filled with a subview which has it’s own view controller. This subview has a button. My goal: I want to change the label by pressing the button in the subview.
I have tried the code beneath. It works fine when I let the ViewWillAppear method of the delegate call the ‘doSomeTask’ method of the SubviewController. A timer begins to count and after a few seconds, the SubviewController calls the delegates changeLabel method, and the label is changed. However, when I call the ‘doSomeTask’ method manually by pressing the button, the delegate isn’t listening. The call doesn’t reach the changeLabel method.
Probably I am doing something ridiculously stupid here. Forgive me, I’m just learning iOS programming. Thanks in advance for all the feedback.
MyViewController.h
#import <UIKit/UIKit.h>
#import "MySubViewController.h"
#interface MyViewController : UIViewController
#property (strong, nonatomic) IBOutlet UIView *detailView;
#property (strong, nonatomic) IBOutlet UILabel *theLabel;
- (IBAction)changeLabel:(id)sender;
#end
MyViewController.m
#import "MyViewController.h"
#import "MySubViewcontroller.h"
#interface MyViewController ()
#end
#implementation MyViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
MySubViewController *subVC = [[MySubViewController alloc] init];
[self addChildViewController:subVC];
[self.detailView addSubview:subVC.view];
// [subVC setDelegate:self]; (no success trying this)
[subVC didMoveToParentViewController:self];
}
-(void)viewWillAppear:(BOOL)animated
{
MySubViewController *mySubVC = [[MySubViewController alloc] init];
[mySubVC setDelegate:self];
[mySubVC doSomeTask]; // this works fine
}
// delegate method
- (void)changeLabel{
self.theLabel.text = #"Hello!";
}
MySubviewController.h
#import <UIKit/UIKit.h>
#protocol MySubViewControllerDelegate <NSObject>
#required
- (void)changeLabel;
#end
#interface MySubViewController : UIViewController
#property (nonatomic, assign) id delegate;
- (IBAction)changeButton:(id)sender;
- (void)doSomeTask;
- (void)goChangeLabel;
#end
MySubViewController.m
#import "MySubViewController.h"
#interface MySubViewController ()
#end
#implementation MySubViewController
#synthesize delegate;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)goChangeLabel
{
[[self delegate] changeLabel];
}
- (void)doSomeTask
{
[NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:#selector(goChangeLabel) userInfo:nil repeats:NO];
}
- (IBAction)changeButton:(id)sender {
// [self doSomeTask]; (no succes trying this)
}
#end
Your problem is this:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
MySubViewController *subVC = [[MySubViewController alloc] init];
[self addChildViewController:subVC];
[self.detailView addSubview:subVC.view];
// [subVC setDelegate:self]; (no success trying this)
[subVC didMoveToParentViewController:self];
}
-(void)viewWillAppear:(BOOL)animated
{
MySubViewController *mySubVC = [[MySubViewController alloc] init];
[mySubVC setDelegate:self];
[mySubVC doSomeTask]; // this works fine
}
In these 2 methods you have created 2 separate variables of type MySubViewController. You have only set the delegate on the variable created inside viewWillAppear.
These are not static classes, singletons or anything else similar. If you create a variable of one type it is in no way linked to the other. The same way you can create multiple NSString's that have no bearing on each other.
Create it like so:
#implementation MyViewController
{
MySubViewController *_subVC;
}
- (void)viewDidLoad
{
[super viewDidLoad];
_subVC = [[MySubViewController alloc] init];
}
now you can use _subVC everywhere in that file as the one reference

Sharing data between an IOS Utility Application views

I have created a very basic application using the Utility Application template in Xcode 4.2 in which I want an integer variable obtained from a slider or text field in my FlipsideViewController available in my MainViewController.
I have been searching for hour on global variables but can't find a nice simple answer that works for my specific case.
Please help
(note: I am very new at developing for IOS and objective C. Dumb your answer down for me as much as you are capable!)
Thanks a lot
The following is a basic version of my code showing what I want to do.
FlipSideViewController.h
#import <UIKit/UIKit.h>
#class FlipsideViewController;
#protocol FlipsideViewControllerDelegate
- (void)flipsideViewControllerDidFinish:(FlipsideViewController *)controller;
#end
#interface FlipsideViewController : UIViewController
#property (weak, nonatomic) id <FlipsideViewControllerDelegate> delegate;
- (IBAction)done:(id)sender;
- (IBAction)sliderChange:(id)sender;
#property (weak, nonatomic) IBOutlet UILabel *sliderValueOnFlipside;
#end
FlipSideViewController.m
#import "FlipsideViewController.h"
#interface FlipsideViewController ()
#end
#implementation FlipsideViewController
#synthesize sliderValueOnFlipside;
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)viewDidUnload
{
[self setSliderValueOnFlipside:nil];
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
#pragma mark - Actions
- (IBAction)done:(id)sender
{
[self.delegate flipsideViewControllerDidFinish:self];
}
- (IBAction)sliderChange:(id)sender {
UISlider *slider = (UISlider *) sender;
int var = [slider value];
sliderValueOnFlipside.text = [NSString stringWithFormat:#"Slider Value is %d",var];
}
#end
MainViewController.h
#import "FlipsideViewController.h"
#interface MainViewController : UIViewController <FlipsideViewControllerDelegate>
- (IBAction)showInfo:(id)sender;
#property (weak, nonatomic) IBOutlet UILabel *sliderValueOnMain;
#end
MainViewController.m
#import "MainViewController.h"
#interface MainViewController ()
#end
#implementation MainViewController
#synthesize sliderValueOnMain;
- (void)viewDidLoad
{
[super viewDidLoad];
sliderValueOnMain.text = [NSString stringWithFormat:#"Slider Value from flipside is %d", var];
}
- (void)viewDidUnload
{
[self setSliderValueOnMain:nil];
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
#pragma mark - Flipside View
- (void)flipsideViewControllerDidFinish:(FlipsideViewController *)controller
{
[self dismissModalViewControllerAnimated:YES];
}
- (IBAction)showInfo:(id)sender
{
FlipsideViewController *controller = [[FlipsideViewController alloc] initWithNibName:#"FlipsideViewController" bundle:nil];
controller.delegate = self;
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:controller animated:YES];
}
#end
I can easily get the value of the slider to be displayed on the flipside view however I also want that value displayed on the main view.
Global variables are generally frowned upon in polite programming circles.
If you want a method in MainViewController to react to a change in state in FlipsideViewController, then you could make MVC a delegate of FVC, and have FVC call a method on MVC when the value changes.
There's a good explanation of the delegate design pattern here: http://mobiledevelopertips.com/objective-c/the-basics-of-protocols-and-delegates.html

Resources