ios assign self to property in another class - iphone

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.

Related

Delegates in iOS

I am a newbie to iOS world, so please ignore the obvious.
I am pushing a viewController(HelpViewController) on top of another viewController(MainViewController). When a particular action happens in the HelpViewController, I would like to update a variable inside the MainViewController. I understand for this I need to use delegate.
Here is my delegate header...
#protocol ViewControllerDelegate <NSObject>
#required
- (void) switchToggled:(BOOL)status;
#end
// Protocol Definition ends here
#interface ViewDelegate : NSObject
{
// Delegate to respond back
id <ViewControllerDelegate> _delegate;
}
#property (nonatomic,strong) id delegate;
-(void)sendMessage:(BOOL)status; // Instance method
#end
and implementation...
#implementation ViewDelegate
#synthesize delegate;
-(id)init {
self = [super init];
return self;
}
-(void)sendMessage:(BOOL)status
{
[delegate switchToggled:status];
}
- (void)dealloc
{
[super dealloc];
}
#end
So Now If I want to implement Protocol ViewControllerDelegate I need to specify in MainViewController, which I do as follows --
MainViewController <ViewControllerDelegate>
and
#pragma mark - ViewControllerDelegate delegate
-(void)switchToggled:(BOOL)status{
NSLog(#"Switch Toggled(%d) Message passed to MainViewController",status);
}
My question is how do I specify Object, which delegate property needs to point to, so that it can come back to MainViewController's "switchToggled".
One way I do is by having property inside HelpViewController as follows -
MainViewController.m
HelpViewController *helpVC = [[HelpViewController alloc] init];
helpVC.mainView = self;
[self.navigationController pushViewController:helpVC animated:YES];
[helpVC release];
HelpViewController.h
#property (nonatomic) MainViewController *mainView;
HelpViewController.m
#synthesize mainView;
ViewDelegate *myDelegate = [[ViewDelegate alloc] init];
// assign delegate
myDelegate.delegate = mainView;
[myDelegate sendMessage];
[myDelegate release];
Is this correct way to implement or there is better way to achieve this or am I totally wrong.
Thanks
You should do:
// HelpViewController.h
#protocol HelpDelegate
- (void)switchToggled:(BOOL)status;
#end
// HelpViewController.m
#interface HelpViewController : UIViewController
#property (nonatomic, assign) id<HelpDelegate> delegate;
- (id)initWithDelegate:(id<HelpDelegate>)delegate
#end
#implementation HelpViewController
- (id)initWithDelegate:(id<HelpDelegate>)delegate
{
if (self = [super init])
{
self.delegate = delegate;
}
}
- (void)sendMessage:(BOOL)status
{
[self.delegate switchToggled:status];
}
// MainViewController.h
#import "HelpViewController.h"
#interface MainViewController.h : UIViewController <HelpDelegate>
// MainViewController.m
- (void)someMethod
{
HelpViewController* viewController;
viewController = [HelpViewController alloc] initWithDelegate:self];
...
}
#pragma mark - Help Delegate
- (void)switchToggled:(BOOL)status
{
...
}
Give the delegate a name that makes clear to which class it belongs.
You don't need the extra class/files for ViewDelegate/ViewControllerDelegate. Just define the delegate in header of class it belongs to: HelpViewController.n in this case.
Similar: Implement the delegate method switchToggled: in the real class MainViewController, and not in the extra/unnecessary class ViewDelegate.
The purpose of delegates is to avoid class dependencies. By including MainViewController in HelpViewController you create such a dependency. This is not necessary as I show, and is wrong design.
You were also creating a circular dependency, because MainViewController already needed HelpViewController in order to show it, and now they need each other the other way around for sending the event.
Alternatively you can make HelpViewController's delegate public, have an init without argument, and expect users to set it with helpViewController.delegate = self; or something. But this would only make sense when the delegate being set is optional (which don't seems the case here, so adding it to the init method is appropriate).
I tell you what I would have done:
1) the protocol definition is ok, but do NOT create the class ViewDelegate, so:
//ViewControllerDelegate.h
#protocol ViewControllerDelegate <NSObject>
#required
- (void) switchToggled:(BOOL)status;
#end
2) Your implementation of the delegate method in MainViewController is ok.
3) Now... the important point:
//interface
#interface HelpViewController : UIViewController //or whatever superclass..
{
id <ViewControllerDelegate> _delegate;
}
#property (nonatomic,strong) id<ViewControllerDelegate> delegate;
#end
//implementation
#implementation HelpViewController
- (void)someMethodWhichCallsTheDelegate
{
//do something
...
// call delegate
//if switchToggled: were optional then add the following
//if ([self.delegate respondToSelector:#selector(switchToggled:)]) {
[self.delegate switchToggled:status];
}
#end
4) Now you have to assign the delegate:
//MainViewController.m
HelpViewController *helpVC = [[HelpViewController alloc] init];
helpVC.delegate = self;
[self.navigationController pushViewController:helpVC animated:YES];
[helpVC release];
And that's it!
BTW: if this delegate is related only to HelpViewControllerthen add the protocol definition where you define the interface of the class, it is not necessary to create a separate header file. If instead the protocol is "global", then it can have some sense to declare it separately.

