I know this is just a fundamental question but still somewhere I am missing something, I am playing with passing data to a textView from another class. For this I have created two classes one with xib file (ViewController) and another without(secondVC).
What I am trying to do is that I have a textview in ViewController class and wanted to pass the data to this textView from secondVC. This is how I am doing.
//ViewController.h
#import <UIKit/UIKit.h>
#import "secondVC.h"
#interface ViewController : UIViewController{
IBOutlet UITextView *textView;
}
#property (nonatomic, retain) UITextView *textView;
- (IBAction)go:(id)sender;
#end
//ViewController.m
- (IBAction)go:(id)sender{
secondVC *sec = [[secondVC alloc] init];
[sec print];
}
//secondVC.h
#import <UIKit/UIKit.h>
#import "ViewController.h"
#interface secondVC : UIViewController
- (void)print;
#end
//secondVC.m
- (void)print{
NSString *printThis = #"This works";
ViewController *vc = [[ViewController alloc] init];
[vc.textView setText:printThis];
//vc.textView.text = printThis //Tried both
}
Any suggestions would be appreciated.
Thanks
you can do like this :
//ViewController.h
#import <UIKit/UIKit.h>
#import "secondVC.h"
#interface ViewController : UIViewController{
IBOutlet UITextView *textView;
}
#property (nonatomic, retain) UITextView *textView;
- (IBAction)go:(id)sender;
#end
//ViewController.m
- (IBAction)go:(id)sender{
secondVC *sec = [[secondVC alloc] init];
sec.viewController = self;
[sec print];
}
//secondVC.h
#import <UIKit/UIKit.h>
#import "ViewController.h"
#interface secondVC : UIViewController {
ViewController *viewController;
}
#property(nonatomic, retain)ViewController *viewController;
- (void)print;
#end
//secondVC.m
#synthesize viewController;
- (void)print{
NSString *printThis = #"This works";
self.viewController.textView.text = printThis ;
}
Try with protocol... if you want to send string from textView(child) to other ViewController(parent)
You need a delegate method that is fired from the SecondVC and handled in the first one (ViewController).
There are a few issues here:
You've got a ViewController creating a new secondVC and sending it a print message. That's okay, but the implementation of -print creates a different instance of ViewController and tries to set the text of it's textView property. That's clearly not what you want -- you should instead be sending the text back to the original instance of ViewController.
That second instance of ViewController very likely has its textView property set to nil since textView is an outlet, but you haven't loaded its view from the .xib.
It's really not nice for one view controller to mess with the views of another view controller. The secondVC should be giving the text to the original ViewController object, not trying to set the text of one of its views.
To facilitate communication from secondVC to ViewController, give secondVC a property to keep track of the original ViewController. The usual thing to do here is to define a delegate protocol for secondVC and implement that protocol in ViewController. When ViewController creates secondVC, it sets the delegate of secondVC to itself. That gives secondVC a pointer to its delegate (it shouldn't care whether its a ViewController or some other kind of object, as long as the delegate implements the right methods).
.h file:
#import <UIKit/UIKit.h>
#protocol StringDelegate <NSObject>
-(void)getArrayOfStrings:(NSMutableArray*)strArray;
#end
#interface WWSettings : UIViewController{
}
#property(nonatomic,assign)id<StringDelegate>delegate;
#end
.m file:
#import "WWSettings.h"
#implementation WWSettings
#synthesize delegate;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
-(void)blablablaFunction{
[delegate getArrayOfStrings:yourArray];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
#end
if you dont understand how it works .. ask ! i'll make my best to help you )
your secondVC
#import <UIKit/UIKit.h>
#import "WWSettings.h"
#interface secondVC : UIViewController<StringDelegate>{
WWSettings *obj;
}
#end
and .m file :
#import "secondVC.h"
#implementation secondVC
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
-(void)getArrayOfStrings:(NSMutableArray *)strArray{
// here you get your array !!! it's a delegate function made by you in child viewController;
}
- (void)viewDidLoad
{
obj = [[WWSettings alloc]init];
[obj setDelegate:self];
[super viewDidLoad];
// Do any additional setup after loading the view.
}
first VC .h file :
#import <UIKit/UIKit.h>
#protocol textViewChildDelegate <NSObject>
-(void)getStrings:(NSString*)string;
#end
#interface textViewChild : UIViewController<UITextViewDelegate>{
UITextView *textView;
}
#property(nonatomic,assign)id<textViewChildDelegate>delegate;
#end
.m file:
#import "textViewChild.h"
#implementation textViewChild
#synthesize delegate;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
-(void)myWorkingMethod{
// get string from textView
[delegate getStrings:textView.text];
}
- (void)viewDidLoad
{
textView = [[UITextView alloc]initWithFrame:CGRectMake(0, 240, 320, 240)];
[super viewDidLoad];
// Do any additional setup after loading the view.
}
Now go to secondVC .h:
#import <UIKit/UIKit.h>
#import "textViewChild.h"
#interface TextViewViewController : UIViewController<textViewChildDelegate>{
UITextView * myfirstTextView;
}
#end
and to .m file:
#import "TextViewViewController.h"
#implementation TextViewViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
-(void)getStrings:(NSString *)string{
myfirstTextView.text = string; // finally we get string from child view controller
}
- (void)viewDidUnload
{
myfirstTextView = [[UITextView alloc]init];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
Related
I have a little trouble with my delegate example. I created a very simple code to learn how delegates work. I know that my delegate not will be called but i can't figure out why?
So here is the complete code. Please tell me what i do wrong. It is really important for me to understand the error in this code.
First Viewcontroller: h.file
#import <UIKit/UIKit.h>
#protocol ViewControllerDelegate;
#interface ViewController : UIViewController
#property (nonatomic, retain) id<ViewControllerDelegate> delegate;
#end
#protocol ViewControllerDelegate <NSObject>
- (void)transfer:(ViewController *)data number:(NSUInteger)value;
#end
First Viewcontroller: m.file
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize delegate;
- (void)viewDidLoad
{
[super viewDidLoad];
if ([delegate respondsToSelector:#selector(transfer:number:)]){
[delegate transfer:self number:65];
NSLog(#"delegate called");
}
[delegate transfer:self number:65]; //Try to call without if-statement.
}
#end
SecondViewcontroller: h.file
#import <UIKit/UIKit.h>
#import "ViewController.h"
#interface SecondViewController : UIViewController <ViewControllerDelegate>
#end
SecondViewcontroller: m.file
#import "SecondViewController.h"
#interface SecondViewController ()
#end
#implementation SecondViewController
- (void)transfer:(ViewController *)data number:(NSUInteger)value
{
NSLog(#"received information from ViewController");
}
- (void)viewDidLoad
{
[super viewDidLoad];
ViewController *viewcontroller = [[ViewController alloc] init];
viewcontroller.delegate = self;
}
#end
In the storyboard i use two container views so both ViewControllers will shown.
Your current code is fine. The problem appears to be that you are never loading the view controllers view(s) so the viewDidLoad method isn't being called.
To test, push the viewcontroller, or just request viewcontroller.view.
I am completely new to this Objective-C programming. I was recently making a very simple app and I couldn't find why the app doesn't work when I am trying to define the UI items in the second controller view. I keep receiving this error message:
"2013-08-04 02:38:45.488 Cheerup[43957:c07] * Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key welcomeMsg.'
* First throw call stack:
(0x1c91012 0x10cee7e 0x1d19fb1 0xb7ae41 0xafc5f8 0xafc0e7 0xb26b58 0x230019 0x10e2663 0x1c8c45a 0x22eb1c 0xf37e7 0xf3dc8 0xf3ff8 0xf4232 0xffc25 0x2ff3a3 0xfcee3 0xfd167 0xfd1a7 0x4690a2 0x45ab99 0x45ac14 0x10e2705 0x162c0 0x16258 0xd7021 0xd757f 0xd66e8 0x45cef 0x45f02 0x23d4a 0x15698 0x1becdf9 0x1becad0 0x1c06bf5 0x1c06962 0x1c37bb6 0x1c36f44 0x1c36e1b 0x1beb7e3 0x1beb668 0x12ffc 0x282d 0x2755)
libc++abi.dylib: terminate called throwing an exception
(lldb) "
Is there some problems with Appdeligate?
followings are two ViewController of mine:
MenuViewController.h
#import <UIKit/UIKit.h>
#interface MenuViewController : UIViewController{
}
#property IBOutlet UIButton *Botton1;
#property IBOutlet UIButton *Botton2;
#end
MenuViewController.m
#import "MenuViewController.h"
#interface MenuViewController ()
#end
#implementation MenuViewController
- (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.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
AfterMenuViewController.h
#import <UIKit/UIKit.h>
#interface AfterMenuViewController : UIViewController{
IBOutlet UILabel *WelcomeMsg;
IBOutlet UIButton *Back;
}
#end
AfterMenuViewController.m
#import "AfterMenuViewController.h"
#interface AfterMenuViewController ()
#end
#implementation AfterMenuViewController
- (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.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Any thoughts?
THanks
Kamyar
Your error says welcomeMsg and your code says WelcomeMsg. Naming is case-sensitive. It looks like you may have renamed an outlet after connecting it. Try removing the connection and re-connecting it.
Note that by convention, instance variables and properties start with lower case letters, and class names start with upper case letters. So welcomeMsg is correct.
I think there is problem with IBOutlets. Try this
#import <UIKit/UIKit.h>
#interface AfterMenuViewController : UIViewController{
// comment this
// IBOutlet UILabel *WelcomeMsg;
// IBOutlet UIButton *Back;
}
#property (weak, nonatomic) IBOutlet UILabel *WelcomeMsg;
#property (weak, nonatomic) IBOutlet UIButton *Back;
#end
I am Following a tutorial at http://www.raywenderlich.com/14172/how-to-parse-html-on-ios .
Here is my detailviewcontroller.h file.
#import <UIKit/UIKit.h>
#end <-- //errors shows up here.
#interface DetailViewController : UIViewController
#property (strong, nonatomic) id detailItem;
#property (weak, nonatomic) IBOutlet UILabel *detailDescriptionLabel;
#end
This is my detailview.m file
#import "DetailViewController.h"
#interface DetailViewController ()
- (void)configureView;
#end
#implementation DetailViewController
#pragma mark - Managing the detail item
- (void)setDetailItem:(id)newDetailItem
{
if (_detailItem != newDetailItem) {
_detailItem = newDetailItem;
// Update the view.
[self configureView];
}
}
- (void)configureView
{
// Update the user interface for the detail item.
if (self.detailItem) {
self.detailDescriptionLabel.text = [self.detailItem description];
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self configureView];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = NSLocalizedString(#"Detail", #"Detail");
}
return self;
}
#end
As i referred above, the #end error message appears and wait to auto fix in red square, the i agree to do the auto fix. Then the xCode applies the #end code over there, as shown in the .h file. Then an other error appears as which is in the title " #end must appear in an objective-c context "
what should i do ?
Is xCode gone mad or what.
Whats wrong ?
In my case, somewhere along the line I missed a #end in one of the .h file. So all files that import that .h file is prompting this error. The funny thing is, I don't receive this error message on the one .h file that does miss the #end. So I guess you need to do some searching make sure you close all your #interface, #implementation or #protocol with #end. Hope that helps.
Just remove that first #end. It's completely wrong. You can only have #end after an #implementation, #interface, or #protocol declaration.
I read in this same site how to inset and UILabel (subclass UILabel and override the required methods). Before adding it to my app I decided to test it out in a standalone test app. Code is shown below.
Here's MyUILabel.h
#import <UIKit/UIKit.h>
#interface MyUILabel : UILabel
#end
Here's MyUILabel.m
#import "MyUILabel.h"
#import <QuartzCore/QuartzCore.h>
#implementation MyUILabel
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
// for border and rounding
-(void) drawRect:(CGRect)rect
{
self.layer.cornerRadius = 4.0;
self.layer.borderWidth = 2;
[super drawRect:rect];
}
// for inset
-(void) drawTextInRect:(CGRect)rect
{
UIEdgeInsets insets = {0, 5, 0, 5};
[super drawTextInRect: UIEdgeInsetsInsetRect(rect, insets)];
}
Here's my ViewController.h
#import <UIKit/UIKit.h>
#import "MyUILabel.h"
#interface ViewController : UIViewController
{
MyUILabel *myDisplay;
}
#property (strong, nonatomic) IBOutlet MyUILabel *myDisplay;
#end
Here's ViewController.m:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize myDisplay;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
myDisplay.text = #"Hello World!";
}
- (void)viewDidUnload
{
[self setMyDisplay:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
#end
None of the methods in MyUILabel.m (that Im overriding) get called.
Insights into why are greatly appreciated.
Regards,
Ramon.
Ok. I did some further digging and in Xcode there is a field visible when looking at the nib file. Its the 'Identity Inspector' (3rd icon from left). This needed to be changed from UILabel to MyUILabel.
Now it works!
I've got a simple "model" class like so (complete with constructor of course)
#implementation Widget
#synthesize name;
#synthesize color;
- (id) init
{
if (self = [super init])
{
self.name = #"Default Name";
self.color = #"brown";
}
return self;
}
#end
I've declared it as an internal member to my controller like so:
#import <UIKit/UIKit.h>
#import "Widget.h"
#interface testerViewController : UIViewController {
IBOutlet UITextField *stuffField;
Widget *widget;
}
#property (nonatomic, retain) UITextField *stuffField;
#property (nonatomic, retain) Widget *widget;
- (IBAction)buttonPressed:(id)sender;
#end
and... I'm trying to initialize it within my controller like so:
#import "testerViewController.h"
#implementation testerViewController
#synthesize stuffField;
#synthesize widget;
- (IBAction)buttonPressed:(id)sender
{
stuffField.text = widget.name;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
widget = [[Widget alloc] init];
}
return self;
}
but.. it doesn't seem to be initializing my object because my textfield comes up blank every time. Any clues?
Try to use
-(void) viewDidLoad{} method to initiliaze your data
in your interface class use #class Widget instead of #import "Widget.h"
and in your implementation class use #import "Widget.h"
and make sure you come into your buttonPressed handler!