Create UIImageView in object - objective-c

I am trying to create a UIImageView programmatically in a method of a object.
-(void) createApple
{
CGRect myImageRect = CGRectMake(100, 100, 64, 64);
image = [[UIImageView alloc] initWithFrame:myImageRect];
[image setImage:[UIImage imageNamed:#"Apple.png"]];
[self.view addSubview:image];
[image release];
}
when I use this code in the ViewController.m it works fine but when I use it in my Apple object I get an error:request for member 'view' in something not a structure or union.
What do I use instead of self.view???
Sorry if I'm repeating posts. I saw a similar question to this but wasn't sure if it was exactly the same situation.

If I got your question correctly you have an interface like this
#interface Apple: NSObject
#end
If you want to create an UIImageView using NSObject methods try this
//first declare a method of UIImageView type
#interface Apple: NSObject
{
}
-(UIImageView *)ImageView;
#end
now come in your Apple.m file
#implementation Apple
-(UIImageView *)ImageView
{
UIImageView *imgView = [UIImageView alloc]initWithFrame:CGRectMake(100, 100, 64, 64)];
imgView setImage:[UIImage imageNamed:#"Apple.png"];
return imgView;
}
#end
now call this method where you want to show your image, in your ViewController.m file you can call it like this- You just have to import your object class first.
#import "ViewController.h"
#import "Apple.h"
#implementation ViewController
-(Void)ViewDidLoad
{
Apple *appleObject = [Apple alloc]init];
UIImageView *imageViewOfViewController = [appleObject ImageView];
[self.view addSubView:imageViewOfViewController];
}
#end
I show you imageview method in viewDidLoad method you can call it any where like this.

The line causing the error would be:
[self.view addSubview:image];
If your Apple object does not extend UIViewController then there will be so self.view property on it, unless you have defined one yourself.
As to what to use instead, that is difficult to say without knowing specifically what you are trying to do.
However, assuming that you want your Apple class to display something on the screen, then probably what you want to do is update Apple so that it extends either UIViewController or (perhaps) UIView. Then in the first case you can use self.view, and in the second case you can just do [self addSubview: image];.

Because "view" is a property of UIViewController and your "apple object" doesn’t have one.

The problem is, you're not calling this method inside UIViewController. Personally I'd do it slightly other way:
- (UIView*) newAppleView
{
CGRect myImageRect = CGRectMake(100, 100, 64, 64);
UIImageView *imageView;
imageView = [[UIImageView alloc] initWithFrame:myImageRect];
[imageView setImage:[UIImage imageNamed:#"Apple.png"]];
return [imageView autorelease];
}
Assuming the newAppleView method is implemented in your UIViewController, you can easly add new apple:
[self.view addSubview:[self newAppleView]];

Related

No visible #interface for 'CameraTakePictureOverlay' for UIImagePickerControllerSourceTypePhotoLibrary

Having trouble using accessing the UIImagePickerControllerSourceTypePhotoLibrary button overlay here is what I got, the problem is in the selector (takeLib:).
using property for the imagePicker
#property (weak, nonatomic) UIImagePickerController *imagePicker;
- (UIButton *) createGetLibraryButton {
UIImage *imglibraryPicture = [StyleKit imageOfLibraryIcon];
CGRect bounds = [UIScreen mainScreen].bounds;
CGRect takePicRect = CGRectMake((bounds.size.width/2) - (imglibraryPicture.size.width/1),
bounds.size.height-imglibraryPicture.size.height/2-CAMERA_BOTTOM_BUTTON_PADDING,
imglibraryPicture.size.width/2,
imglibraryPicture.size.height/2);
UIButton *btnLibrary = [[UIButton alloc] initWithFrame:takePicRect];
//using selector(takeLib:)
[btnLibrary setBackgroundImage:imglibraryPicture forState:UIControlStateNormal];
[btnLibrary addTarget:self action:#selector (takeLib:) forControlEvents:UIControlEventTouchUpInside];
return btnLibrary;
}
the selector here is where the problem occurs
-(void) takeLib:(id)sender
{
self.imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
self.imagePicker.delegate = self;
[self presentViewController:self.imagePicker animated:YES completion:^{
}];
}
error stated:
No visible #interface for 'CameraTakePictureOverlay' declares the selector 'presentViewController:animated:completion:'
From what super class did you inherit CameraTakePictureOverlay?
Super class should be UIViewController. UIImagePickerController docs
Present the user interface. On iPhone or iPod touch, do this modally (full-screen) by calling the presentViewController:animated:completion: method of the currently active view controller, passing your configured image picker controller as the new view controller.

iOS - Implementation of MVC-Pattern without Interface Builder

I'm creating a little MVC-sample-project as an iPhone-application in XCode, which is built completely with code and therefore doesn't use Interface Builder. First I'd like to show you the code I have so far.
Controller
The controller instantiates the model and the view and also contains a function which demonstrates the independency between model and view:
ViewController.h
#import <UIKit/UIKit.h>
#import "MainView.h"
#import "ProjectModel.h"
#interface ViewController : UIViewController
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
{
ProjectModel *model;
MainView *myMainView;
}
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
model = [[ProjectModel alloc] init];
myMainView = [[MainView alloc] initWithFrame:CGRectMake(0, 0, 320, 468)];
[self.view addSubview:myMainView];
//test function to illustrate that view and model are independent
[self calculate];
}
- (void)calculate
{
int result = [model operationWithNumber:3 andAnotherNumber:5];
[myMainView showResult:result];
}
#end
Model
The class ProjectModel is responsible for the model of the project and is in this example for the sake of simplicity only responsible for summing up two numbers:
ProjectModel.h
#import <Foundation/Foundation.h>
#interface ProjectModel : NSObject
-(int)operationWithNumber:(int)number1 andAnotherNumber:(int)number2;
#end
ProjectModel.m
#import "ProjectModel.h"
#implementation ProjectModel
-(int)operationWithNumber:(int)number1 andAnotherNumber:(int)number2
{
return (number1 + number2);
}
#end
View
The view-class creates all the elements of the view and contains a function which displays the result of a calculation in a label.
MainView.h
#import <UIKit/UIKit.h>
#interface MainView : UIView
{
UILabel *lblResult;
}
- (void)showResult:(int)result;
#end
MainView.m
#import "MainView.h"
#implementation MainView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
UILabel *lblTitle = [[UILabel alloc] initWithFrame:CGRectMake(20, 20, 280, 50)];
lblTitle.text = #"This is my View";
[self addSubview:lblTitle];
lblResult = [[UILabel alloc] initWithFrame:CGRectMake(20, 200, 280, 50)];
lblResult.text = #"Result will be displayed here.";
[self addSubview:lblResult];
}
return self;
}
- (void)showResult:(int)result
{
lblResult.text = [NSString stringWithFormat:#"Resultat: %d", result];
}
#end
My Question:
I hope you understood the code so far. Based on the code above, I'd like to implement a button in the view-class which should calculate and display two numbers when the users clicks this button. Thus when the user clicks the button, the calculate-function in the ViewController should be called. I created a button with the following code in MainView.m:
UIButton *btnCalculate = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btnCalculate setFrame:CGRectMake(20, 90, 280, 50)];
[btnCalculate setTitle:#"Calculate" forState:UIControlStateNormal];
[btnCalculate addTarget:self action:#selector(calculate:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:btnCalculate];
The problem is this line in the code above:
[btnCalculate addTarget:self action:#selector(calculate:) forControlEvents:UIControlEventTouchUpInside];
how can I add a function from the controller as the action of the button. I know that the target should not be self, since the function should be called in the ViewController, but I have no idea how I could do that. Could anyone help me and tell me how I can solve this problem?
The only solution that I can see right now is that the complete GUI is created in the ViewController directly. But I don't think that this is a nice solution, since the main purpose of MVC is to avoid the mix of controller and view code in the same class.
Also I'm wondering whether this code generally conforms to the MVC-pattern propagated by Apple, since I'm pretty new to this design-pattern. I'd really appreciate a short feedback for this code.
Don't set the target in the view class. For MVC, the view should not explicitly know about the controller. The view class should have a public property to expose the button and then the controller can update the button to add the target.
Other than that it looks like you understand the point of MVC.
This line does confuse a bit [self.view addSubview:view]; as it appears to be trying to add the view as a subview of itself...
The MVC pattern is a nice thing, but I don't think it is necessary for a program like yours to have that degree of separation. Also the button can be in the view class since it is a part of that pattern along with calculate function.

Changing an image in MKMapKit MKAnnotation Subclass

I am having some problems with changing an image view inside of an MKAnnotationView subclass. I have a timer that updates the annotation position based on data about where a user was at a certain point. This works fine and the annotation position is updated correctly. I do this with the following code:
[_myAnnotation setCoordinate:point.position];
Below this, I also calculate whether the user was heading east or west. If the user is heading east, I call the setIsMovingRight:YES method on the MyAnnotation class, and do the opposite for when the user is heading west.
I have verified that the method is being called with the correct values at the correct times by using NSLog inside the method to print out whenever the value changes. However, it doesn't seem like the setIsMovingRight method has any effect on the visual appearance of the annotation. I try setting the background colour of the imageview to red whenever the method is called, but even this has no effect. I have tried calling setNeedsDisplay in various places with no success.
I can add and recreate an annotation view, but then the annotation flashes on and off whenever the position changes and it really does not look very good.
The following is the code for my custom annotation view, "MyAnnotation".
#interface MyAnnotation : MKAnnotationView <MKAnnotation>
{
UIImageView *_imageView;
BOOL _currentlyMovingRight;
}
#property (nonatomic) CLLocationCoordinate2D coordinate;
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *subtitle;
#property (nonatomic,retain) UIImage *image;
-(void)setIsMovingRight:(BOOL)movingRight;
#end
#implementation MyAnnotation
#synthesize coordinate, title, subtitle, image;
-(id)initWithAnnotation:(id<MKAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier];
if(self)
{
_currentlyMovingRight = NO;
_imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"right.png"]];
[self addSubview:_imageView];
}
return self;
}
-(void)setIsMovingRight:(BOOL)movingRight
{
_imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 30, 30)];
[_imageView setBackgroundColor:[UIColor redColor]]; // THIS LINE NEVER DOES ANYTHING.
if(movingRight && !_currentlyMovingRight)
{
NSLog(#"right now.");
[_imageView setImage:[UIImage imageNamed:#"right.png"]];
}
else if (!movingRight && _currentlyMovingRight)
{
NSLog(#"left now.");
[_imageView setImage:[UIImage imageNamed:#"left.png"]];
}
_currentlyMovingRight = movingRight;
[self addSubview:_imageView];
[self setNeedsDisplay];
}
I would appreciate any help or advice that anyone could give. Thanks!
I think that the annotation views use KVO to listen for changes. Have you tried changing the image property? Something like [self setImage:myNewImage]

How do I connect an array of buttons w/i singleton?

My appDelegate, in the method didFinishLaunchingWithOptions I load my view controller then create a singleton:
UIViewController *MainWinVC = [[p3VC alloc] init];
[[self window] setRootViewController:MainWinVC];
ansButSingleton *ansButs = [[ansButSingleton alloc] init];
ansButSingleton.h looks like this:
#import <Foundation/Foundation.h>
#interface ansButSingleton : NSObject {
// View objects:
UIButton *Ans1;
UIButton *Ans2;
UIButton *Ans3;
UIButton *Ans4;
UIButton *Ans5;
UIButton *Ans6;
UIButton *Ans7;
UIButton *Ans8;
// Other objects:
NSArray *ansButs;
}
#property (strong) UIButton *Ans1, *Ans2, *Ans3, *Ans4, *Ans5, *Ans6, *Ans7, *Ans8;
#property (strong) NSArray *ansButs;
+ (ansButSingleton *) ansButsName; // Declare class method
#end
and ansButSingleton.m like this:
#import "ansButSingleton.h"
#implementation ansButSingleton
static ansButSingleton *ansButsName;
#synthesize Ans1, Ans2, Ans3, Ans4, Ans5, Ans6, Ans7, Ans8;
#synthesize ansButs;
//////////////////// instantiate ////////////////////
+ (ansButSingleton *) ansButsName { // class method
#synchronized(self)
{
if (!ansButsName)
ansButsName = [[ansButSingleton alloc] init];
return ansButsName;
}
}
//////////////////// initialize ////////////////////
- (id)init { // class instance method
NSLog(#"Initializing answer buttons");
if (ansButsName) {
return ansButsName;
}
self = [super init];
if(self) {
// First initialze the individual buttons
self.Ans1 = [[UIButton alloc] init];
[Ans1 setTitle:#"" forState:UIControlStateNormal];
self.Ans2 = [[UIButton alloc] init];
[Ans2 setTitle:#"" forState:UIControlStateNormal];
self.Ans3 = [[UIButton alloc] init];
[Ans3 setTitle:#"" forState:UIControlStateNormal];
self.Ans4 = [[UIButton alloc] init];
[Ans4 setTitle:#"" forState:UIControlStateNormal];
self.Ans5 = [[UIButton alloc] init];
[Ans5 setTitle:#"" forState:UIControlStateNormal];
self.Ans6 = [[UIButton alloc] init];
[Ans6 setTitle:#"" forState:UIControlStateNormal];
self.Ans7 = [[UIButton alloc] init];
[Ans7 setTitle:#"" forState:UIControlStateNormal];
self.Ans8 = [[UIButton alloc] init];
[Ans8 setTitle:#"" forState:UIControlStateNormal];
// Make an array containing the objects: this is the objective-C way!
self.ansButs = [[NSArray alloc] initWithObjects: Ans1, Ans2, Ans3, Ans4, Ans5, Ans6, Ans7, Ans8, nil];
}
NSLog(#"Done initializing answer buttons");
return self;
}
#end
This builds and runs fine (it doesn't do much yet). The buttons are visible due to the successful loading of the nib. However, they are not active since I haven't connected them to the code (no IBActions).
Question: How do I connect buttons created this way to the buttons in the nib? If these were simple buttons (not an array of buttons) I would create a method and use IBAction as part of that method declaration. But this case seems a bit different. Or maybe not. If these were labels (which I also need to do later), my reading leads me to believe IBOutletCollection might work, but there is no IBActionCollection that I can see. Expert guidance needed! Thanks.
EDIT ... working with Rob to implement his ideas. My viewLoad method was copied and pasted from yours, but maybe there was something in it I needed to change?
#pragma mark - View lifecycle
- (void)loadView {
NSDictionary *externals = [NSDictionary dictionaryWithObject:[AnswerButtons answerButtons]
forKey:#"answerButtons"];
NSDictionary *nibOptions = [NSDictionary dictionaryWithObject:externals
forKey:UINibExternalObjects];
[self.nibBundle loadNibNamed:self.nibName owner:self options:nibOptions];
[[AnswerButtons answerButtons] buttonsDidLoad];
}
There are a number of ways you could do this. I'd do it by hooking up the singleton's connections in the nib. Here's how.
First, let's fix up the singleton class to match iOS programming conventions and provide the support for wiring up the button connections in the nib:
AnswerButtons.h
#import <Foundation/Foundation.h>
#interface AnswerButtons : NSObject
#property (strong, nonatomic) IBOutlet UIButton *button1, *button2, *button3, *button4, *button5, *button6, *button7, *button8;
#property (strong, nonatomic, readonly) NSArray *buttons;
+ (AnswerButtons *)answerButtons;
- (void)buttonsDidLoad;
#end
AnswerButtons.m
#import "AnswerButtons.h"
#implementation AnswerButtons
#synthesize button1 = _button1;
#synthesize button2 = _button2;
#synthesize button3 = _button3;
#synthesize button4 = _button4;
#synthesize button5 = _button5;
#synthesize button6 = _button6;
#synthesize button7 = _button7;
#synthesize button8 = _button8;
#synthesize buttons = _buttons;
+ (AnswerButtons *)answerButtons {
static AnswerButtons *singleton;
static dispatch_once_t once;
dispatch_once(&once, ^{
singleton = [[AnswerButtons alloc] init];
});
return singleton;
}
- (void)buttonsDidLoad {
_buttons = [[NSArray alloc] initWithObjects:_button1, _button2, _button3, _button4, _button5, _button6, _button7, _button8, nil];
}
#end
Note that we create the singleton in the class method the first time the singleton is requested. Don't do it in application:didFinishLaunchingWithOptions:.
Next, let's hook up the buttons in the nib:
Open the nib for the p3VC class. (You should consider changing this name to start with a capital letter and spell out ViewController or just Controller.)
Drag an “External Object” from the Object Library into the nib.
In the Identity Inspector, set the External Object's custom class to AnswerButtons.
In the Attributes Inspector, set its External Object Identifier to answerButtons.
Control-drag from the Answer Buttons object to each of the eight buttons, connecting the button to the appropriate outlet.
Finally, we need to provide the AnswerButtons singleton to the nib loader when we load the nib. Edit p3VC.m and give it a loadView method:
p3VC.m
- (void)loadView {
NSDictionary *externals = [NSDictionary dictionaryWithObject:[AnswerButtons answerButtons]
forKey:#"answerButtons"];
NSDictionary *nibOptions = [NSDictionary dictionaryWithObject:externals
forKey:UINibExternalObjects];
[self.nibBundle loadNibNamed:self.nibName owner:self options:nibOptions];
[[AnswerButtons answerButtons] buttonsDidLoad];
}
With this approach, you can also create IBAction methods in the AnswerButtons class and use the nib to connect the buttons to those actions.
Since UIButton inherits from UIControl you can use the method:
[yourButton1 addTarget:yourObject action:#selector(yourMethod) forControlEvents:UIControlEventTouchUpInside];
Hook that in the loop where the buttons are created and you are good to go. If you are adding the buttons from interface builder then you need to hook an IBOutlet for each. Example: In your view controller init:
self.Ans1 = [[UIButton alloc] init];
[Ans1 setTitle:#"" forState:UIControlStateNormal];
//set the action
[Ans1 addTarget:self action:#selector(yourMethod) forControlEvents:UIControlEventTouchUpInside];
Another way would be to create the IBAction method for each button and hook that method to the method in the singleton, which in my opinion is much more clear.
Example: in your view controller:
-(IBAction) button1Press:(id)sender{
[yourSingleton button1Press];
}
To connect the buttons to interface builder, you'd have to place "IBOutlet" before the UIButton in each one of your variable declarations.
IBOutlet UIButton * Ans1;
Then in interface builder, you can right click and drag from view controller onto the button and select the right button. Then if you wanted to have each button perform a method, you should declare an IBAction method in your .h file:
-(IBAction)doButtonStuff:(id)sender;
Then to hook up the act to each button in interface builder, go to interface builder and right click and drag from the button to view controller and select what method you want to associate it with. Typically using interface builder is quick and easy but if you want to do some extra behind the scenes stuff, you can use the code whitelion posted.
Also, just a side note, to use less code when setting up your buttons, you can do a for each loop.
for (UIButton * button in ansButs) {
self.button = [[UIButton alloc] init];
[button setTitle:#"" forState:UIControlStateNormal];
}
This is a lot less code!!! You'd have to declare the array before this code and include all of the buttons in it.

Calling SEL from parentViewController in iOS

I have a ViewController in which I create a Modal ViewController. I have a SEL value in my modal that I set when it is being instantiated from the parent.
setDateViewController.selectorName = #selector(myMethod:);
In my modal I am trying to call this SEL like:
[[self parentViewController] performSelector:self.selectorName withObject:selectedDate afterDelay:.5];
{selectedDate} is obviously a value from my modal.
I don't get any errors or stack, however, this SEL (method) on my parent is never being called. For some reason I think this should work, but something tells me I'm way off track.
Thanks.
I guess [self parentviewcontroller] is not returning anything.
Try UiviewController* v = [self parentviewcontroller]; and check if is nil. Most probably it should be nil. Else if its was pointing to another object of different class then it would have crashed. Please do one thing. YOu should set bot the object and the methd you need to call. IT will solve any issues if it has any.
setDateViewController.selectorDelegate = self;
setDateViewController.selectorName = #selector(myMethod:);
call like this from parent class. So you can dynamically specify the method and the object you want to call gives more flexibility.
and use,
[selectorDelegate performSelector:self.selectorName withObject:selectedDate afterDelay:.5];
this should solve any issues.
Perhaps you would consider added a delegate protocol to your modal that will allow it to call the method on the parent.
Quick (untested) example:
// MyController.h
#protocol MyControllerDelegate;
#interface MyController : UIViewController
{
id<MyControllerDelegate> delegate;
}
#end
#protocol MyControllerDelegate <NSObject>
- (void)methodToCall:(id)sender;
#end
// MyControler.m
#implementation MyController
- (void) loadView
{
[super loadView];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.frame = CGRectMake(20.0f, 20.0f, 50.0f, 30.0f);
[btn setTitle:#"blah" forState:UIControlStateNormal];
[btn addTarget:self.delegate
action:#selector(methodToCall:)
forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
}
#end
// ParentController.h
#interface ParentController : UIViewController<MyControllerDelegate>
{
}
#end
// ParentController.m
#implementation ParentController
- (void)methodToCall:(id)sender
{
NSLog(#"HERE");
}
#end
Just make sure when you are creating your modal controller you set it's delegate to self on the parent:
MyController *controller = [[MyController alloc] init];
controller.delegate = self;
[self presentModalViewController:controller animated:YES];