I'm trying to remotely adjust an object myImageView's alphato 0 of MyViewControllerclass From Another class Assistant(it's a NSObject subclass).
in Assistant.h
#import <Foundation/Foundation.h>
#class MyViewController;
#interface Assistant : NSObject {
MyViewController *myViewController;
UIImageView *button;
}
- (void)adjustAlpha:(id)sender;
#property (nonatomic, retain) UIImageView *button;
in Assistant.m
#import "MyViewController.h"
#implementation Assistant
#synthesize button;
- (id)init
{
self = [super init];
if (self)
{
myViewController = [[MyViewController alloc] init];
NSLog(#"alloced?: %#", myViewController ? #"YES" : #"NO");
}
return self;
}
- (void)adjustAlpha:(id)sender
{
NSLog(#"method called");
myViewController.myImageView.alpha = 0;
}
the method did get called, But myViewController.myImageView.alpha didn't change, why? where i need to fix? thank you for reading ^_^
Edit
This is MyViewController class:
MyViewController.h
#class Assistant;
#class MyAppAppDelegate;
#interface MyViewController : UIViewController <UITextViewDelegate, UIScrollViewDelegate>
{
UIImageView *myImageView;
Assistant *assistant;
}
#property (nonatomic, retain) UIImageView *myImageView;
MyViewController.m
#import "MyViewController.h"
#import "Assistant.h"
#implementation MyViewController
#synthesize myImageView;
- (void)viewDidLoad
{
[super viewDidLoad];
assistant = [[Assistant alloc] init];
myScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0,0,320,460);
[self.view addSubview: myScrollView];
myImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"weather.png"]];
myImageView.frame = CGRectMake(19, 54, 48, 48);
myImageView.userInteractionEnabled = YES;
[myScrollView addSubview:myImageView];
//this button uses to call adjustAlpha
assistant.button = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"button.png"]];
assistant.button.frame = CGRectMake(19, 126, 48, 48);
assistant.button.userInteractionEnabled = YES;
[myScrollView addSubview:assistant.button];
//here is how i call adjustAlpha:
assistant.adjustAlphaTap = [[UITapGestureRecognizer alloc] initWithTarget:assistant action:#selector(adjustAlpha:)];
[assistant.button addGestureRecognizer:assistant.adjustAlphaTap];
}
this question got complex and need some experiments, so just hanging there, will make it clear when i have time. for developer met the same problems: declare the object you need to access in a singleton class, can be easily accessed from any other classes, and Merry Christmas!
This will only work if myImageView is declared as a global scope variable (also called an iVar) in the .h file of your MyViewController class AND that it has a property of (nonatomic, retain) with a matching #synthesize in the .m.
If this sounds like what you're doing then can you please post the contents of your MyViewController h and m files.
If you have everything defined like Thomas described, can you check if the adjustAlpha method is called on the main thread?
Related
I'm trying to change UITextView.text from SecondViewController in ViewController. I can do it if it was NSString type in SecondViewController by doing:
SVC.string = #"test";
The problem is that:
messageBox.text doesn't change
SVC.messageBox.text returns (null)
One of the methods in ViewController.m:
SecondViewController *SVC = [[SecondViewController alloc]initWithNibName:#"SecondViewController" bundle:nil];
SVC.messageBox.text = #"changed";
NSLog(#"SVC: %#", SVC.messageBox.text); // result = (null)
[self presentViewController:SVC animated:YES completion:NULL];
SecondViewController.h:
#import <UIKit/UIKit.h>
#interface SecondViewController : UIViewController
#property (nonatomic) IBOutlet UITextView *messageBox;
#end
SecondViewController.m:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
self.messageBox.text = #"first";
}
How to get over with this?
Try this,
One of the methods in ViewController.m:
SecondViewController *SVC = [[SecondViewController alloc]initWithNibName:#"SecondViewController" bundle:nil];
SVC.strMessage= #"changed";
[self presentViewController:SVC animated:YES completion:NULL];
SecondViewController.h:
#import <UIKit/UIKit.h>
#interface SecondViewController : UIViewController
{
IBOutlet UITextView *messageBox;
}
#property (nonatomic) NSString *strMessage;
#end
SecondViewController.m:
#synthesize strMessage;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
self.messageBox.text = strMessage;
}
You can use delegates to do it as well.
Example:
Viewcontroller2nd.h
#protocol SecondViewControllerDelegate <NSObject>
#optional
-(void) changeLabel:(NSString*)str;
#end
#interface ViewController2nd : UIViewController{
IBOutlet UIButton *bttn;
id <SecondViewControllerDelegate> delegate;
}
#property (retain) id delegate;
#end
Viewcontrollerone.h
#interface ViewController : UIViewController <SecondViewControllerDelegate>
{
IBOutlet UILabel *lbl;
}
-(IBAction)passdata:(id)sender;
#end
Viewcontrollerone.m
-(void) changeLabel:(NSString*)str{
lbl.text = str;
}
More about delegates:http://developer.apple.com/library/ios/#documentation/uikit/reference/UIApplicationDelegate_Protocol/Reference/Reference.html
Hope this helps...
The problem with your code is your accessing the uicontrols which are not yet created in the memory.
You have to change the order of the execution of your statements like this...
SecondViewController *SVC = [[SecondViewController alloc]initWithNibName:#"SecondViewController" bundle:nil];
[self presentViewController:SVC animated:YES completion:NULL];
SVC.messageBox.text = #"changed";
NSLog(#"SVC: %#", SVC.messageBox.text);
Set #property (nonatomic) IBOutlet UITextView *messageBox; to #property (nonatomic, strong) IBOutlet UITextView *messageBox; and check if you have connected it with UItextView. And don't reset it in viewDidLoad. Another thing you can try is:
SecondViewController *SVC = [[SecondViewController alloc]initWithNibName:#"SecondViewController" bundle:nil];
[self presentViewController:SVC animated:YES completion:NULL];
SVC.messageBox.text = #"changed";
NSLog(#"SVC: %#", SVC.messageBox.text); // result = (null)
Along with what mentioned above.
just property-synthesize string andf just assign this string to yourTextView.text. For example see bellow..
#interface SecondViewController : UIViewController{
NSString *strMsgText;
}
#property(nonatomic, retain) NSString *strMsgText;
#end
#implementation SecondViewController
#synthesize strMsgText;
after that when you present SecondViewController at that time assign your value like bellow..
SecondViewController *SVC = [[SecondViewController alloc]initWithNibName:#"SecondViewController" bundle:nil];
SVC.strMsgText = #"changed";
[SVC.strMsgText retain];
[self presentViewController:SVC animated:YES completion:NULL];
and in viewDidLoad: method of SecondViewController just assign that string to messageBox(TextView), like bellow...
- (void)viewDidLoad
{
messageBox.text = strMsgText;
}
I am currently dynamically adding a UIImage to my UIScrollView object and everything is working as intended. I need to add extra functionality now (a UIActivityIndicator in the center of the image when it is loading from the internet, and a label underneath) so I thought why not create a custom View which has all of these laid out as I need them to be, and then just load it into the scrollView. I have encountered a problem though, when I add it to the scrollView, nothing shows up. Here is what I have:
NewsViewController.m:
imageScrollView.contentSize = CGSizeMake(320*numberOfPages, 303);
pageControl.numberOfPages = numberOfPages;
dispatch_queue_t imageDownload = dispatch_queue_create("imageDownload", NULL);
__block NSData *temp;
CustomImageView *customImageView = [[CustomImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 303)];
[imageScrollView addSubview:customImageView];
[[customImageView activityIndicator] startAnimating];
dispatch_async(imageDownload, ^{
temp = [[NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://www.wlfarm.org/wp-content/uploads/2012/05/farm.jpg"]]retain];
dispatch_async(dispatch_get_main_queue(), ^{
customImageView.imageView.image = [[UIImage alloc] initWithData:temp];
[[customImageView activityIndicator] stopAnimating];
[customImageView setNeedsDisplay];
customImageView.caption.text = #"HAHAHAHAHHAHA";
[imageScrollView setNeedsDisplay];
[temp release];
});
});
dispatch_release(imageDownload);
CustomImageView.h:
#import <UIKit/UIKit.h>
#interface CustomImageView : UIView
{
IBOutlet UIImageView *imageView;
IBOutlet UILabel *caption;
IBOutlet UIActivityIndicatorView *activityIndicator;
}
#property (nonatomic, retain) IBOutlet UIImageView *imageView;
#property (nonatomic, retain) IBOutlet UILabel *caption;
#property (nonatomic, retain) IBOutlet UIActivityIndicatorView *activityIndicator;
#end
CustomImageView.m
#import "CustomImageView.h"
#interface CustomImageView ()
#end
#implementation CustomImageView
#synthesize caption, imageView, activityIndicator;
- (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 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 (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
I am including a screenshot of my XIB file, and the program running on the simulator. The first picture shows nothing in the scrollView(the attempt made by using my custom class), and the second page of the scroll view is the attempt made by adding a UIImageView to the UIScrollView(which worked). Can anyone point out what I am doing wrong? Am I not allowed to load a custom view into a UIScrollView? Thanks for your help!
IB Screenshot - http://i.stack.imgur.com/gz9UL.png
iOS Simulator No Image with CustomView Screenshot - http://i.stack.imgur.com/zhswq.png
iOS Simulator Image with UIImageView Screenshot - http://i.stack.imgur.com/97vmU.png
It looks as though CustomImageView is a subclass on UIViewController, not UIImageView or UIView. You can't add a UIViewController as a subview like that. change it to subclass UIView and it should work.
To load a UIView from a .nib, you need to declare your IBOutlet properties as you would for a UIViewController. Define the correct custom class in IB and connect everything up, including the base view. Then override the following method inside your custom view class.
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// Initialization code.
//
[[NSBundle mainBundle] loadNibNamed:#"<NIB NAME HERE>" owner:self options:nil];
[self addSubview:self.view];
}
return self;
}
It seems you have cut and pasted methods from a UIViewController subclass into you UIView subclass. Start by deleting all the methods you've pasted in between #synthesize and #end . A UIView subclass requires different methods to to load from a .nib, so you need to override the method shown above instead and use the line of code
[[NSBundle mainBundle] loadNibNamed:#"<NIB NAME HERE>" owner:self options:nil];
to load the nib.
Further to your comment about connecting the base view, here is what I mean:
After creating your custom class and nib file, open the nib and highlight "Files Owner" on the left, then on the top right hand side, select the icon 3rd from the left, looks like an ID card or something. In the "Class" box, add the name of your custom class.
In your customClass, add an IBOutlet UIView property called baseView, and add a UIView that covers the view in IB at the root level, connect these two. Then add everything else on top of that
you code would now look something like this:
CustomImageView.h
#import <UIKit/UIKit.h>
#interface CustomImageView : UIView
{
IBOutlet UIView *baseView
IBOutlet UIImageView *imageView;
IBOutlet UILabel *caption;
IBOutlet UIActivityIndicatorView *activityIndicator;
}
#property (nonatomic, retain) IBOutlet UIView *baseView;
#property (nonatomic, retain) IBOutlet UIImageView *imageView;
#property (nonatomic, retain) IBOutlet UILabel *caption;
#property (nonatomic, retain) IBOutlet UIActivityIndicatorView *activityIndicator;
#end
CustomImageView.m
#import "CustomImageView.h"
#interface CustomImageView ()
#end
#implementation CustomImageView
#synthesize baseView, caption, imageView, activityIndicator;
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// Initialization code.
//
[[NSBundle mainBundle] loadNibNamed:#"<NIB NAME HERE>" owner:self options:nil];
[self addSubview:self.baseView];
}
return self;
}
#end
Provided you connect it all up in IB it should work fine, just remember to add the baseView
As mentioned earlier initWithNibName belongs to controllers.
As I think, you're going the wrong way.
you have a ViewController and want to add a customView, to load dynamically a image from URLData.
You have 2 Options:
Option 1: Do everything in IB:
In Interfacebuilder edit/(or add a new one) the ViewController's XIB File and add the views that you like. The file's owner is a UIViewController Class/Subclass. Do everything like you did before, except doing it in the view controller. In your App delegate initWithNibName your ViewController like so
self.viewController = [[testViewController alloc] initWithNibName:#"testViewController" bundle:nil];
If you want to, initialize your own view controller, which you like to push and push it in the stack.
What you're doing wrong: You are initializing a customImageView with a Frame, but the nib doesn't get loaded automatically. The Properties are there, but the nib isn't.
If you really want a stable thing choose
Option 2: Do everything programatically (It is easier, more understanding and lightweight):
From your implementation we do the following:
NewsViewController.m
Do like you did before!!!
CustomImageView.h:
#import <UIKit/UIKit.h>
#interface CustomImageView : UIView
{
UIImageView *imageView;
UILabel *caption;
UIActivityIndicatorView *activityIndicator;
}
#property (nonatomic, retain) UIImageView *imageView;
#property (nonatomic, retain) UILabel *caption;
#property (nonatomic, retain) UIActivityIndicatorView *activityIndicator;
#end
CustomImageView.m:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
caption = [[UILabel alloc] initWithFrame:CGRectMake(0, 250, 320, 50)];
[caption setBackgroundColor:[UIColor greenColor]];
imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 250)];
[imageView setBackgroundColor:[UIColor blueColor]];
activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
self.activityIndicator.frame = CGRectMake(320/2-25, 460/2-25, 50, 50);
[self.activityIndicator startAnimating];
[self addSubview:self.caption];
[self addSubview:self.imageView];
[self addSubview:self.activityIndicator];
}
return self;
}
Then do everything you did before.
That would do a better job
I have been stuck here.
I have a NSString in Appdelegate. And I have two views called firstview,second view.In first view I have a label and set text from stringvariable which is in Appdelegate .When I click on the button in first view,It goes to the secondview(added the second view to first view as a subview).In second view I have a back button.when I click the back button it is displaying the first view ( Here I am setting the value which is in the appdelegate.And then used this [self.view removeFromSuperview]).The Problem is first view is appearing but label value is not updating.Can any body tell me how to update the Labeltext.Kindly tell me.
Appdelegate.h
#import <UIKit/UIKit.h>
#class FirstView;
#interface AppDelegate : UIResponder <UIApplicationDelegate>
{
NSString *str1;
}
#property (nonatomic,retain) NSString *str1;
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) ViewController *viewController;
#end
Appdelegate.m
#import "AppDelegate.h"
#import "FirstView.h"
#implementation AppDelegate
#synthesize window = _window;
#synthesize viewController = _viewController;
#synthesize str1;
- (void)dealloc
{
[_window release];
[_viewController release];
[super dealloc];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
self.viewController = [[[FirsView alloc] initWithNibName:#"FirstView" bundle:nil] autorelease];
self.str1 = #"view1";
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
FirstView.h
#import <UIKit/UIKit.h>
#import "secondView.h"
#interface FirstView : UIViewController
{
IBOutlet UILabel *btn;
secondView *cont;
}
-(IBAction)gotoView2:(id)sender;
#end
FirstView.m
#import "FirstView.h"
-(IBAction)gotoView2:(id)sender
{
cont = [[secondView alloc] initWithNibName:#"secondView" bundle:nil];
[self.view addSubview:cont.view];
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
AppDelegate *del = [[UIApplication sharedApplication] delegate];
[btn setTitle:del.str1];
}
**SecondView.h**
#import <UIKit/UIKit.h>
#interface SecondView : UIViewController
{
}
-(IBAction)goBack:(id)sender;
#end
SecondView
#import "SecondView.h"
#import "AppDelegate.h"
#implementation SecondView
-(IBAction)gotoView1:(id)sender
{
AppDelegate *del = [[UIApplication sharedApplication] delegate];
[del setStr1:#"Home"];
[self.view removeFromSuperView];
}
There is a pattern how to do such things. You should define a protocol like this:
#protocol FirstViewDelegate <NSObject>
- (void)didDismissSecondView;
#end
Your first view should conform to this protocol:
#interface FirstView: UIViewController <FirstViewDelegate> {
...
in its implementation add function didDismissSecondView:
- (void) didDismissSecondView
{
AppDelegate *del = [[UIApplication sharedApplication] delegate];
[btn setTitle:del.str1];
}
Your second view has to have a property
#interface SecondView : UIViewController
{
id<FirstViewDeledate> delegate;
}
#property (nonatomic, retain) id<FirstViewDeledate> delegate;
When you show your second view from the first view set its delegate to self of first view
in your function:
-(IBAction)gotoView2:(id)sender
{
SecondView *aView = [[SecondView alloc] init] // or whatever
...//other initialization code
aView.delegate = self;
... // show it
}
and before you dismiss the second view:
-(IBAction)gotoView1:(id)sender
{
AppDelegate *del = [[UIApplication sharedApplication] delegate];
[del setStr1:#"Home"];
[self.delegate didDismissSecondView];
[self.view removeFromSuperView];
}
And you done.
A bit long, but works.
I am trying to get my hands on some iphone development. To try to better understand things, I'm going first without IB.
I managed to build a basic app that displays some text. No big deal, until I ran it through Instruments. It shows me some leaks and I cannot understand them.
Any help on this would be greatly appreciated.
MyAppDelegate.h
#interface MyAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
MyViewController *viewController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) MyViewController *viewController;
#end
MyAppDelegate.m
#implementation MyAppDelegate
#synthesize window;
#synthesize viewController;
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// NEXT LINE LEAKS
[window addSubview:viewController.view];
[window makeKeyAndVisible];
}
- (void)dealloc {
[viewController release];
[window release];
[super dealloc];
}
#end
MyViewController.h
#interface MyViewController : UIViewController {
UILabel *firstMessage;
}
MyViewController.m
-(void)loadView {
// Background
CGRect mainFrame = [[UIScreen mainScreen] applicationFrame];
UIView *contentView = [[UIView alloc] initWithFrame:mainFrame];
contentView.backgroundColor = [UIColor blackColor];
self.view = contentView;
[contentView release];
// Add UILabel
// NEXT LINE LEAKS
firstMessage = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 30)];
firstMessage.font = [UIFont fontWithName:#"Helvetica" size:16];
firstMessage.textColor = [UIColor whiteColor];
firstMessage.backgroundColor = [UIColor blackColor];
[self.view addSubview:firstMessage];
[firstMessage release];
}
-(void) viewDidLoad {
NSString * msg;
msg=[[NSString alloc] initWithFormat:#"stuff here"];
firstMessage.text=msg;
[msg release];
}
-(void)dealloc {
[firstMessage release];
[super dealloc];
}
Try using #property (nonatomic, retain) UILabel* firstMessage in your header, #synthesize firstMessage in your implementation and then release your firstMessage object in the dealloc method.
Try not to release your firstMessage in loadView. Only release it in your controller's dealloc method.
I'm new to iPhone programming, and I'm trying to make a simple program without a NIB. I have worked through some NIB tutorials, but I'd like to try some things programmatically.
My code loads without errors, makes the status bar black, and makes the background white. But, I don't think I'm loading my view with a label correctly after that. I presume I'm doing something just fundamentally wrong, so if you could point me in the right direction, I'd appreciate it. I think if I can get the label to show, I'll get some understanding. Here's my code:
//helloUAppDelegate.h
#import <UIKit/UIKit.h>
#import "LocalViewController.h"
#interface helloUAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
LocalViewController *localViewController;
}
#property (nonatomic, retain) UIWindow *window;
#property (nonatomic, retain) LocalViewController *localViewController;
#end
//helloUApDelegate.m
#import "helloUAppDelegate.h"
#implementation helloUAppDelegate
#synthesize window, localViewController;
- (void)applicationDidFinishLaunching:(UIApplication *)application {
application.statusBarStyle = UIStatusBarStyleBlackOpaque;
window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
if (!window) {
[self release];
return;
}
window.backgroundColor = [UIColor whiteColor];
localViewController = [[LocalViewController alloc] init];
[window addSubview:localViewController.view];
// Override point for customization after application launch
[window makeKeyAndVisible];
}
//LocalViewController.h
#import <UIKit/UIKit.h>
#interface LocalViewController : UIViewController {
UILabel *myLabel;
}
#property (nonatomic, retain) UILabel *myLabel;
#end
//LocalViewController.m
#import "LocalViewController.h"
#implementation LocalViewController
#synthesize myLabel;
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
self.myLabel = [[UILabel alloc] initWithFrame:CGRectMake(50, 100, 200, 100)];
self.myLabel.text = #"Lorem...";
self.myLabel.textColor = [UIColor redColor];
}
- (void)dealloc {
[super dealloc];
[myLabel release];
}
Add your label to your LocalViewController's view:
- (void)loadView {
[super loadView];
self.myLabel = [[UILabel alloc] initWithFrame:CGRectMake(50, 100, 200, 100)];
self.myLabel.text = #"Lorem...";
self.myLabel.textColor = [UIColor redColor];
[self addSubview:self.myLabel];
[self.myLabel release]; // since it's retained after being added to the view
}