Subclassed controls not being released - iphone

We have found a large memory issue in our application. We have subclassed UITextField and add these to all of our main views. The main views are being dealloced correctly, however the dealloc method in our subclass never gets hit. Here is our subclass:
Header:
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "MyEntities.h"
#import "MyControlHelper.h"
#interface MyTextField : UITextField {
MyControlHelper *myHelper;
UIView *disabledEffect;
}
#property (nonatomic, retain) MyControlHelper *myHelper;
#property (nonatomic, retain) UIView *disabledEffect;
#end
Implementation:
#import "MyTextField.h"
#implementation MyTextField
#synthesize myHelper;
#synthesize disabledEffect;
-(id) initWithCoder:(NSCoder *)aDecoder{
if (self = [super initWithCoder:aDecoder]){
myHelper = [[MyControlHelper alloc] init];
[myHelper setBoundTextField:self];
[myHelper SetupKeyboardListener];
[self setReturnKeyType:UIReturnKeyDone];
self.autocorrectionType = FALSE;
self.delegate = myHelper;
}
return self;
}
-(id) init{
if (self = [super init]){
myHelper = [[MyControlHelper alloc] init];
[myHelper setBoundTextField:self];
[myHelper SetupKeyboardListener];
[self setReturnKeyType:UIReturnKeyDone];
self.autocorrectionType = FALSE;
self.delegate = myHelper;
}
return self;
}
-(id)initWithFrame:(CGRect)frame{
if (self = [super initWithFrame:frame]){
myHelper = [[MyControlHelper alloc] init];
[myHelper setBoundTextField:self];
[myHelper SetupKeyboardListener];
[self setReturnKeyType:UIReturnKeyDone];
self.autocorrectionType = FALSE;
self.delegate = myHelper;
}
return self;
}
-(void)dealloc{
self.myHelper = nil;
self.disabledEffect= nil;
[super dealloc];
}
#end
Any help would be greatly appreciated.
Cheers.

You might have an issue with your myHelper reference. You have declared it as (nonatomic, retain) property. If your MyControlHelper class has a property for your MyTextField also being retained, you are building a cyclic reference and your field is retaining myHelper and vice versa.
If this is the case I suggest you declare the property for the textfield within MyControlHelper with (nonatomic, assign) to resolve the cycle.
It would help to post the code for MyControlHelper, as well.

Related

ios assign self to property in another class

I'm trying to assign self to a property in antoher class (nsobject class) using self as pointer to the view controller but the property is always nil. Any of you knows why or how can I fixed?
viewcontroller.m
-(void)startToDoSomething:(NSString*)testToRun
{
SecondClass *secondClass = [[SecondClass alloc] init];
secondClass.viewController = self;
[secondClass doSomething];
}
SecondClass.h:
NSObject classe:
.h file
#import "ViewController.h"
#class ViewController;
#interface SecondClass : NSObject
{
ViewController *viewController;
}
#property (nonatomic,retain) ViewController *viewController;
Why don't you add an init method:
-(id)initWithViewController:(ViewController *)aViewController
{
self = [super init];
if(self)
{
self.viewController = aViewController;
}
return self;
}
Then you can just call it like this
SecondClass *secondClass = [[SecondClass alloc] initWithViewController:self];
You can also change the property to (nonatomic, assign) and change the synthesize to #synthesize viewController = _viewController
Inside the SecondClass you use _viewController.
Hope it helps.

Passing data between two ViewControllers Problem

