My idea is to add generated integer value to the name of UIImageView. Here is an example: I have three UIImageViews named imageView1, imageView2, imageView3. When a button is pressed I have there this simple code:
self.value = value + 1;
(and of course I have this "value" declared) Now I want add some code which says something like:
UIImage *img = [UIImage imageNamed:#"image.png"];
[imageView(value) setImage:img];
So this I want this part of code ...[imageView(value)... to use the value I defined above. How could I do this?
You can set a tag for your image views:
// set tag
[imageView1 setTag:1];
[imageView2 setTag:2];
//...
// get the image view with the tag
[(UIImageView *)[self.view viewWithTag:value] setImage:img];
//...
You could use a tag, or you can put the UIImageViews into an NSArray. Then you can do something like
[((UIImageView *)[imageViewArray objectAtIndex:self.value]) setImage:img];
Here I tried to did according to your requirement.
my ViewController Class
- (void)viewDidLoad
{
[super viewDidLoad];
ExtendedUIImageView *eimage=[[ExtendedUIImageView alloc]initExtendedUIImageViewWithFrame:CGRectMake(0, 0, 768, 1024)];
UIImage *img1=[UIImage imageNamed:#"mac.png"];
UIImage *img2=[UIImage imageNamed:#"images.jpeg"];
UIImage *img3=[UIImage imageNamed:#"mac.png"];
[eimage addUIImage:img1 ToExtendedImageViewWithRect:CGRectMake(100, 100, 100, 100) withTag:1];
[eimage addUIImage:img2 ToExtendedImageViewWithRect:CGRectMake(210, 100, 100, 100) withTag:2];
[eimage addUIImage:img3 ToExtendedImageViewWithRect:CGRectMake(320, 100, 100, 100) withTag:3];
[self.view addSubview:eimage];
}
- (IBAction)chageImage:(UIButton *)sender {
NSLog(#"#####");
UIImage *img2=[UIImage imageNamed:#"images.jpeg"];
[eimage replaceImage:img2 forTag:3];
}
I Extended the UIView Class and created new Class ExtendedImageView class
ExtendedImageView.h
#interface ExtendedUIImageView : UIView
-(id)initExtendedUIImageViewWithFrame:(CGRect)rect;
-(void)addUIImage:(UIImage *)img ToExtendedImageViewWithRect:(CGRect)rect withTag:(int)n;
-(void)replaceImage:(UIImage *)newImg forTag:(int)n;
#end
ExtendedImageView.m
#implementation ExtendedUIImageView
-(id)initExtendedUIImageViewWithFrame:(CGRect)rect{
if([super initWithFrame:rect]){
return self;
}
return nil;
}
-(void)addUIImage:(UIImage *)img ToExtendedImageViewWithRect:(CGRect)rect withTag:(int)n{
UIImageView *imgView=[[UIImageView alloc]initWithImage:img];
//[imgView setBackgroundColor:[UIColor grayColor]];
imgView.frame=rect;
[imgView setTag:n];
[self addSubview:imgView];
}
-(void)replaceImage:(UIImage *)newImg forTag:(int)n{
for(UIView * img in [self subviews]){
if([img isKindOfClass:[UIImageView class]]&&[img tag]==n){
((UIImageView *)img).image=newImg;
}
}
}
#end
Related
I have a custom cell in a UITableView using an xib file. I programatically created a UILabel with a height of 200 and a width of 50. When I do an NSLog in the customCell.m of the label's width and height, it gives me w: 50 and h: 200. But when I do an NSLog in mainViewController.m it gives me 0 for the height and width.
Not sure why it does that. I need to get the real height of the label in the mainViewController.m
Here's my code:
customCell.m
- (void)awakeFromNib
{
self.label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 50, 200)];
[self.label setText:#"This is a label"];
[self.myView addSubview:self.label];
NSLog(#"%f", self.label.frame.size.height); // Results: 200.0000
}
mainViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
customCell *cellVC = [[cutsomCell alloc] init];
NSLog(#"%f, %f", cellVC.label.frame.size.height); // Results: 0.0000
}
Isn't awakeFromNib supposed to get called the mainViewController.m at viewDidLoad if I use an xib file? If not, how do I call it in viewDidLoad?
awakeFromNib is an initializer called when you load from nib..ie you add a view and change its class to your custom class in storyboard/nib and this porcess will call awakeFromNib method..not programatically
When done programatically use init method for the purpose or a custom initializer
-(id)init
{
//class super init calls
//then method calls
self.label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 50, 200)];
[self.label setText:#"This is a label"];
[self.myView addSubview:self.label];
//return self
}
Example
- (id) init {
// Call superclass's initializer
self = [super init];
if(self) {
self.label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 50, 200)];
[self.label setText:#"This is a label"];
[self.myView addSubview:self.label];
}
return self;
}
I created a custom object (NSImageView) to display images and I use addSubview: self.view to add
I want to determine if the mouse click in it.
How do I do?
Thank you.
NSImage *Image = [NSImage imageNamed:#"oneimage.jpg"];
NSImageView *ImageView = [[NSImageView alloc] init];
[ImageView setImage:Image];
[self.window addSubview:ImageView];
[ImageView_IconToAdd setAcceptsTouchEvents:YES];
[ImageView_IconToAdd setWantsRestingTouches:YES];
-(void)mouseDragged:(NSEvent *)theEvent {
id clickedObject = [self hitTest:[theEvent locationInWindow]];
if ([clickedObject isKindOfClass:[NSImageView class]]) {
NSLog(#"Clicked an ImageView");
} else if ([clickedObject isKindOfClass:[NSView class]]) {
NSLog(#"Clicked a WebView");
}
}
But error:
No visible #interface for 'WindowImage' declares the selector 'hitTest:'
And can't get Object!
I am creating a game using Sprite Kit, want to add a text field over scene. Here is the code:
#interface MKMainMenuScene ()
//...
#property (nonatomic) NSTextField *field;
#end
#implementation MKMainMenuScene
- (void)didMoveToView:(SKView *)view
{
[super didMoveToView:view];
[self.view addSubview:_field];
}
- (id)initWithSize:(CGSize)size
{
if (self == [super initWithSize:size])
{
//...
_field = [[NSTextField alloc] initWithFrame:
NSMakeRect(self.frame.size.width / 2, self.frame.size.height / 2 + 20,
100, 40)];
[_field setBackgroundColor:[NSColor whiteColor]];
[_field setStringValue:#"Enter smth"];
}
return self;
}
But text field doesn't appear, it is under the scene. Does someone know what is the problem and how to solve it?
Got it working.
Must set necessary views as Layer-Backed Views. Tried doing this in the Nib, didn't work for me. So I did it in code.
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
/* Insert Label. FOR TESTING, may remove */
NSTextField *label = [[NSTextField alloc] initWithFrame:NSMakeRect(50, 50, 300, 300)];
[label setStringValue:#"Hello All"];
[label setTextColor:[NSColor whiteColor]];
[label setBackgroundColor:[NSColor redColor]];
[label setFont:[NSFont fontWithName:#"Helvetica" size:20]];
[[self.window contentView] addSubview:label];
/* SET LAYER BACK VIEW
* This is the one line code to make it work.
*/
[self.window.contentView setWantsLayer:YES];
}
UPDATE:
The above code will cause a freeze or a problem on either a SCNView or SKView. To fix this, don't set the UI as a subview, but as a sibling to SKView. And then set the UI as Layer-Backed by setWantsLayer.
Window
-> Content NSView
-> SKView/SCNView
-> NSTextField <-- Layer-Backed
Code:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
/* Insert Label. FOR TESTING, may remove */
NSTextField *label = [[NSTextField alloc] initWithFrame:NSMakeRect(50, 50, 300, 300)];
// . . . .
[[self.window contentView] addSubview:label];
/* UPDATE */
[label setWantsLayer:YES];
}
Hope this helps someone else who's following my steps.
Try this one:
- (void)didMoveToView:(SKView *)view
{
[super didMoveToView:view];
[view addSubview:_field];
}
In my TestApp, I created a class "Carousel" which should let me create a swipe menu with a UIPageControl in an easy way (by simply creating an instance of the class Carousel).
Carousel is a subclass of UIView
At init, it creates an UIView, containing UIScrollView, UIPageControl
I can add further UIViews to the scroll view
I don't know if this is the proper way to do it, but my example worked quite well in my TestApp. Swiping between pages works perfectly and the display of the current page in the UIPageControl is correct.
If there were not one single problem: The UIPageControl sometimes reacts to clicks/taps (I only tested in Simulator so far!), sometimes it doesn't. Let's say most of the time it doesn't. I couldn't find out yet when it does, for me it's just random...
As you can see below, I added
[pageControl addTarget:self action:#selector(pageChange:) forControlEvents:UIControlEventValueChanged];
to my code. I thought this would do the proper handling of taps? But unfortunately, pageChange doesn't get always called (so the value of the UIPageControl doesn't change every time I click).
I would appreciate any input on this because I couldn't find any solution on this yet.
This is what I have so far:
Carousel.h
#import <UIKit/UIKit.h>
#interface Carousel : UIView {
UIScrollView *scrollView;
UIPageControl *pageControl;
BOOL pageControlBeingUsed;
}
- (void)addView:(UIView *)view;
- (void)setTotalPages:(NSUInteger)pages;
- (void)setCurrentPage:(NSUInteger)current;
- (void)createPageControlAt:(CGRect)cg;
- (void)createScrollViewAt:(CGRect)cg;
#end
Carousel.m
#import "Carousel.h"
#implementation Carousel
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// Create a scroll view
scrollView = [[UIScrollView alloc] init];
[self addSubview:scrollView];
scrollView.delegate = (id) self;
// Init Page Control
pageControl = [[UIPageControl alloc] init];
[pageControl addTarget:self action:#selector(pageChange:) forControlEvents:UIControlEventValueChanged];
[self addSubview:pageControl];
}
return self;
}
- (IBAction)pageChange:(id)sender {
CGRect frame = scrollView.frame;
frame.origin.x = frame.size.width * pageControl.currentPage;
frame.origin.y = 0;
[scrollView scrollRectToVisible:frame animated:TRUE];
NSLog(#"%i", pageControl.currentPage);
}
- (void)addView:(UIView *)view {
[scrollView addSubview:view];
}
- (void)createPageControlAt:(CGRect)cg {
pageControl.frame = cg;
}
- (void)setTotalPages:(NSUInteger)pages {
pageControl.numberOfPages = pages;
}
- (void)setCurrentPage:(NSUInteger)current {
pageControl.currentPage = current;
}
- (void)createScrollViewAt:(CGRect)cg {
[scrollView setPagingEnabled:TRUE];
scrollView.frame = cg;
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width*pageControl.numberOfPages, scrollView.frame.size.height);
[scrollView setShowsHorizontalScrollIndicator:FALSE];
[scrollView setShowsVerticalScrollIndicator:FALSE];
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
float frac = scrollView.contentOffset.x / scrollView.frame.size.width;
NSUInteger page = lround(frac);
pageControl.currentPage = page;
}
#end
ViewController.m (somewhere in viewDidLoad)
Carousel *carousel = [[Carousel alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
for (int i=0; i<5; i++) {
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(i * 320, 0, 320, 420)];
UIColor *color;
if(i%3==0) color = [UIColor blueColor];
else if(i%3==1) color = [UIColor redColor];
else color = [UIColor purpleColor];
view.backgroundColor = color;
[carousel addView:view];
view = nil;
}
[carousel setTotalPages:5];
[carousel setCurrentPage:0];
[carousel createPageControlAt:CGRectMake(0,420,320,40)];
[carousel createScrollViewAt:CGRectMake(0,0,320,420)];
Your code is correct. Most likely the frame of your pageControl is pretty small, so theres not a lot of area to look for touch events. You would need to increase the size of the height of pageControl in order to make sure taps are recognized all of the time.
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.