Changing image in different view - objective-c

I am attempting to change the character image in the game that I am creating but I am having some issues. I have a view controller where I will have all of the characters as their own buttons, and by selecting a button it should change the character image in the GameViewController
change.h
- (IBAction)charOne:(id)sender;
change.m
- (IBAction)charOne:(id)sender
{
GameViewController *changeView = [GameViewController game];
UIImageView *Romo = [GameView changeView];
[ChangeView setImage:[UIImage imageNamed:#"testOne.png"]];
NSLog(#"Test");
}
GameViewController.m
{
IBOutlet UIImageView *changeView;
}
#property (strong, nonatomic) IBOutlet UIImageView *changeView;
This code isn't working for me, I do not receive an error message but nothing is changed after the image is selected.
On the GameViewController the UIImage name that I am attempting to change the image for is named Romo.
Any help will be appreciated

try :
[Romo setImage:[UIImage imageNamed:#"testOne.png"]];
instead of :
[ChangeView setImage:[UIImage imageNamed:#"testOne.png"]];
You're calling the setImage method on a class rather than an instance of a class. Since Romo is the instance of UIImageView you want to affect (which is a reference pointer to the UIImageView on your game view controller), that should be the instance you affect.
Also, bad practice to name instances starting with a capital letter -- they turn out looking like classes.

Related

didSelectRowAtIndexPath, pushViewController and a little lable

I have a table controller in which I use didSelectRowAtIndexPath to navigate from the pushed cell to another view. In it I initialize new view controller and push some data in it. After that I do pushViewController.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
ServicesModel *service = [services objectAtIndex:indexPath.row];
ServiceViewController *serviceViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"ServiceView"];
serviceViewController.serviceModel = service;
NSLog(#"Set model %#", service.title);
// Pass the selected object to the new view controller.
[self.serviceController pushViewController:serviceViewController animated:YES];
}
In my ServiceViewController I have a label serviceTitle and ServiceModel property for selected service
#property (weak, nonatomic) IBOutlet UILabel *serviceTitle;
#property (strong, nonatomic) ServiceModel *serviceModel;
Using viewDidLoad I'm trying to change text of the label
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
NSLog(#"viewDidLoad %#", self.serviceModel.title);
self.serviceTitle.text = self.serviceModel.title;
}
Also I'm trying to access model in viewDidAppear
- (void) viewDidAppear:(BOOL)animated
{
NSLog(#"viewDidAppear %#", self.serviceModel.title);
}
but when view opens, label is empty. Why? What am I doing wrong? The most strange is the log:
(-[ServiceViewController viewDidLoad]) (ServiceViewController.m:43) viewDidLoad (null)
(-[ServicesTableViewController tableView:didSelectRowAtIndexPath:]) (ServicesTableViewController.m:127) Set model Google.com
(-[ServiceViewController viewDidAppear:]) (ServiceViewController.m:36) viewDidAppear (null)
It shows that viewDidLoad fires before I assign the model property. And in viewDidAppear model property is still null. How it can be?
You have two problems. The first one, as 0x7fffffff mentioned, is that you're instantiating your controller incorrectly (it should be initWithNibName:bundle: if made in a xib, and like 0x7fffffff said if in a storyboard).
Second, you can't access the label in serviceViewController from didSelectRowAtIndexPath, because its view has not been loaded yet. So, instead of setting the label in didSelectRowAtIndexPath, you should have a string property in serviceViewController, and give it the value service.text. Then in viewDidLoad, you can populate your label with that string.
Is the label missing altogether, or do you see it and it just didn't receive updated text? If the label is missing, then it's probably a problem in how you're creating the view controller. If for example, you're using storyboards, you should be accessing the view controller like this:
ServiceViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"SomeStoryBoardID"];
Instead of this:
ServiceViewController *serviceViewController = [[ServiceViewController alloc] init];
If however, you can see the label, but it just hasn't updated it's text, the first thing you should to is examine the connections inspector in Interface Builder, and verify that the IBOutlet for the label is properly linked.

Objective-C: Adding UIButtons programmatically from another class

I'm having trouble connecting the dots between code and .xib files.
If I want to add a series of UIButtons programmatically to my view controller, how would I go about doing this from a separate class?
For instance, if I have MainViewController.m, which is set as the root view controller in Xcode, how can I add a UIButton to that view controller from SecondViewController.m? Is this even possible?
I would essentially like to place all of my "user interface" code in a separate class.
Thanks
To do this, create a UIButton *myButton programmatically and then call [mainViewController addSubview:myButton];. This may mean you need to store a MainViewController * property in your SecondViewController class.
Important methods and properties for a UIButton instance (essentially, just take a look at the documentation, but here's a minimal set of stuff to get you started):
+[UIButton buttonWithType:buttonType] - Make sure if you're doing anything remotely custom to use UIButtonTypeCustom here (it doesn't give you any default background images or otherwise to have to nil out)
setFrame: - Position the button relative to its container and set the size, for usability reasons the width and height should be at least 44 pixels (as mentioned here).
setTitle:forState: - UIControlStateNormal will act as the default properties for other states too, so you may only need to set the text here
setBackgroundImage:forState: - use UIControlStateNormal and UIControlStateHighlighted/UIControlStateSelected primarily, UIControlStateDisabled if you wish to show it grayed out or inaccessible at any point.
setImage:forState: - Use for an icon next to the button text (like an arrow pointing down for Save or up for Load, etc)
setEnabled:, setHidden:, setSelected: - Transition between different button states. setHighlighted: happens automatically when you tap the button.
addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside - TouchUpInside is almost always what you want for a simple button press, I'm using a method named buttonClicked: here to handle my button press.
Oh, and if you use [[UIButton alloc] initWith...] don't forget to [myButton release] once it's added to the mainViewController :)
use this
#import "MainViewController.h"
#interface SecondViewController
{
MainViewController *mainView;
}
#property(nonatomic, retain) MainViewController *mainView;
-(void)addButtons;
In your implementation
#synthesize mainView;
-(void)addButtons
{
UIButton *add = [UIButton alloc] init];
//do necessary stuff on button here
[self.mainView addSubview:add];
[add release];
}
In your MainViewcontroller.m
#import "SecondViewController.h"
-(void)viewDidLoad
{
[self superViewDidLoad];
SecondViewController *second = [SecondViewController alloc] init];
second.mainView = self;
[second addButton];
[second release];
}

Fetching reference to superview from UITextField?

I have created three UIImageViews. I then added a UITextField to each image as a subview.
When the user clicks on the text field I want to capture which UIImageView ths text field belongs to. I am trying the following code :
-(void)textFieldDidBeginEditing : (UITextField *)textField {
textField = retainedObject;
MyPicture *capture = nil;
for (UIImageView *oneView in retainedObject.superview) {
if ([oneView isMemberOfClass:[myPicture class]])
capture = (UIImageView *)oneView;
}
However I get an error that UIView may not respond to count by enumeration. It looks like the superview of the textfield is UIView rather than UIImageView perhaps ? Can anybody help solve this ?
Thanks,
Martin
A UIView's superView is assumed to be a UIView. However, you can still cast it as a UIImageView, and call UIImageView methods on it, but just make sure it will always be a UIImageView without exception, as otherwise it will crash.
Source: My own applications ;)

Subclassing UIButton but can't access my properties

I've created a sub class of UIButton:
//
// DetailButton.h
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface MyDetailButton : UIButton {
NSObject *annotation;
}
#property (nonatomic, retain) NSObject *annotation;
#end
//
// DetailButton.m
//
#import "MyDetailButton.h"
#implementation MyDetailButton
#synthesize annotation;
#end
I figured that I can then create this object and set the annotation object by doing the following:
MyDetailButton* rightButton = [MyDetailButton buttonWithType:UIButtonTypeDetailDisclosure];
rightButton.annotation = localAnnotation;
localAnnotation is an NSObject but it is really an MKAnnotation. I can't see why this doesn't work but at runtime I get this error:
2010-05-27 10:37:29.214 DonorMapProto1[5241:207] *** -[UIButton annotation]: unrecognized selector sent to instance 0x445a190
2010-05-27 10:37:29.215 DonorMapProto1[5241:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[UIButton annotation]: unrecognized selector sent to instance 0x445a190'
'
I can't see why it's even looking at UIButton because I've subclassed that so it should be looking at the MyDetailButton class to set that annotation property. Have I missed something really obvious. It feels like it :)
Thanks in advance for any help you can provide
Ross
UIButton is a class cluster, which implies that Apple's implementation of buttonWithType: probably looks something like this:
+(id)buttonWithType:(UIButtonType)t {
switch (t) {
case UIButtonTypeDetailDisclosure:
return [[[PrivateDetailDisclosureButtonClass alloc] init] autorelease];
case ...
}
}
So when you call [MyDetailButton buttonWithType:UIButtonTypeDetailDisclosure]; you don't get an instance of MyDetailButton, you get an instance of PrivateDetailDisclosureButtonClass (or whatever Apple actually calls it).
Note, however, that you can get buttonWithType to instantiate a subclass if you call it with UIButtonTypeCustom (At least in the simulator running v3.0):
// LGButton is a straightforward subclass of UIButton
LGButton *testBtn = [LGButton buttonWithType:UIButtonTypeCustom];
LGButton *testBtn2 = [LGButton buttonWithType:UIButtonTypeDetailDisclosure];
NSLog(#"testBtn: %#, testBtn2: %#", [testBtn class], [testBtn2 class]);
// Output: testBtn: LGButton, testBtn2: UIButton
I made the same attempt as original poster but it seems that subclassing UIButton to do something like this is hard.
What I did, which is a hack - but works for me now, is add a UITextField as subview of the UIButton. The UITextField has no frame and is hidden, but I can freely store text strings in the textfield's text property. Which is what I wanted to do...
UITextField* tf = [[UITextField alloc] init];
tf.text = #"the text that I wanna store";
tf.hidden = YES;
tf.tag = TAGOFBUTTONSUBTEXTFIELD;
[previouslyCreatedButton addSubview:tf];
[tf release];
I defined TAGOFBUTTONSUBTEXTFIELD as 99 somewhere. Global. It's ugly but...
Then later, to get that text string use something like this:
+(NSString*)getStoredStringFromButton:(UIButton*)button {
UITextField* tf = (UITextField*)[button viewWithTag:TAGOFBUTTONSUBTEXTFIELD];
return tf.text;
}
So this assumes that no one else tries to add a subview with tag 99 to the button.
Lol :-)
That exception is because the actual button that you are trying to get the annotation from is not of class MyDetailButton, it is a UIButton. Verify that you set the class in IB for that particular button. Select the button in IB and press ⌘4 to see its identity, change the Class Identity to MyDetailButton.
Just making a subclass isn't enough; the subclass does not take the place of its superclass. The same way not all UIControls, not all UIViews, not all UIResponders, and not all NSObjects have the behavior of UIButton, not all UIButtons have the behavior of your custom subclass.
What you need is an instance of your subclass. What you have is an instance of UIButton.
The solution is to make that instance an instance of your subclass instead. If you created the button in Interface Builder, select the button and press ⌘6, then change the instance's Custom Class there. If you're creating the button in code, send your alloc message to your custom subclass, not directly to UIButton.

Append text with UITextField text

I am running Objective-C/Cocoa in Shell in Windows, not on Mac OS X.
I want to append a string with an existing string in a text field when I click a button. I've created a button in a window, but I don't know how to append a string when I click that button.
How can I append a string to a text field when that button is clicked?
This is a pretty empty question and will probably get deleted quickly. However, to attempt to answer it in some way:
If you want to display something when you click a button then you'll need a UIButton (already added you have said) and let's say a UILabel. You can find a UILabel in the same window you discovered the button. Add it to the view, somewhere just below the button.
You then want to find the .h file that corresponds to the .xib file (if you set something up by default in XCode it will have been created for you). Let's call it MyViewController.h although it will have a different name in your app.
In that .h file, you want to create an IBAction (so that you can detect the button click in code) and an IBOutlet (so you can update the text on the label).
The code should end up looking something like this:
//
// MyViewController.h
#import <UIKit/UIKit.h>
#interface MyViewController : UIViewController {
UILabel *label;
}
#property (nonatomic, retain) IBOutlet UILabel *label;
- (IBAction)buttonClick;
#end
Then, go back to the .xib file where you created your button. Select "File's Owner", open up the "Identity inspector" under the "Tools" menu and make sure the class is set to the same name as the class whose .h file we were just editing.
Now we need to connect the button and the label. Click on the button and bring up the "connections inspector" from the "Tools" menu again. Click in the circle next to "touch up inside" and drag it to the "File's owner". Select the "buttonClick" method that pops up in a window for you. Now select the File's owner. Click in the circle next to the word "label" and drag it to the label on your iPhone screen. This has now connected up the label and the button to the code you wrote before.
Finally, save the .xib file and open up the MyViewController.m file (or whatever it is called in your app). Add the following to it:
//
// MyViewController.m
#import "MyViewController.h" // Swap this name for the name of your .h file
#implementation MyViewController
#synthesize label;
-(IBAction)buttonClick {
label.text = #"Hello World!"
}
- (void)dealloc {
[label release];
[super dealloc];
}
#end
Spend some time looking at various tutorials etc and you'll quickly get up to speed.
You didn't specify whether you're using UILabel (Cocoa Touch) or NSTextField (Cocoa). For the latter, get the field's stringValue, send that object a stringByAppendingString: message with the string you want to append, and pass the result to the field's setStringValue: method.
Short answer: create an IBAction method in a controller class and set the IBAction as the target of your button.
Long answer: Get a book and learn the details of Cocoa. Cocoa is difficult to get started with, but once you've made the initial investment you'll be able to quickly create apps. I'd recommend Cocoa Programming for Mac OS X by Aaron Hillegass. It's desktop orientated rather than iPhone, but that shouldn't put you off.
There are also loads of great web resource to learn Cocoa. Cocoa Dev Central and the Apple developer site are great places to start.
import <UIKit/UiKit.h>
#interface MyViewController : UIViewController {
    UIButton *btnToAppend;
UITextField *textfield;
}
- (IBAction)buttonClick:(id)sender;
#end
import "MyViewController.h"
#implementation MyViewController
-(void)init{
btnToAppend = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btbToAppend.frame = CGRectMake(10, 10, 100, 30);
[btnToAppend setText:#"Append Text" forState:UIControlStateNormal];
[btnToAppend addTarget:self action:#select(buttonClick:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubView:btnToAppend];
textfield = [[UITextField alloc] initWithFrame:CGRectMake(10, 200, 300, 50)];
textfield.borderStyle = UITextBorderStyleRoundedRect;
[self.view addSubView:textfield];
}
-(IBAction)buttonClick:(id)sender {
NSString *string = [textfield.text stringByAppendingString:#"Welcome "];
    textfield.text = string;
}
- (void)dealloc {
    [super dealloc];
}
#end
Output will be like :
Welcome Welcome Welcome ...