Hi I have two viewControllers.
NewsViewController
#import "SingleViewController.h"
#interface NewsViewController : UIViewController {
}
- (NSString *)getFirstImage:(NSString *)htmlString;
#end
and the implementation file:
#import "SingleViewController.h"
SingleViewController *singleViewController;
#interface NewsPadViewController () <UIActionSheetDelegate>
- (void)loadSubscriptions;
#property (nonatomic, assign) BOOL wrap;
#property (nonatomic, retain) NSMutableArray *items;
#end
#implementation NewsPadViewController
....CODE....
- (void)carouselCurrentItemTapped{
//[self addSubview:articolo];
MWFeedItem *item =[reader.feedItems objectAtIndex:[carousel currentItemIndex]];
NSLog(#"Current Item tappped, index: %d", [carousel currentItemIndex]);
singleViewController.prova.text=#"CIAO";
singleViewController.ciao=#"sample";
[singleViewController.web loadHTMLString:item.summary baseURL:nil];
NSLog(#"conternutio:");
NSLog(singleViewController.ciao);
}
SingleViewController.h
#import <UIKit/UIKit.h>
#interface SingleViewController : UIViewController{
#public
UIWebView *web;
UILabel *prova;
NSString *ciao;
}
#property (nonatomic,retain) IBOutlet UIWebView *web;
#property (nonatomic,retain) IBOutlet UILabel *prova;
#property (nonatomic,retain) IBOutlet NSString *ciao;
#end
and SingleViewController.m
#import "SingleViewController.h"
#implementation SingleViewController
#synthesize web,prova,ciao;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[prova setText:ciao];
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
Why I can't access from NewsPadViewController at object in SingleViewController? Where is my error? thanks
UPADATE
- (void)carouselCurrentItemTapped{
//[self addSubview:articolo];
MWFeedItem *item =[reader.feedItems objectAtIndex:[carousel currentItemIndex]];
NSLog(#"Current Item tappped, index: %d", [carousel currentItemIndex]);
SingleViewController *singleViewController = [[SingleViewController alloc] initWithNibName:#"SingleViewController" bundle:[NSBundle mainBundle]];
singleViewController.prova.text=#"CIAO";
singleViewController.ciao=#"sample";
[singleViewController.web loadHTMLString:item.summary baseURL:nil];
NSLog(#"conternutio:");
NSLog(singleViewController.ciao);
[singleViewController setOpz:#"sample"];
}
I don't see any instantiation of SingleViewController. You have a pointer to it, but I don't see anywhere in your code example where you actually create it.
Somewhere you need something like:
if (!singleViewController) {
singleViewController = [[SingleViewController alloc] init];
}
or
SingleViewController *singleViewController = [[SingleViewController alloc] initWithNibName:#"SingleView" bundle:nil];
or from somewhere else you need to send a message or set an instance variable in NewsViewController that points to an existing instance of SingleViewController.

Changed nib File to a OPGL ES View, Buttons don't work

Hy,
There is no problmen with changing the nib but when I'm in the nib-File with the OPGL ES view my buttons that are integrated in this view won't work. When I press one the application crashes.
This is the Code how I change the View to the Second Nib:
- (IBAction)drawEAGLView:(id)sender {
NSArray* nibViews = [[NSBundle mainBundle] loadNibNamed:#"settingsViewController" owner:self options:nil];
EAGLView* glView = [ nibViews objectAtIndex: 1];
self.view = glView;
[glView startAnimation];}
The Animation is working .
This is the Code of the ViewController where the Button is declared:
SettingsViewController.h:
#import <UIKit/UIKit.h>
#interface SettingsViewController : NSObject {
IBOutlet UIButton *wowButton;
}
#property(nonatomic,retain) IBOutlet UIButton *wowButton;
- (IBAction)wowButtonPressed:(id)sender;
int testvarAnimation;
int animNext;
#end
SettingsViewController.m:
#import "SettingsViewController.h"
#implementation SettingsViewController
#implementation SettingsViewController
#synthesize wowButton;
- (IBAction)wowButtonPressed:(id)sender{
NSLog(#"TOUCHED");
//testvarAnimation = 1;
animNext =1;
}
- (void)dealloc {
[wowButton release];
[super dealloc];
}
#end
Here I show you how I connected the Functions and the Outlets:
http://s3.imgimg.de/uploads/screenshotConna91ea645png.png
Please tell me If you need more informations.
Thanks
Hy I solved my problem, I rewrote my drawEAGLView Methode:
- (IBAction)drawEAGLView:(id)sender {
SettingsViewController *sViewController = [[SettingsViewController alloc] initWithNibName:#"SettingsViewController" bundle:nil];
[[self.view superview] addSubview:sViewController.view];
}
I also corrected my SettingsViewController.h:
#import <UIKit/UIKit.h>
#class EAGLView;
#interface SettingsViewController : UIViewController {
IBOutlet UIButton *wowButton;
EAGLView *glview;
}
#property(nonatomic,retain) IBOutlet UIButton *wowButton;
#property (nonatomic, retain) IBOutlet EAGLView *glView;
- (IBAction)wowButtonPressed:(id)sender;
int testvarAnimation;
int animNext;
#end
And last but not least I changed my SettingsViewController.m:
#import "SettingsViewController.h"
#import "EAGLView.h"
#implementation SettingsViewController
#synthesize wowButton, glView;
- (IBAction)wowButtonPressed:(id)sender{
NSLog(#"TOUCHED");
//testvarAnimation = 1;
animNext =1;
}
- (void)viewDidLoad {
glView.animationInterval = 1.0 / 60.0;
[glView startAnimation];
[super viewDidLoad];
}
- (void)dealloc {
[wowButton release];
[super dealloc];
}
#end
I also changed my Nib file. I removed the ViewController and set the type of the File's Owner to my viewController named "SettingsViewController". I connected the File's Owner Outlet view with the EAGLView and the button with the SettingsViewControllers wowButtonPressed Method
I hope I could help also someone else,
Thanks
Here is the right solution for this problem:
First you have to create a parnet object of your view you want to be shown as first.
You need to do this in the header file of the second view.
//
// SettingsViewController.h
// NeheTutorial2
//
// Created by Global Sound on 05.04.11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#import <UIKit/UIKit.h>
#class EAGLView;
#class mobilesynthViewController;
#interface SettingsViewController : UIViewController {
IBOutlet UIButton *wowButton;
IBOutlet UIButton *optiButton;
EAGLView *glView;
//mobilesynthViewController *mViewController;
mobilesynthViewController *parent;
}
#property(nonatomic,retain) IBOutlet UIButton *wowButton;
#property(nonatomic,retain) IBOutlet UIButton *optiButton;
#property (nonatomic, retain) IBOutlet EAGLView *glView;
//#property(nonatomic,retain) IBOutlet mobilesynthViewController *mViewController;
#property (nonatomic, retain) mobilesynthViewController *parent;
- (IBAction)wowButtonPressed:(id)sender;
- (IBAction)optiButtonPressed:(id)sender;
int testvarAnimation;
int animNext;
int musicOn;
int isAnimating;
float zaehler;
#end
Now in the implemetaion File you need to add the parent object to your function:
#import "SettingsViewController.h"
#import "EAGLView.h"
//#import "mobilesynthViewController.h"
#implementation SettingsViewController
#synthesize wowButton, optiButton, glView;//,mViewController;
#synthesize parent;
- (IBAction)wowButtonPressed:(id)sender{
NSLog(#"TOUCHED");
[parent startThread];
[parent showbButtonStop];
testvarAnimation = 0;
animNext =1;
//musicOn =1;
}
- (IBAction)optiButtonPressed:(id)sender{
NSLog(#"OPTIONS ON");
[self dismissModalViewControllerAnimated:YES];
[parent showbButton];
//mobilesynthViewController *aRootViewController = [[mobilesynthViewController alloc] initWithNibName:#"mobilesynthViewContoller" bundle:nil];
//[self setRootViewController:aRootViewController];
//[aRootViewController release];
//mobilesynthViewController *mViewController = [[mobilesynthViewController alloc] initWithNibName:#"mobilesynthViewController" bundle:nil];
//[[self.view superview] addSubview:mViewController.view];
//self.view = mViewController;
//CGRect rect = [[UIScreen mainScreen] applicationFrame];
//mViewController = [[mobilesynthViewController alloc] initWithFrame:CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height)];
//self.view = mViewController;
}
- (void)viewDidLoad {
glView.animationInterval = 1.0 / 60.0;
[glView startAnimation];
[super viewDidLoad];
}
/*
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
*/
- (void)dealloc {
[wowButton release];
[optiButton release];
[super dealloc];
}
#end
In my case I'm calling a other function in the main View of my program. When the button in the second view is pressed the function in the first view is called through the the parent object
[parent startThread];
Again the startThread methode was declerated in another view.
I hope I could help you.

how to access UI elements of one viewcontroller from an objective c class?

In my application i have some view controllers and one objective c class ,how can i access the UI elemets of one view controller to change their values in objective class .
To explain further , i have a UILable *lab in the firstviewcontroller and just imported
#import "firstViewController.h"
in my customclass.m file and i am trying to do like this in one method of objective c class
firstViewController.lab.text=#"example";
( i know its not correct method but i am trying to explain what i am doing )
can any one please tell me how can i do that ?
First thing you need to do is grab a reference to the view controller you wish to operate on. One way to do this and have it available to other classes is to store a reference to it in a singleton object that you instantiate in your customclass.m. Specifically this is how this method works:
Define Singleton Object:
#import <Foundation/Foundation.h>
#interface MySingleton : NSObject {
MyViewController *myViewController;
}
#propery (nonatomic. retain) MyViewController *myViewController;
+(MySingleton*)sharedMySingleton;
#implementation MySingleton
#synthesize myViewController;
static MySingleton* _sharedMySingleton = nil;
+(MySingleton*)sharedMySingleton
{
#synchronized([MySingleton class])
{
if (!_sharedMySingleton)
[[self alloc] init];
return _sharedMySingleton;
}
return nil;
}
+(id)alloc
{
#synchronized([MySingleton class])
{
NSAssert(_sharedMySingleton == nil, #"Attempted to allocate a second instance of a singleton.");
_sharedMySingleton = [super alloc];
return _sharedMySingleton;
}
return nil;
}
-(id)init {
self = [super init];
if (self != nil) {
// initialize stuff here
}
return self;
}
#end
Whereever you instantiate your myViewController you do this:
#import "MySingleton.h"
MySingleton *sinlgeton = [MySingleton sharedMySingleton];
singleton.myViewController = myViewController;
Now in your CustomClass.m you do this:
#import "MySingleton.h"
MySingleton *sinlgeton = [MySingleton sharedMySingleton];
singleton.myViewController.lab.text = #"example"
As I said this is ONE WAY to do this. However, you most probably DO NOT want to access and change view controller properties in a custom class so you should really rethink why you are doing this at all.
As with most programming tasks there are several solutions and it depends on the situation.
You can have FirstViewController own the instance of the MyCustomClass and then pass itself.
#interface FirstViewController : UIViewController {
MyCustomClass *customClass_;
}
#end
#implementation FirstViewController
- (void)viewDidLoad {
[super viewDidLoad];
customClass_ = [[MyCustomClass alloc] init]
customClass_.firstViewController = self;
}
#end
#interface MyCustomClass : NSObject {
FirstViewController *firstViewController;
}
#property (nonatomic, assign) FirstViewController *firstViewController;
#end
This way MyCustomClass can access the properties of FirstViewController. If you don't want to give MyCustomClass access to all of FirstViewController you can use pass along the properties that MyCustomClass should know about.
#interface FirstViewController : UIViewController {
MyCustomClass *customClass_;
UILabel *lab;
}
#property (nonatomic, retain) IBOutlet UILabel *lab;
#end
#implementation FirstViewController
- (void)viewDidLoad {
[super viewDidLoad];
customClass_ = [[MyCustomClass alloc] init]
customClass_.lab = self.lab;
}
#end
#interface MyCustomClass : NSObject {
UILabel *lab;
}
#property (nonatomic, retain) IBOutlet UILabel *lab;
#end
It could very well be the case that it doesn't make sense for FirstViewController to be the owner of MyCustomClass. Perhaps it is the AppDelegate or some parent controller that have access to both instances.
#interface RandomParentClass : NSObject {
FirstViewController *firstViewController;
MyCustomClass *customClass:
}
#end
#implementation RandomParentClass
- (void)setUpController {
firstViewController = [[FirstViewController alloc] init];
customClass = [[MyCustomClass alloc] init];
customClass.lab = firstViewController.lab;
// or
customClass.firstViewController = firstViewController;
}
#end

Sharing Data between XIB's

I'm following the James Brannan tutorial's, and im trying to share data between some xbis. No luck.
I have 2 xib's. The first, simple button and textfield. The second, just a label, to show the result of the first xib textfield.
So, i dont know what im doing wrong. Im using NSObject like in tutorial.
SharedData.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#interface SharedData : NSObject {
NSString *MeuNome;
}
#property (nonatomic, retain) NSString *MeuNome;
#end
SharedData.m
#import "SharedData.h"
#implementation SharedData
#synthesize MeuNome;
- (void) dealloc {
self.MeuNome = nil;
[super dealloc];
}
#end
FirstStepViewController.h
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import "SharedData.h"
#interface FirstStepViewController : UIViewController {
IBOutlet SharedData *sharedData;
IBOutlet UITextField *campoNome;
}
#property (nonatomic, retain) UITextField * campoNome;
#property (nonatomic, retain) SharedData *sharedData;
- (IBAction) takeNextStep: (id) sender;
#end
FirstStepViewController.m
#import "FirstStepViewController.h"
#import "SecondStepViewController.h"
#import "LuconeAppDelegate.h"
#implementation FirstStepViewController
#synthesize campoNome, sharedData;
- (IBAction) takeNextStep : (id) sender{
// declaracao de shared data
[sender resignFirstResponder];
self.sharedData.MeuNome = self.campoNome.text;
// faz animacao para proximo slide
SecondStepViewController *varSecondViewController = [[SecondStepViewController
alloc] initWithNibName:#"SecondStepViewController" bundle:nil ];
[self.navigationController pushViewController:varSecondViewController
animated: YES];
[self navigationController].navigationBarHidden = NO;
}
- (void)viewDidLoad {
[self navigationController].navigationBarHidden = YES;
[super viewDidLoad];
}
- (void)dealloc {
self.sharedData = nil;
//self.campoNome = nil;
[super dealloc];
}
#end
SecondStepViewController.h
#import <UIKit/UIKit.h>
#import "SharedData.h"
#interface SecondStepViewController : UIViewController {
IBOutlet SharedData *sharedData;
IBOutlet UILabel *nome;
}
#property (nonatomic, retain) SharedData *sharedData;
#property (nonatomic, retain) UILabel *nome;
#end
SecondStepViewController.m
#import "SecondStepViewController.h"
#import "SharedData.h"
#implementation SecondStepViewController
#synthesize nome, sharedData;
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = #"step two";
self.nome.text = self.sharedData.MeuNome;
}
- (void)dealloc {
self.sharedData = nil;
[super dealloc];
}
#end
What's wrong?
Thanks!
There are three small problems with your code.
IBOutlet is only for controls that you put on your view using interface builder e.g. UIButtons, UILabels. So it is unnecessary for instances of SharedData to be IBOutlets. Furthermore if you create your interface programmatically then using IBOutlet is again unnecessary.
You Declare that sharedData is an instance of SharedData class but you do not instantiate it. in your FirstStepViewController.m before you set any of sharedData's properties you should add the following code:
sharedData = [[sharedData alloc] init];
after that you can do:
self.sharedData.MeuNome = self.campoNome.text;
if you omit the "self." the code should work just as fine.
Finally before pushing the second view controller to the navigation stack you have to assign the sharedData object in your first view controller to sharedData in your second view controller.
in your FirstStepViewController.m add:
[varSecondViewController sharedData] = [self sharedData];
before:
[self.navigationController pushViewController:varSecondViewController
animated: YES];
Finally make sure you have connected all your outlets correctly in interface builder and everything should run perfectly then :)