How to change MutableArray from other view?

In my Application,
There are two different views ItemList And ItemSearch.
In ItemList file I have one NsMutableArray with name tblItem. I want pass data in tblitem from the Itemsearch page.
How can I do this?
You can make use of properties as follows:
1.Create a property in ItemList.h of tblItem as,
#property(nonatomic, retain) NSMutableArray *tblItem;
then synthesize it in ItemList.m,
#synthesize tblItem;
When you are navigating from ItemSearch to ItemList ie when you are initializing ItemList just provide tblItem the required values as,
ItemListObj.tblItem = theSearchedArray;
Declare an NSMutableArray as property in the SecondViewController and assign the array at the time you are pushing or presenting the SecondViewController from the FirstViewController.
#interface SecondViewController : UIViewController
{
NSMutableArray *aryFromFirstViewController;
}
#property (nonatomic,retain) NSMutableArray *aryFromFirstViewController;
#end
At the implementation, synthesize the property
#implementation SecondViewController
#synthesize aryFromFirstViewController;
#end
At the header of the FirstViewController import the SecondViewController
#import "SecondViewController.h"
At implementation of the FirstViewController, add the code like below in where you wrote the code to present or push the SecondViewController
#implementation FirstViewController
- (void) functionForPushingTheSecondViewController
{
SecondViewController *objSecondViewController = [[SecondViewController alloc] initWithNIBName: #"SecondViewController" bundle: nil];
objSecondViewController.aryFromFirstViewController = self.myAryToPass;
[self.navigationController pushViewController:objSecondViewController animated: YES];
[objSecondViewController release];
}
#end
Please don't forget to release the aryFromFirstViewController at dealloc method of SecondViewController, otherwise it will leak because we retained it. I'l feel good if i come to know that this helped you in someways. Enjoy.
It depends on your need. You can use Singleton class for sharing of your variables between different classes. Define all variable which you wants share in your DataClass.
in .h file (where RootViewController is my DataClass, replace name with your new class)
+(RootViewController*)sharedFirstViewController;
in .m file
//make the class singleton:-
+(RootViewController*)sharedFirstViewController
{
#synchronized([RootViewController class])
{
if (!_sharedFirstViewController)
[[self alloc] init];
return _sharedFirstViewController;
}
return nil;
}
+(id)alloc
{
#synchronized([RootViewController class])
{
NSAssert(_sharedFirstViewController == nil,
#"Attempted to allocate a second instance of a singleton.");
_sharedFirstViewController = [super alloc];
return _sharedFirstViewController;
}
return nil;
}
-(id)init {
self = [super init];
if (self != nil) {
// initialize stuff here
}
return self;
}
after that you can use your variable in any other class like this
[RootViewController sharedFirstViewController].variable
Hope it's help you:)

Change UIImageView from anotherVIewControllers

I am trying change an UIImageView from other viewControllers, but I don't know why image does not change !! here is my code :
#import "ViewController.h"
#class ViewController;
#interface CoverGallery : UIViewController {
ViewController *mainViewController;
}
#property (nonatomic,retain) ViewController *mainViewController;
- (IBAction)img1;
.m
- (IBAction)img1 {
mainViewController.coverArt.image = [UIImage imageNamed:#"coverDefault.png"];
[self dismissModalViewControllerAnimated:YES];
}
There is an UIImageView called coverArt in MainViewController , thanks
Here is my button action which switch between views :
ViewController (My First view)
.h
#interface ViewController : UIViewController {
ViewController *mainViewController;
}
#property (nonatomic, retain) ViewController *mainViewController;
.m :
#synthesize mainViewController;
- (void) CoverGallery {
CoverGallery *gallery = [[CoverGallery alloc] initWithNibName:#"CoverGallery" bundle:nil];
gallery.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:gallery animated:YES];
//here is the problem, compiler gives me the mainViewController is not the property of CoverGallery
gallery. mainViewController = self;
[gallery release];
}
How are you initializing the property mainViewController? You need set it as the MainViewController by setting its property when you present the modal view.
I imagine your doing this in the MasterViewController:
CoverGallery *gallery = [[CoverGallery alloc]initWithNibName:#"CoverGallery" bundle:nil];
gallery.masterViewContrller = self; //Set it here
[self presentModalViewController:gallery animated:YES];
I fixed a typo..
and this:
ViewController *mainViewController;
should be:
MainViewController *mainViewController;
but you need to Import it in the same header file.

Subclassed controls not being released

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.

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