How to add a UIImageView to a UIView (not a UIViewController)? - objective-c

I created view-based application.
I have got a sampleGameViewContrioller.xib, which contains main View, and child View, which connected with class Behavior.
SampleViewController.xib:
View
View <- Behavior
In sampleViewContoller.m I create instance of the class Behavior:
Behavior *b = [[Behavior alloc] initilizeWithType:#"type" position:rect mapArray:arrMap];
Behavior.m:
-(id) initilizeWithType:(NSString *)type position:(CGRect) pos mapArray:(NSMutableArray *) mapArr {
self = [super initWithFrame:CGRectMake(0, 0, 1024, 570)];
if (self != nil) {
if ([type isEqualToString:#"type"]) {
arrMap = mapArr;
self.rectForDraw = pos;
self.file = [[NSString alloc]initWithString:#"girl.png"];
UIImageView *imgg = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"girl.png"]];
imgg.frame = rect;
[self addSubview:imgg];
timer = [NSTimer scheduledTimerWithTimeInterval:0.015 target:self selector:#selector(moving:) userInfo:nil repeats:YES];
}
}
return self;}
But it doesn't work. Image doesn't add to my View.
if I add imageView in -(void)drawRect:(CGRect) rect, it's working:
- (void)drawRect:(CGRect)rect {
self.img = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"girl.png"]];
self.img.frame = CGRectMake(100, 100, 100, 100);
[self addSubview:self.img]; }
But i should send parameters of drawing in class Behavior through constructor. How to add imageView without method drawRect, with my constructor?
sorry for my English :)

If u want to add an image view over simple UIView then just do [self.view addSubview:imageview]; If you are getting that Image from Behaviour class method then return UIImageView from that method and the add it to your view
Try this:
Behavior *b = [[Behavior alloc] init];
Then write one method in Behaviour class
-(UIImageView*) initilizeWithType:(NSString *)type position:(CGRect) pos mapArray:(NSMutableArray *) mapArr {
// Your Logic
return imgView; //UIImageView object
}
Then call this method in your viewcontroller as
UIImageView *imgView=[b initilizeWithType:#"YOUR STRING" position:YOUR RECT pos mapArray:YOUR ARRAY ];

imgg.frame = rect;
This line assigns your imageView frame to... nothing as far as I can see. Should this be pos or rectForDraw? When adding to your view in drawRect you are explicitly setting a real frame so this is probably where the difference lies.

Related

UIImageView subclass' image property

I have this in my config.h
#define SomeImage [UIImage imageNamed:#"some_pic.png"]
I have a class named Something subclass of UIImageView, imported config.h in Something.h
In Something.m initWithFrame method:
self.image = SomeImage;
The problem is when i create a new Something and add it to superview , I can't see anything.
I think I can handle the problem with initWithImage but couldn't figure out why my code isn't working.
Did you mentioned frame for your Something.m ?
It should work fine, example
Something *something = [[Something alloc] initWithFrame:CGRectMake(10, 10, 200, 200)];
[self.view addSubview:something];
Something.m
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
self.image = SomeImage;
return self;
}

UIPageViewController - view doesn't load

