Send a Delegate message from UIPopover to Main UIViewController - ios

I'm trying to use a Button in my UIPopover to create a UITextView in my Main UIViewController the code I have looks something like this (PopoverView.h file):
#protocol PopoverDelegate <NSObject>
- (void)buttonAPressed;
#end
#interface PopoverView : UIViewController <UITextViewDelegate> { //<UITextViewDelegate>
id <PopoverDelegate> delegate;
BOOL sendDelegateMessages;
}
#property (nonatomic, retain) id delegate;
#property (nonatomic) BOOL sendDelegateMessages;
#end
Then in my PopoverView.m file:
- (void)viewDidLoad
{
[super viewDidLoad];
UIButton * addTB1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
addTB1.frame = CGRectMake(0, 0, 100, 50);
[addTB1 setTitle:#"Textbox One" forState:UIControlStateNormal];
[self.view addSubview:addTB1]; // Do any additional setup after loading the view from its nib.
[addTB1 addTarget:self action:#selector(buttonAPressed)
forControlEvents:UIControlEventTouchUpInside];
}
- (void)buttonAPressed
{
NSLog(#"tapped button one");
if (sendDelegateMessages)
[delegate buttonAPressed];
}
And also in my MainViewController.m :
- (void)buttonAPressed {
NSLog(#"Button Pressed");
UITextView *textfield = [[UITextView alloc] init];
textfield.frame = CGRectMake(50, 30, 100, 100);
textfield.backgroundColor = [UIColor blueColor];
[self.view addSubview:textfield];
}
I'm using a delegate protocol to link the popover and the ViewController but I'm stuck on how I get my BOOL statement to link the -(void)buttonAPressed in the PopoverView and MainViewController so that when I press the button in the Popover a textview appears in the Main VC. How would I go about doing this?

In MainViewController, where you create PopoverView, be sure to set its delegate property otherwise sending messages to delegate in PopoverView will do nothing.
For example, in MainViewController.m:
PopoverView *pov = [[PopoverView alloc] initWithNibName:nil bundle:nil];
pov.delegate = self; // <-- must set this
thePopoverController = [[UIPopoverController alloc] initWithContent...
I am not sure why you need the sendDelegateMessages variable. Even with that bool, you must set the delegate property so PopoverView has an actual object reference to send the messages to.
If you want to make sure the delegate object has implemented the method you're about to call, you can do this instead:
if ([delegate respondsToSelector:#selector(buttonAPressed)])
[delegate buttonAPressed];
Also, the delegate property should be declared using assign (or weak if using ARC) instead of retain (see Why use weak pointer for delegation? for an explanation):
#property (nonatomic, assign) id<PopoverDelegate> delegate;
Another thing is if you're not using ARC, you need to add [textfield release]; at the end of the buttonAPressed method in MainViewController to avoid a memory leak.

Related

Custom UIView doesnt show

I have very simple UIView that creating the box, but what is happen is the UIView does not show at all, here is my code on sharingButtons.m
-(void)createContainer{
winWidth = [UIScreen mainScreen].bounds.size.width;
buttonContainer = [[UIView alloc] initWithFrame:CGRectMake(0, 0, winWidth, 20)];
buttonContainer.backgroundColor = [UIColor redColor];
[self.view addSubview:buttonContainer];
}
-(void)createButton{
[self createContainer];
}
and here is my sharingButtons.h
#interface SocialSharing : UIViewController {
int winWidth;
}
- (void)createButton;
- (void)createContainer;
#pragma mark - Properties
#property(nonatomic, strong) UIView* buttonContainer;
#end
And createButton method is called from MyViewControler.m on viewDidLoad
Is any wrong with my code??
EDITED
Here is my code on MyViewControler.m
- (void)loadSocialSharingButton {
socialButtons = [[SocialSharing alloc] init];
[socialButtons createButton];
}
- (void)viewDidLoad {
[super viewDidLoad];
[self loadSocialSharingButton];
}
Sorry I just learn about obj c :)
Thanks a lot
The reason your buttonContainer is not visible is, it is not loaded in your view hierarchy.
To make it visible you should add it as subview. In MyViewController.m in viewDidLoad add the following line after [self loadSocialSharingButton];
[self.view addSubview:socialButtons.buttonContainer];
Hope this Helps!
Your SocialSharing is subclass of UIViewController.
And you add your buttonContainer view to this SocialSharing Controller,this controller is not on screen if you just call
socialButtons = [[SocialSharing alloc] init];
[socialButtons createButton];
So,you can not see anything.
In an iOS App, only one ViewController at a time is active. And as you are at MyViewController, so MyViewController is active, if you want to navigate to any other view controller than you need to present or push the instance of same. Doing so will make the other view controller as active.
In your case the problem is your SocialSharing is a subclass of UIViewController as it is created as SocialSharing : UIViewController and it's not active, so adding any view over it won't be visible as the instance of SocialSharing is not pushed/ presented. If you need to show the view from SocialSharing than either you subclass it from UIView or push/ present the instance of SocialSharing to make it's view active and visible.
You are currently # MyViewController and But you are loading your custom view # SocialSharing ViewController, Both ViewController are distinct and you can't just get your custom view at social sharing to MyViewController by initializing it.
You have change SocialSharing class as sub class of UIView and initialize this view and add to subview of MyViewController.
SocialSharing.h
#interface SocialSharing : UIView {
int winWidth;
}
- (instancetype)createButton;
#pragma mark - Properties
#property(nonatomic, strong) UIView* buttonContainer;
#end
SocialSharing.m
- (instancetype)createButton
{
winWidth = [UIScreen mainScreen].bounds.size.width;
self = [super initWithFrame:CGRectMake(0, 0, winWidth, 20)];
if (self) {
buttonContainer = [[UIView alloc] initWithFrame:];
buttonContainer.backgroundColor = [UIColor redColor];
[self addSubview:buttonContainer];
}
return self;
}
MyViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
[self loadSocialSharingButton];
}
- (void)loadSocialSharingButton {
socialButtons = [SocialSharing alloc] createButton];
[self.view addSubView:socialButtons];
}

How to pass a button action from a uiview to another view controller

I have a uiview named leftMenuView and on that view i have a button and i want to add an action to that button so that action method should call a view controller. Take a look what till i have done:
this is my leftMenuView.h
#import <UIKit/UIKit.h>
#class LeftMenuView;
#protocol LeftMenuViewProtocol <NSObject>
-(void)homeClicked;
#end
#interface LeftMenuView : UIView
#property (nonatomic,assign) id<LeftMenuViewProtocol> customDelegate;
-(IBAction)homeClickedAction:(id)sender;
#end
and in leftMenuView.m file
#import "LeftMenuView.h"
#implementation LeftMenuView
-(IBAction)homeClickedAction:(id)sender
{
[self.customDelegate homeClicked];
NSLog(#"Clicked Home");
}
#end
Now i am trying to call that method through the delegate
Now in homeViewController.h
#interface homeViewController : UIViewController<LeftMenuViewProtocol>
and now in my homeViewController.m i am trying to call that method but it is not called
-(void)homeClicked
{
NSLog(#"Clicked Home");
}
But the above method is not called where as in leftViewMenu.m that method is called. Hope any one helps me regarding this issue.
Or, assuming you have a reference on your leftMenuView in your homeViewController you can create your UIButton programmatically and set the target of your button with your homeViewController. For example, in the viewDidLoad of your homeViewController, you can do something like:
UIButton *myButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 100, 20)]; // set the frame you want
myButton.backgroundColor = [UIColor redColor]; // Do additional set up
[myButton addTarget:self action:#selector(homeClicked) forControlEvents:UIControlEventTouchUpInside]; // here the target of your button's action is your homeViewController
[self.leftMenuView addSubView:myButton]; // Add the button in your left view
I suppose that in homeViewController you have a property for the LeftMenuView you need to set the customDelegate to self. In the homeViewController viewDidLoad method:
self.leftMenuView.customDelegate = self;

Button is disabled when adding background

I am using Parse anypic tutorial and I want to create a somehow different UI. But I have some troubles.
So, my ViewController is this :
#interface PAPHomeViewController ()
#property (nonatomic, strong) PAPSettingsActionSheetDelegate *settingsActionSheetDelegate;
#property (nonatomic, strong) UIView *blankTimelineView;
#end
#implementation PAPHomeViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"LoadView is called");
// Present Anypic UI
[self presentUI];
}
-(void) presentUI {
/*UIImageView *backgroundImageView = [[UIImageView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
[backgroundImageView setImage:[UIImage imageNamed:#"DefaultAnypic.png"]];
self.view = backgroundImageView;*/
// Settings button
self.settingsButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[self.settingsButton addTarget:self
action:#selector(settingsButtonAction:)
forControlEvents:UIControlEventTouchUpInside];
[self.settingsButton setTitle:#"Settings" forState:UIControlStateNormal];
self.settingsButton.frame = CGRectMake(200.0, 200.0, 100.0, 100.0);
[self.view addSubview:self.settingsButton];
}
and its .h file is this :
#interface PAPHomeViewController : PAPPhotoTimelineViewController
#end
The PAPPhotoTimelineViewController is also a separateViewController, which the Home extends from and it is a tableViewController, which also calls ViewDidLoad.
The problem :
With the above Code, I see my button and I can click on my button.
But, if I uncomment stuff for the background, I do see the background, I do see the button, but it cannot be clicked - it is like no touch on the button is identified.
I am also confused, now that I am extending another ViewController which also implements viewDidLoad, why they are both called, in which order etc.
You shouldn't assign a new UIView to your self.view.
Instead of self.view = backgroundImageView;, just add it like a random view.
[self.view addSubview:backgroundImageView];
Doing that, you will follow the right way to add subview: your backgroundImageView will be displayed in your view, and your button will be add above it.

ARC and autoreleased object

I need a ViewController to be called modally to show some UIButton and other UIView on top of the current window. I want the background to be partially transparent and showing the current window below it - something similar to a UIActionSheet but with a custom design. I coded my VC to do the following: 1) during init the VC sets self.view.frame equals to [[UIApplication sharedApplication]keyWindow].frame 2) when show() is called the VC adds self.view on top of [[UIApplication sharedApplication]keyWindow] subViews 3) when an internal button calls the private method release() the VC remove self.view from its superview. Example with a single release button as follows:
#implementation ModalController
- (id)init
{
self = [super init];
if (self){
//set my view frame equal to the keyWindow frame
self.view.frame = [[UIApplication sharedApplication]keyWindow].frame;
self.view.backgroundColor = [UIColor colorWithWhite:0.3f alpha:0.5f];
//create a button to release the current VC with the size of the entire view
UIButton *releaseMyselfButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[releaseMyselfButton setTitle:#"Release" forState:UIControlStateNormal];
releaseMyselfButton.frame = CGRectMake(0, 0, 90, 20);
[releaseMyselfButton addTarget:self action:#selector(releaseMyself) forControlEvents:UIControlEventTouchDown];
//add the button to the view
[self.view addSubview:releaseMyself];
}
return self;
}
- (void) show
{
//add self.view to the keyWindow to make sure that it will appear on top of everything else
[[[UIApplication sharedApplication]keyWindow] addSubview:self.view];
}
- (void)releaseMyself
{
[self.view removeFromSuperview];
}
#end
If I create an instance of ModalController from another VC and I call show() everything goes as expected:
#interface CurrentVC ()
#property (strong, nonatomic) ModalController *myModalController;
#end
#implementation CurrentVC
- (void)viewDidLoad
{
[super viewDidLoad];
self.myModalController = [[ModalController alloc]init];
[self.myModalController show];
}
#end
To make it work I need to retain the ModalController in a property until release () is called. However I would like to have the same freedom I have with UIActionSheet and simply keep an instance of it in a local variable:
#implementation CurrentVC
- (void)viewDidLoad
{
[super viewDidLoad];
ModalController *myModalController = [[ModalController alloc]init];
[myModalController show];
}
#end
If I do this with the current code ARC will release myModalController straight after show() is called and the release button will be pointing to nil. How can I make this work without storing the object in a property? I've identified a work around but I'm not sure it's a good design option:
#interface ModalController ()
#property (strong, nonatomic) ModalController *myselfToAutorelease;
#implementation ModalController
- (id)init
{
self = [super init];
if (self){
... ... ...
self.myselfToAutorelease = self;
}
return self;
}
- (void) show
{
... ... ...
}
- (void)releaseMyself
{
[self.view removeFromSuperview];
self.myselfToAutorelease = nil;
}
What I've done is making ModalController "self sufficient" - it stores a pointer to itself during init and set it to nil when it's ready to release himself. It works but I have the feeling that this is against the ARC design principles! Is this approach correct? If not, how can I handle this differently?
Thanks in advance for your help.
Doesn't work like that.
You don't keep a reference to self.
In the main view controller you just create your object. If you need it to be around longer keep it in a property in the main view controller , when done, set the property to nil in the main view controller.

Accessing UIButton from another class not working?

I am trying to access my UIButton in my Play class from my CCLayerClass.
The problem is that it is not working!
Here is how I declare it in the Play class:
.h
IBOutlet UIButton *pauseButton;
#property(nonatomic, retain) IBOutlet UIButton *pauseButton;
.m
#synthesize pauseButton;
Then in the dealloc:
[pauseButton release];
Also of course I connect it then in Interface builder.
Then in my other class (My CCLayer) class. I try to do this:
Play *play = [[[Play alloc] init] autorelease];
[play.pauseButton setHidden:YES];
The thing is, is that it simply just does not hide the button. Is there any reason for this?
Thanks!
Edit1:
My Play.h
IBOutlet UIButton *pauseButton;
BOOL pauseButtonVisible;
#property(nonatomic, retain) IBOutlet UIButton *pauseButton;
#property(readwrite) BOOL pauseButtonVisible;
.m
#synthesize pauseButton;
- (void)setPauseButtonVisible: (BOOL) variableToSet {
pauseButtonVisible = variableToSet;
if(pauseButton)
[pauseButton setHidden: !pauseButtonVisible];
}
- (BOOL) pauseButtonVisible
{
return(pauseButtonVisible);
}
viewWillAppear:
[pauseButton setHidden: !pauseButtonVisible];
I also made sure I connected it in Interface Builder
Then in CCLayerClass I do this:
Play *play = [[[Play alloc] init] autorelease];
if(play.pauseButton == NULL) {
NSLog( #"pause button is NULL");
}
But that NSLog gets called! Why is my pauseButton NULL? I just need to alloc it so it stays alive, is that possible?
Thanks!
play.pauseButtonVisible = YES;
Okay. Hopefully third time is the charm (and after that, I'm giving up cause it's time for me to go to bed).
Here in the .h file, I'm keeping the new pauseButtonVisible BOOL property.
#interface Play : UIViewController
{
BOOL pauseButtonVisible;
IBOutlet UIButton *pauseButton;
}
#property(nonatomic, retain) IBOutlet UIButton *pauseButton;
#property(readwrite) BOOL pauseButtonVisible;
#end
But in the .m file, we're doing something a little different:
#interface Play
// here we are rolling our own setters and getters
// instead of #synthesizing...
- (void)setPauseButtonVisible: (BOOL) variableToSet
{
pauseButtonVisible = variableToSet;
if(pauseButton)
[pauseButton setHidden: !pauseButtonVisible];
}
- (BOOL) pauseButtonVisible
{
return(pauseButtonVisible);
}
- (void) viewWillAppear: (BOOL) animated
{
[pauseButton setHidden: !pauseButtonVisible];
[super viewWillAppear: animated];
}
and
Play *play = [[[Play alloc] init] autorelease]; // you should really be using initWithNibName, but anyways
play.pauseButtonVisible = YES;
So now, hopefully pause button will be visible or hidden at the appropriate time for while your code is running.

Resources