I need to upload a local picture in my webview (IOS).
Apparently, it seems that Apple has some problems with that.
2016-04-06 18:47:37.337 DemoWebView[839:112324] Warning: Attempt to
present on whose view is not in the window hierarchy!
(iOS 8 SDK: modal UIWebView and camera/image picker)
Despite my extensive research, I didn't find a solution to my problem.
if anyone can help me .. I would be very grateful.
class : ViewController
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[button setFrame:CGRectMake(80, 150, 160, 60)];
button.backgroundColor = [UIColor whiteColor];
[button setTitle:#"Click Here !" forState:UIControlStateNormal];
[self.view addSubview:button];
}
-(void) buttonClicked:(UIButton*)sender{
ViewController2 * test = [[ViewController2 alloc]init];
[self presentViewController:test animated:true completion:NULL];
}
#end
class : ViewController2
#interface ViewController2 : UIViewController
#end
#import "ViewController2.h"
#interface ViewController2 ()
#property (strong, nonatomic) UIWebView *webView;
#end
#implementation ViewController2
- (void)viewDidLoad {
[super viewDidLoad];
_webView = [[UIWebView alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.view = _webView;
[_webView loadHTMLString:#"<br /><br /><input type=\"file\" accept=\"image/*;capture=camera\">" baseURL:nil];
}
#end
DemoProjet :
Thks
You are trying to present UIWebview indirectly from first ViewController,that's reason you are getting warning message.
Try This:
#import "ViewController2.h"
#interface ViewController2 (){
UIWebView *webView;
}
#end
#implementation ViewController2
- (void)viewDidLoad {
[super viewDidLoad];
webView = [[UIWebView alloc] init];
[self.view addSubview:webView]
}
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
webView.frame = [UIScreen mainScreen].bounds;
[_webView loadHTMLString:#"Your_html_string" baseURL:nil];
}
}
#end
update: I saw your question containing link and i found that you didn't override this method
-(void)dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion
{
if ( self.presentedViewController)
{
[super dismissViewControllerAnimated:flag completion:completion];
}
}
It works with the override. Thanks a lot for your answer.
EDIT
I understand why it didn't work in the first time i tried.. In my main app, i have a UINavigationController class but i continued to override the dismiss method in my UIViewController class.
Related
Here is the main idea
+---MyViewController.m----+ +---BtnOnClickResp.m-----+
| | EventTouchUpInside: | |
| Button ---------------------------------------> OnBtnClick() |
| | textView.text=#"blabla"| | |
| *textView <------------------------------------------ + |
| | | |
+-------------------------+ +------------------------+
I want to test if button OnClick could be pressed in another controller like this:
MyViewController.h
#import <UIKit/UIKit.h>
#interface MyViewController : UIViewController
#property (nonatomic, strong) UITextView *textView;
+(id) sharedInstance;
#end
MyViewController.m
#import "MyViewController.h"
#import "BtnOnClickResp.h"
#interface MyViewController ()
#end
#implementation MyViewController
#synthesize textView;
+ (id) sharedInstance{
static MyViewController *instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
});
return instance;
}
- (void) setUpScene{
textView = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, 500, 400) ];
[textView setBackgroundColor:[UIColor grayColor]];
[textView setFont:[UIFont systemFontOfSize:18]];
[textView setTextColor:[UIColor blackColor]];
textView.text = #"";
[self.view addSubview:textView];
UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(100, 50 , 400, 50)];
[btn setTitle:#"Click Me" forState:UIControlStateNormal];
[btn setBackgroundColor:[UIColor yellowColor]];
[btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[btn addTarget:[[BtnOnClickResp alloc] init] action:#selector(onBtnClick:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
}
- (void)viewDidLoad {
[super viewDidLoad];
[self setUpScene];
// Do any additional setup after loading the view.
}
#end
BtnOnClickResp.h
#import <UIKit/UIKit.h>
#interface BtnOnClickResp : UIViewController
#end
BtnOnClickResp.m
#import "BtnOnClickResp.h"
#import "MyViewController.h"
#interface BtnOnClickResp ()
#end
#implementation BtnOnClickResp
- (void) onBtnClick: (UIButton *) btn{
NSLog(#"btn was click but I am in another controller");
MyViewController *control = [MyViewController sharedInstance];
control.textView.text = #" I am setting this content in another view cheers!!!";
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
The main idea is draw/add a button view in the MyViewController and make the response to click code in another controller, I thought the action assignment code:
[btn addTarget:self action:#selector(onBtnClick:) forControlEvents:UIControlEventTouchUpInside];
if we change the self to the actually controller we want to use then the click event will be dispatched to that controller
But it seems not working.
Really a beginner of ios development would be happy if you don't downvote this beginner's question.
EIDT
After taking the advice as #Mike suggested,
I change the MyViewController.m to this:
#import "MyViewController.h"
#import "BtnOnClickResp.h"
#interface MyViewController (){
//here is the change , I made a private ref of the controller
BtnOnClickResp *respContl;
}
#end
#implementation MyViewController
#synthesize textView;
+ (id) sharedInstance{
static MyViewController *instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
});
return instance;
}
- (void) setUpScene{
textView = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, 500, 400) ];
[textView setBackgroundColor:[UIColor grayColor]];
[textView setFont:[UIFont systemFontOfSize:18]];
[textView setTextColor:[UIColor blackColor]];
textView.text = #"";
[self.view addSubview:textView];
UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(100, 50 , 400, 50)];
[btn setTitle:#"Click Me" forState:UIControlStateNormal];
[btn setBackgroundColor:[UIColor yellowColor]];
[btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[btn addTarget:respContl action:#selector(onBtnClick:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
}
- (void)viewDidLoad {
respContl = [[BtnOnClickResp alloc] init];
[super viewDidLoad];
[self setUpScene];
// Do any additional setup after loading the view.
}
#end
Now I could see the NSLog of btn was click but I am in another controller but the view content still kept not changed to #" I am setting this content in another view cheers!!!" as it expected to be in BtnOnClickResp.m
This is the launch code in AppDelagate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
UIViewController *control = [[MyViewController alloc] init];
[self.window setRootViewController:control];
[self.window setBackgroundColor:[UIColor greenColor]];
[self.window makeKeyAndVisible];
// Override point for customization after application launch.
return YES;
}
You are adding Target
[btn addTarget:[[BtnOnClickResp alloc] init] action:#selector(onBtnClick:) forControlEvents:UIControlEventTouchUpInside];
to
[BtnOnClickResp alloc] init]
is Wrong
Because it will create new instance and add listener to it.
However you are try to access action in other instance
You have 4 solutions
Create shared instance of BtnOnClickResp and assign target to it
Pass the self of BtnOnClickResp to the MyViewController on and assign it
Create Delegate
Post Notification
Declare a property of BtnOnClickResp and set it as button target.
#import "MyViewController.h"
#import "BtnOnClickResp.h"
#interface MyViewController ()
#property(nonatomic, strong) BtnOnClickResp onClickRespObj;
#end
#implementation MyViewController
#synthesize textView;
+ (id) sharedInstance{
static MyViewController *instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
});
return instance;
}
- (id)init{
if(self = [super init]){
self.onClickRespObj = [[BtnOnClickResp alloc] init];
}
return self;
}
- (void) setUpScene{
textView = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, 500, 400) ];
[textView setBackgroundColor:[UIColor grayColor]];
[textView setFont:[UIFont systemFontOfSize:18]];
[textView setTextColor:[UIColor blackColor]];
textView.text = #"";
[self.view addSubview:textView];
UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(100, 50 , 400, 50)];
[btn setTitle:#"Click Me" forState:UIControlStateNormal];
[btn setBackgroundColor:[UIColor yellowColor]];
[btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[btn addTarget:self.onClickRespObj action:#selector(onBtnClick:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
}
- (void)viewDidLoad {
[super viewDidLoad];
[self setUpScene];
// Do any additional setup after loading the view.
}
#end
Hi I am adding one custom button programmatically on navigation bar and i have written all button properties in my background class and i am calling this method from my main class
And here I have used protocols for getting button touching event in my main class from background class but it's not working using protocols
my code:-
background class:-
BackGroundClass.h
#import <UIKit/UIKit.h>
#protocol buttonprotocol<NSObject>
#required
- (void) buttonTapped;
#end
#interface BackGroundClass : UIViewController
#property (nonatomic, weak) id<buttonprotocol> delegate;
#end
BackGroundClass.m
#import "BackGroundClass.h"
#interface BackGroundClass ()
#end
#implementation BackGroundClass
#synthesize delegate;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)backbutton: (UINavigationItem *)navigationitem
{
UIImage* image3 = [UIImage imageNamed:#"back.png"];
CGRect frameimg = CGRectMake(15,5,25,25);
UIButton *someButton = [[UIButton alloc] initWithFrame:frameimg];
[someButton setBackgroundImage:image3 forState:UIControlStateNormal];
[someButton addTarget:self action:#selector(Back_btn:)
forControlEvents:UIControlEventTouchUpInside];
[someButton setShowsTouchWhenHighlighted:YES];
UIBarButtonItem *mailbutton =[[UIBarButtonItem alloc] initWithCustomView:someButton];
navigationitem.leftBarButtonItem = mailbutton;
}
- (void)Back_btn :(id)sender
{
[delegate buttonTapped];
}
#end
main class:-
mainclass.h
#import <UIKit/UIKit.h>
#import "BackGroundClass.h"
#interface mainclass : UIViewController<buttonprotocol>
mainclass.m
#import "mainclass.h"
#import "BackGroundClass.h"
#interface mainclass ()
{
BackGroundClass * bg;
}
#end
#implementation mainclass
- (void)viewDidLoad {
[super viewDidLoad];
bg = [[BackGroundClass alloc]init];
[bg backbutton:self.navigationItem];
}
- (void)buttonTapped
{
NSLog(#"ok it's 2");
}
but that above button tapped a method isn't called what I did wrong?
When you are creating the object of your BackGroundClass class, then you are not setting the delegate of the class to self, thats why your delegate method is not calling, try it like this
bg = [[BackGroundClass alloc]init];
bg.delegate = self;
First of all, using Class in class names is bad practice. As for View Controllers you should use either ViewController or VC postfix for your class names.
For example, the proper names of your Objective-C classes would be: BackgroundViewController, MainViewController
Secondly, ViewController instances are used to react to user interaction with the view attached to this ViewController and provide visible changes based on Data component of MVC work.
So, there is no reason to use second, in your case BackgroundViewController (BackgroundClass).
For more info about MVC pattern, please refer this link:
Apple's MVC articles
As there is no need in external ViewController we also should remove the delegate using and place all logic inside this main View Controller.
Thirdly, as mentioned in Apple's Mobile HIG, buttons should have a height around 44px, so your back button's size of 25x25 would make most users experience hard trying to tap on it.
At last, you should receive the class with code similar to it:
MainViewController.h
#import <UIKit/UIKit.h>
#interface MainViewController : UIViewController
#end
MainViewController.m
#import "MainViewController.h"
#implementation MainViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIImage *icon = [UIImage imageNamed:#"back.png"];
static CGFloat defaultButtonSize = 44.; // Default button's tap area size
CGSize buttonSize = CGSizeMake(defaultButtonSize, defaultButtonSize);
// The size image should take inside the button
CGSize imageSizeInsideButton = CGSizeMake(25., 25.);
CGRect frameimg = CGRectMake(15., 5., defaultButtonSize, defaultButtonSize);
UIButton *someButton = [[UIButton alloc] initWithFrame:frameimg];
[someButton setImage:icon forState:UIControlStateNormal];
[someButton addTarget:self
// No need to put colon after method name,
// since you have no use of control that triggered action
action:#selector(backButtonClicked)
forControlEvents:UIControlEventTouchUpInside];
someButton.showsTouchWhenHighlighted = YES;
// Calculate edge insets so image will take the size
// you specified dozen of lines before
CGFloat imageVerticalPaddingInButton = (buttonSize.height - imageSizeInsideButton.height) / 2.;
CGFloat imageHorizontalPaddingInButton = (buttonSize.height - imageSizeInsideButton.height) / 2.;
// Apply it to button
someButton.imageEdgeInsets = UIEdgeInsetsMake(imageVerticalPaddingInButton,
imageHorizontalPaddingInButton,
imageVerticalPaddingInButton,
imageHorizontalPaddingInButton);
UIBarButtonItem *mailbutton =[[UIBarButtonItem alloc] initWithCustomView:someButton];
self.navigationItem.leftBarButtonItem = mailbutton;
}
// As stated in "addTarget", there is no "sender" since you don't really need it
// If you ever would need the use of it,
// don't forget to put colon in "addTarget" UIButton's method
// and place something like :(UIButton *)buttonThatClicked
// after methodName
- (void)backButtonClicked {
// Get back to your previous view controller or do whatever you like there
[self.navigationController popViewControllerAnimated:YES];
}
#end
But if you want to use this thing in as many View Controllers as possible, then you should create the category:
UIViewController+CustomBackButton.h
#import <UIKit/UIKit.h>
#interface UIViewController (CustomBackButton)
- (void)setBackButtonImage:(UIImage *)image withSize:(CGSize)size target:(id)target selector:(SEL)selector;
#end
UIViewController+CustomBackButton.m
#import "UIViewController+CustomBackButton.h"
#implementation UIViewController (CustomBackButton)
- (void)setBackButtonImage:(UIImage *)image withSize:(CGSize)size target:(id)target selector:(SEL)selector {
static CGFloat defaultButtonSize = 44.;
CGSize buttonSize = CGSizeMake(defaultButtonSize, defaultButtonSize);
CGRect frameimg = CGRectMake(15., 5., defaultButtonSize, defaultButtonSize);
UIButton *someButton = [[UIButton alloc] initWithFrame:frameimg];
[someButton setImage:image forState:UIControlStateNormal];
[someButton addTarget:target
action:selector
forControlEvents:UIControlEventTouchUpInside];
someButton.showsTouchWhenHighlighted = YES;
CGFloat imageVerticalPaddingInButton = (buttonSize.height - size.height) / 2.;
CGFloat imageHorizontalPaddingInButton = (buttonSize.height - size.height) / 2.;
someButton.imageEdgeInsets = UIEdgeInsetsMake(imageVerticalPaddingInButton,
imageHorizontalPaddingInButton,
imageVerticalPaddingInButton,
imageHorizontalPaddingInButton);
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithCustomView:someButton];
self.navigationItem.leftBarButtonItem = backButton;
}
#end
And then your View Controller's implementation file will be much cleaner.
MainViewController.m
#import "MainViewController.h"
#import "UIViewController+CustomBackButton.h"
#implementation MainViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIImage *icon = [UIImage imageNamed:#"back.png"];
CGSize iconSize = CGSizeMake(25., 25.);
[self setBackButtonImage:icon
withSize:iconSize
target:self
selector:#selector(backButtonClicked)];
}
- (void)backButtonClicked {
// Get back to your previous view controller or do whatever you like there
[self.navigationController popViewControllerAnimated:YES];
}
#end
And then you can use this on every ViewController to customize your back button.
It seems like such a simple thing to remove a button from a view, but it is not working.
MyViewController.h
#import <UIKit/UIKit.h>
#interface MyViewController : UIViewController
#property (strong, nonatomic, readonly, getter = getMyButton) UIButton* myButton;
- (id) init;
- (id) getMyButton;
#end
MyViewController.m
#import "MyViewController.h"
#interface MyViewController ()
#end
#implementation MyViewController
#synthesize myButton = _myButton;
- (id) init
{
if([super initWithNibName: nil bundle: nil])
{
_myButton = nil;
}
return self;
}
- (id) getMyButton
{
if(!_myButton) _myButton = [self createMyButton];
return _myButton;
}
- (void) viewDidLoad
{
[super viewDidLoad];
UIButton* myButton = self.myButton;
[self.view addSubview: myButton];
}
- (void) didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (UIButton*) createMyButton
{
UIButton *button = [[UIButton alloc] init];
[button setTitle: #"My Button"
forState: UIControlStateNormal];
[button addTarget: self
action: #selector(myAction:)
forControlEvents: UIControlEventTouchUpInside];
button.frame = CGRectMake(10, 10, 100, 40);
return button;
}
- (void) myAction: (id) sender
{
[self.myButton performSelectorOnMainThread: #selector(removeFromSuperview) withObject: nil waitUntilDone: NO];
}
#end
But no luck. Clicking the button simply does nothing.
If it is not a problem of concurrency then maybe it is a memory management problem? Maybe it is just something daft, I don't know.
I tried putting the following line into the myAction method
NSLog(#"Test 1");
if(_startButton.superview) NSLog(#"Test 2");
Only 'Test 1' is logged. Perhaps that is a clue but what I don't know is why the button has no superview when it is added to view and is visible on the screen
Additional information
I don't know, if any of this is relevant, but maybe
I just updated Xcode to the latest version from the developer program (it supported up to iOS version 7.0 before, now 7.1)
I just started testing the app on an actual iPhone (I get the same problem testing with the simulator though)
Around the same time as this problem I also noticed that NSLog function doesn't work inside AppDelegate applicationHasLaunched method
Thanks
You didn't set the action for that button.
Change your createMyButton method like:
- (UIButton*) createMyButton
{
UIButton *button = [[UIButton alloc] init];
[button setTitle: #"My Button"
forState: UIControlStateNormal];
button.frame = CGRectMake(10, 10, 100, 40);
[button addTarget:self action:#selector(myAction:) forControlEvents:UIControlEventTouchUpInside];
return button;
}
Also change myAction method like:
- (void)myAction:(UIButton *)sender
{
[sender performSelectorOnMainThread: #selector(removeFromSuperview) withObject: nil waitUntilDone: NO];
}
Your code seems overly complicated:
Why do you need to lazy create the button?
Why does it need to be readonly?
Why do you need the performselector in your action?
I have taken the liberty to rewrite your code:
Header file
#property (nonatomic,strong) UIButton * button;
Code file
- (void)viewDidLoad
{
[super viewDidLoad];
self.button = [UIButton buttonWithType:UIButtonTypeSystem];
[self.button setTitle:#"MyButton" forState:UIControlStateNormal];
self.button.frame = self.view.bounds;
[self.button addTarget:self action:#selector(myAction:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.button];
}
-(void)myAction:(UIButton*)sender
{
[sender removeFromSuperview];
}
Happy coding!
Edit
If you insist on going with your original code, try changing
- (id) getMyButton
to
-(UIButton*)myButton
Buttons are a class family and should be created with [UIButton buttonWithType:]
I am sure that your myAction is not get fired. Cause you forget to addTarget
on your createMyButton method just add one more line
[button addTarget:self action:#selector(myAction:) forControlEvents:UIControlEventTouchUpInside];
UPDATE: You've also marked this question as iOS but you are importing OSX headers
#import "NSViewController.h"
#interface MyViewController: NSViewController
you should be inheriting from UIViewController
#import <UIKit/UIKit.h>
#interface MyViewController : UIViewController
Are you creating the view controller via the init code you've posted?
- (id) init
{
if([super initWithNibName: nil bundle: nil])
{
_myButton = nil;
}
return self;
}
Here you are not allocating anything to self the code should be
- (id) init
{
self = [super initWithNibName: nil bundle: nil];
if(self)
{
_myButton = nil;
}
return self;
}
This question already has answers here:
Passing data between view controllers
(45 answers)
Closed 8 years ago.
What I have is menu at the top (vertical slider). On the top I have button, on clicking this button, the view will get scroll down and display the menu.
For this what I am doing is creating a view and showing it at top.
Now when I click on the button, I am planning to change the frame of top view with animation.
I am able to handle the frame and animation, however problem I am facing is setting the text to the right label and left button.
Below is the dropbox link to download the sample project. Any idea/ solution will be appreciated.
https://www.dropbox.com/s/pdaelw2k8ljnaki/TwoView.zip
What I tried is below code
CommonViewController *newClass = [[CommonViewController alloc] init];
newClass.parentObject = self;
NSLog(#"text is %#", newClass.rightSideLabel.text);
newClass.rightSideLabel.text = #"NEW VALUE HERE";
However still on the right side I see products only.
Full Code
CommonViewController.h
#import <UIKit/UIKit.h>
#interface CommonViewController : UIViewController
#property (retain, nonatomic) IBOutlet UIView *topView;
#property (retain, nonatomic) IBOutlet UILabel *rightSideLabel;
#property (retain, nonatomic) IBOutlet UIButton *leftSideButton;
#property (retain, nonatomic) IBOutlet UIButton *middleButton;
#property (retain, nonatomic) IBOutlet UIImageView *topImageView;
#property (nonatomic, assign) CommonViewController *parentObject;
#end
CommonViewController.m
#import "CommonViewController.h"
#interface CommonViewController ()
#end
#implementation CommonViewController
#synthesize topView, rightSideLabel, leftSideButton, middleButton, topImageView, parentObject;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
topView = [[UIView alloc] initWithFrame:CGRectMake(0, -416, 320, 460)];
topImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
topImageView.image = [UIImage imageNamed:#"top_bar_bg4.png"];
middleButton = [UIButton buttonWithType:UIButtonTypeCustom];
[middleButton setFrame:CGRectMake(120, topView.frame.size.height-44, 80, 44)];
[middleButton setBackgroundImage:[UIImage imageNamed:#"slide_arrow_open.png"] forState:UIControlStateNormal];
leftSideButton = [UIButton buttonWithType:UIButtonTypeCustom];
[leftSideButton setFrame:CGRectMake(0, topView.frame.size.height-44, 80, 44)];
[leftSideButton setTitle:#"BACK" forState:UIControlStateNormal];
[leftSideButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
rightSideLabel = [[UILabel alloc] initWithFrame:CGRectMake(200, topView.frame.size.height-40, 110, 40)];
rightSideLabel.text = #"PRODUCTS";
rightSideLabel.textColor = [UIColor whiteColor];
rightSideLabel.backgroundColor = [UIColor clearColor];
[topView addSubview:topImageView];
[topView addSubview:middleButton];
[topView addSubview:leftSideButton];
[topView addSubview:rightSideLabel];
[self.view addSubview:topView];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
bViewController.h
#import <UIKit/UIKit.h>
#import "CommonViewController.h"
#interface bViewController : CommonViewController
#end
bViewController.m
#import "bViewController.h"
#interface bViewController ()
#end
#implementation bViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.view.backgroundColor = [UIColor lightGrayColor];
CommonViewController *newClass = [[CommonViewController alloc] init];
newClass.parentObject = self;
NSLog(#"text is %#", newClass.rightSideLabel.text);
newClass.rightSideLabel.text = #"NEW VALUE HERE";
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
What I want to do is keep common things in CommonViewController
Below is what I did...
In bViewController.m, I added below.
[[NSUserDefaults standardUserDefaults] setValue:#"New Value Here" forKey:#"notValue"];
[[NSUserDefaults standardUserDefaults] synchronize];
[[NSNotificationCenter defaultCenter] postNotificationName:#"ChangeRightSideLabel" object:self];
And in CommonViewController.m, viewDidLoad
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(receiveTestNotification:) name:#"ChangeRightSideLabel" object:nil];
- (void) receiveTestNotification:(NSNotification *) notification
{
// [notification name] should always be #"TestNotification"
// unless you use this method for observation of other notifications
// as well.
if ([[notification name] isEqualToString:#"ChangeRightSideLabel"]) {
NSLog (#"Successfully received the test notification!");
trightSideLabel = [[NSUserDefaults standardUserDefaults] valueForKey:#"notValue"];
rightSideLabel.text = trightSideLabel;
}
}
You have to respect MVC design Pattern approach. So instead of "newClass.rightSideLabel.text = #"NEW VALUE HERE";" You have to write :
in NewClass.h:
-#property(strong,nonatomic) stringText;
in NewClass.m:(ViewDidLoad Method)
-rightSideLabel.text=stringText;
in the current class:
-newClass.stringText= #"NEW Value HERE";
You need to make a string property for CommonViewController and assign the text to it.
And in CommonViewController's ViewDidLoad set that text to rightSideLabel.
This is firstPopoverViewController.h code:
#import <UIKit/UIKit.h>
#interface firstPopoverViewController : UIViewController
#end
This is my firstPopoverViewController.m code:
#import "firstPopoverViewController.h"
#interface firstPopoverViewController ()
#end
#implementation firstPopoverViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.contentSizeForViewInPopover = CGSizeMake(300, 290);
// Header label
UILabel *h1 = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 300, 85)];
h1.font = [UIFont fontWithName:#"myFont" size:22.0];
h1.textColor = [UIColor blackColor];
h1.textAlignment = NSTextAlignmentCenter;
h1.text = #"Heading";
h1.numberOfLines = 0;
h1.backgroundColor = [UIColor greenColor];
// Ok button BG View
UIView *buttonBG = [[UIView alloc] initWithFrame:CGRectMake(0, 300-75, 300, 75)];
buttonBG.backgroundColor = [UIColor greenColor];
// Ok button
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame = CGRectMake(300/2-130/2, 290-35-15, 130, 35);
button.backgroundColor = [UIColor whiteColor];
[button setTitle:#"OK" forState:UIControlStateNormal];
[button addTarget:self action:#selector(closePop) forControlEvents:UIControlEventTouchUpInside];
button.adjustsImageWhenHighlighted=YES;
// Adding views
[self.view addSubview:h1];
[self.view addSubview:buttonBG];
[self.view addSubview:button];
}
-(void)closePop {
}
#end
Then there's ViewController.h:
#import <UIKit/UIKit.h>
#import "firstPopoverViewController.h"
#interface ViewController : UIViewController
#property (strong, nonatomic) UIButton *popButton;
#property (strong, nonatomic) firstPopoverViewController *firstPopoverViewController;
#property (strong, nonatomic) UIPopoverController *firstPopover;
#end
And finally ViewController.m:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
/* ##### UIPopController stuff ##### */
UIImage *popButtonImage = [UIImage imageNamed:#"menu.png"];
_popButton = [UIButton buttonWithType:UIButtonTypeCustom];
_popButton.frame = CGRectMake(0, 0, 73, 66);
[_popButton addTarget:self action:#selector(openPop) forControlEvents:UIControlEventTouchUpInside];
_popButton.adjustsImageWhenHighlighted=NO;
[_popButton setImage:popButtonImage forState:UIControlStateNormal];
[self.view addSubview:_popButton];
}
-(void)openPop {
if (_firstPopoverViewController == nil) {
//Create the _firstPopoverViewController.
_firstPopoverViewController = [[firstPopoverViewController alloc] init];
}
if (_firstPopover == nil) {
_firstPopover = [[UIPopoverController alloc] initWithContentViewController:_firstPopoverViewController];
_firstPopover.popoverContentSize = CGSizeMake(300, 290);
[_firstPopover presentPopoverFromRect:CGRectMake(0,0, 73, 66) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionRight animated:YES];
NSLog(#"show");
} else {
NSLog(#"dismiss");
[_firstPopover dismissPopoverAnimated:YES];
_firstPopover = nil;
}
}
#end
It's pretty basic code that displays a button and when I click this button it shows popover. I want to close this popover using button that's inside firstPopoverViewControll.m file. There's a closePop{} method, what should I put inside it to close this popover? Thanks.
By the way I'm beginner as you can see, I researched stackoverflow and there are some solutions with delegates, which seems to be working for others, but didn't work for me, could you please show me a solution on my code that I posted? Thank you people very much.
There may be a simpler method that I'm not aware of, but the following method should work:
Use NSNotificationCenter to post a notification back to the ViewController containing the UIPopOverController to tell it to dismiss the popover.
First, in ViewController.m viewDidLoad add:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(closePop:) name:#"ClosePopOver" object:nil];
Then add the following method to ViewController.m:
- (void)closePop:(NSNotification *)notification {
[_firstPopover dismissPopoverAnimated:YES];
}
Then in irstPopoverViewController.m:
- (void)closePop {
[[NSNotificationCenter defaultCenter] postNotificationName:#"ClosePopOver" object:nil];
}
That should do the trick.
A delegate is the way to go. I do admit though that I was confused by them at first, but they are quite simple to setup.
In your firstPopoverController.h put this:
#import <UIKit/UIKit.h>
#protocol FirstPopoverDelegate
- (void) closedPopover;
#end
#interface firstPopoverViewController : UIViewController
#property (nonatomic, assign) id< FirstPopoverDelegate > delegate;
#end
Then in your .m of you popover,
-(void)closePop
{
[self.delegate closedPopover];
}
In your main UIViewController's .h:
#import <UIKit/UIKit.h>
#import "firstPopoverViewController.h"
#interface ViewController : UIViewController <FirstPopoverDelegate>
#property (strong, nonatomic) UIButton *popButton;
#property (strong, nonatomic) firstPopoverViewController *firstPopoverViewController;
#property (strong, nonatomic) UIPopoverController *firstPopover;
#end
Then in the .m, first register to listen of the delegate by adding this to your openPop method:
this is important and easy to forget.. nothing will happen if it is not set
_firstPopoverViewController.delegate = self;
Finally, in your .m add the delegate method:
- (void)closedPopover
{
//you can also pass data back in this function, just modify its parameters here and when you define it in the .h of the popover
[_firstPopoverViewController dismissPopoverAnimated:YES];
}