I want to load a UIView as the first page and some UIImageViews after that. The UIImageViews load fine, but the first UIView shows blank.
I designed the UIView in storyboard. It has some UIButtons and few other controls. What am I doing wrong?
I created the project from the default pageController template.
ModelController.m
- (id)init
{
self = [super init];
if (self) {
// Create the data model.
/*
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
_pageData = [[dateFormatter monthSymbols] copy];
*/
NSMutableArray *imageViews = [[NSMutableArray alloc] init];
FirstViewController *firstViewController = [[FirstViewController alloc] init];
firstViewController.view.frame = CGRectMake([UIScreen mainScreen].bounds.origin.x,[UIScreen mainScreen].bounds.origin.y,[[UIScreen mainScreen] bounds].size.height, [[UIScreen mainScreen] bounds].size.width);
[imageViews addObject:firstViewController];
for (int i=1; i<=19; i++) {
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[NSString stringWithFormat:#"picture%i.jpg", i]]];
imageView.frame = CGRectMake([UIScreen mainScreen].bounds.origin.x,[UIScreen mainScreen].bounds.origin.y,[[UIScreen mainScreen] bounds].size.height, [[UIScreen mainScreen] bounds].size.width);
[imageViews addObject:imageView];
}
_pageData = imageViews;
}
return self;
}
- (DataViewController *)viewControllerAtIndex:(NSUInteger)index storyboard:(UIStoryboard *)storyboard
{
// Return the data view controller for the given index.
if (([self.pageData count] == 0) || (index >= [self.pageData count])) {
return nil;
}
// Create a new view controller and pass suitable data.
DataViewController *dataViewController = [storyboard instantiateViewControllerWithIdentifier:#"DataViewController"];
dataViewController.dataObject = [self.pageData objectAtIndex:index];
if(index == 0)
{
//[dataViewController addChildViewController:[self.pageData objectAtIndex:index]];
FirstViewController *firstViewController = [self.pageData objectAtIndex:index];
[dataViewController.view addSubview:firstViewController.view];
}
else
{
UIImageView *imageView = [self.pageData objectAtIndex:index];
[dataViewController.view addSubview:imageView];
}
return dataViewController;
}
You haven't provided enough context to be certain, but it appears that what you need to load from the storyboard initially is an instance of FirstViewController, not an instance of UIView, so you'd need to do something like this instead of what you're currently doing:
FirstViewController *firstViewController = [self.storyboard instantiateInitialViewController];
// Note: If you need to adjust the frame of the controller's view, use the screen's
// application frame rather than its bounds.
controller.view.frame = [UIScreen mainScreen].applicationFrame;
Also, this seems like a bad idea, since you later fill the rest of the array with instances of UIImageView:
[imageViews addObject:firstViewController];
Why not add the controller's view to the array? Then you could eliminate the conditional logic in your viewControllerAtIndex:storyboard: method. Also, it's not clear why you're passing the storyboard in as an argument rather than using the built-in property, or for that matter, what class the code you posted belongs to, and what its relation is to the rest of your app. Maybe you could provide a little more info about that.
I got it to working by adding a xib file for FirstViewController. What ever I design in the xib shows up well. Previously I was designing it in the storyboard.

problem with UiImageView.image = nil

.h file
#interface AppViewController : UIViewController {
...
UIImageView *imageViewArray[3][5];// not using any #property for this
...
}
...
#define FOR(j,q) for (int j = 0; j < q; j++)
.m file
ViewDidLoad{
FOR(i,5){
FOR(j,3)
{
image_names[0] = [UIImage imageNamed:[NSString stringWithFormat:#"%d.png",j]];
imageViewArray[j][i] = [[UIImageView alloc] initWithImage: image_names[0]];
CGRect newFrame ;
newFrame = CGRectMake(60+(j*130), 110+(150*i),130,136);
imageViewArray[j][i].frame = newFrame;
[self.view addSubview:imageViewArray[j][i]];
}
}
}
//clear the previous images and call a method to add new
-(IBAction)Change{
FOR(i,5)
FOR(p,3)
imageViewArray[p][i].image = nil;
[self ImageSwitch];
}
-(void)ImageSwitch{
FOR(i,5){
FOR(j,3)
{
image_namesTmp[0] = [UIImage imageNamed:[NSString stringWithFormat:#"%d.png",j+3]];
imageViewArray[j][i] = [[UIImageView alloc] initWithImage: image_namesTmp[0]];
CGRect newFrame ;
newFrame = CGRectMake(60+(j*130), 110+(150*i),130,136);
imageViewArray[j][i].frame = newFrame;
[self.view addSubview:imageViewArray[j][i]];
}
}
}
when i press the button for the first time it works fine(old images get replaced with new ones),but if i do it second time
imageViewArray[p][i].image = nil;
this line wont work and all the previous images still remain there and new images are overlapping with the present ones
In the ImageSwitch method you are always creating new instances of UIImageView.
imageViewArray[j][i] = [[UIImageView alloc] initWithImage: image_namesTmp[0]];
At this point, there already is a reference to UIImageView stored in the variable. You are losing your reference to it and since you alloc/inited it, you will most probably also leak its memory. Moreover, you are adding new UIImageViews to the view hierarchy, but you are not removing the old ones.
Try something like this:
[imageViewArray[j][i] removeFromSuperview];
[imageViewArray[j][i] release];
imageViewArray[j][i] = [[UIImageView alloc] initWithImage: image_namesTmp[0]];
Second time you set your images you don't need to recreate the UIImageView objects. Your ImageSwitch method is better declared as,
-(void)ImageSwitch{
FOR(i,5){
FOR(j,3)
{
imageViewArray[j][i].image = [UIImage imageNamed:[NSString stringWithFormat:#"%d.png",j+3]];
}
}
}
Just changing the images will suffice and that's what you need to do.
You need an NSMutableArray of ImageViews. In your header declare the NSMutableArray:
NSMutableArray *_imageViewArray;
Then in your viewDidLoad method initialize the array and then populate it with your image views.
_imageViewArray = [[NSMutableArray alloc]init];
for (int i =0; i < imageNames; i++) {
UIImageView *tempImageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:[imageNames objectAtIndex:i];
[_imageViewArray addObject:tempImageView];
[tempImageView release];
}
So thats the image view array populated, you may do it a different way but thats up to you.
To switch the views over what I would do is like so...
[self.view removeAllSubviews]; // gets rid of all previous subviews.
[self.view addSubview:[_imageViewArray objectAtIndex:3]];// could be any number. generate a random number if you want.
Thats all you would need to do. If you wanted to know which image view was being displauyed the maybe declare an instance of UIImageView in your header called _currentImageView and then you can remove just that image view instead of all subviews.
Hope this helped.

location and size of a frame into different classes

I have a UIView class, to create the structure, I do:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
//creo la view
CGRectMake(0, 0, 100, 100); //I would just like the frame size
self.clipsToBounds = YES;
}
return self;
}
so I make the location and size of the frame.
I call this class in the main UIViewController
is there a way to just create the size of frame in the class, and in the UIViewController set the position?
MyClass *myClass1 = [[Item alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; //I would just like the frame position
[self.view addSubview:myClass1];
thanks a lot!
I think you are looking at something like initWithOrigin:.
- (id)initWithOrigin:(CGPoint)origin {
CGSize size = CGSizeMake(100,100);
CGRect frame;
frame.origin = origin;
frame.size = size;
return [self initWithFrame:frame];
}
Now you can use it as,
MyClass *myClass1 = [[MyClass alloc] initWithOrigin:CGPointMake(0,0)];
[self.view addSubview:myClass1];

Cocoa Touch: Creating and Adding Custom View

I create a custom view in cocoa touch that is superclassed by UIView and in my main controller I initialize it and then add it as a subview to the main view, but when I add it to the main view it calls my initializer method again and causes an infinite loop. Am I going about creating my custom view wrong?
Here is the mainView
- (void)loadView {
UIImage* tempImage = [UIImage imageNamed: #"image1.jpg"];
CustomImageContainer *testImage = [[CustomImageContainer alloc] initWithImage: tempImage andLabel: #"test image" onTop: true atX: 10 atY: 10];
[self.view addSubview: testImage];
}
and the CustomImageContainer
-(CustomImageContainer *) initWithImage: (UIImage *)imageToAdd andLabel: (NSString *)text onTop: (BOOL) top atX: (int) x_cord atY: (int) y_cord{
UIImageView *imageview_to_add = [[UIImageView alloc] initWithImage: imageToAdd];
imageview_to_add.frame = CGRectMake(0, 0, imageToAdd.size.width, imageToAdd.size.height);
UILabel *label_to_add = [[UILabel alloc] init];
label_to_add.text = text;
label_to_add.alpha = 50;
label_to_add.backgroundColor = [UIColor blackColor];
label_to_add.textColor = [UIColor whiteColor];
[self addSubview: imageview_to_add];
self.frame = CGRectMake(x_cord, y_cord, imageToAdd.size.width, imageToAdd.size.height);
if (top) {
label_to_add.frame = CGRectMake(0, 0, imageview_to_add.frame.size.width, imageview_to_add.frame.size.height);
//[self addSubview: label_to_add];
}
else {
label_to_add.frame = CGRectMake(0,.2 * imageview_to_add.frame.size.height, imageview_to_add.frame.size.width, imageview_to_add.frame.size.height);
}
[self addSubview: label_to_add];
[super init];
return self;
}
Why did you put the [super init] statement at the end of the initializer ? When subclassing, you usually put this statement at the start of method.
For UIView subclasses, the designated initializer when creating views in code is initWithFrame:, so you should call it before adding the label and the image. You can use the image to compute the frame needed by the custom view.
-(CustomImageContainer *) initWithImage: (UIImage *)imageToAdd andLabel: (NSString *)text onTop: (BOOL) top atX: (int) x_cord atY: (int) y_cord{
// The view will gets its frame to the size of the image
UIImageView *imageview_to_add = [[UIImageView alloc] initWithImage: imageToAdd];
// Call the designated initializer
CGRect frame = CGRectMake(x_cord, y_cord, imageToAdd.size.width, imageToAdd.size.height);
self = [super initWithFrame:frame];
[self addSubview: imageview_to_add];
UILabel *label_to_add = [[UILabel alloc] init];
label_to_add.text = text;
label_to_add.alpha = 50;
label_to_add.backgroundColor = [UIColor blackColor];
label_to_add.textColor = [UIColor whiteColor];
if (top) {
label_to_add.frame = CGRectMake(0, 0, imageview_to_add.frame.size.width, imageview_to_add.frame.size.height);
}
else {
label_to_add.frame = CGRectMake(0,.2 * imageview_to_add.frame.size.height, imageview_to_add.frame.size.width, imageview_to_add.frame.size.height);
}
[self addSubview: label_to_add];
return self;
}
If you still have an infinite loop, pause the debugger and search for the recurrent method pattern in the stack trace. This pattern will gives you where the code enters the infinite loop.