How to call a UIView method in my UIViewController? - ios

I have a method to create a rectangle in my custom uiview and I want to call it in my UIViewController.I am trying to use UITapGestureRecognizer in my UIViewController and check if a point in the rectangle is called.
rectangle in my custom uiview ( myView.m )
- (CGRect) myRect
{
return CGRectMake(10, 10, self.bounds.size.height - 20, self.bounds.size.height - 20);
}
UITapGestureRecognizer method in my MyViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
[self.PlayDraw setNeedsDisplay];
}
- (IBAction)handleTap:(UITapGestureRecognizer *)sender {
CGPoint point = [sender locationInView:self.view];
if(CGRectContainsPoint([self.PlayDraw myRect],point)) {
NSLog(#"touched");
}
and I get an error for [self.PlayDraw myRect] that says
No visible #interface for 'MyViewController' declares the
selector 'myRect'
and here is my MyViewController.h
#interface MyViewController : UIViewController
{
}
- (IBAction)handleTap:(UITapGestureRecognizer *)sender;
#property (strong, nonatomic) IBOutlet myView *PlayDraw;
#end

In your myView.h file add:
- (CGRect) myRect;
You have to expose this method to other classes.

Related

When I animate the custom view, the height of the view changes

My xib of BetRecordAniChooserView :
My ViewController in simulator:
You can see the background view of the chooser-view height is reduce.
My code is below:
BetRecordAniChooserView.h:
#import <UIKit/UIKit.h>
typedef void(^ChooseBlock)(NSString *choosedStr);
#interface BetTRecordAniChooserView : UIView
#property (nonatomic, assign) UIViewController *owener;
#property (nonatomic, assign) BOOL isShow;
#property (nonatomic, copy) ChooseBlock block;
- (void)showSelf;
- (void)hideSelf;
#end
BetRecordAniChooserView.m:
#import "BetTRecordAniChooserView.h"
#interface BetTRecordAniChooserView ()
#property (weak, nonatomic) IBOutlet UIButton *all_button;
#property (weak, nonatomic) IBOutlet UIButton *check_pending_button;
#property (weak, nonatomic) IBOutlet UIButton *deposited_button;
#property (weak, nonatomic) IBOutlet UIButton *have_cancel_button;
#end
#implementation BetTRecordAniChooserView
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
// Drawing code
}
*/
- (void)awakeFromNib {
[super awakeFromNib];
self.frame = CGRectMake(0, 0, self.bounds.size.width, 100);
self.all_button.selected = YES;
}
#pragma mark - actions
- (IBAction)allAction:(UIButton *)sender {
self.block(sender.titleLabel.text);
}
- (IBAction)checkPendingAction:(UIButton *)sender {
self.block(sender.titleLabel.text);
}
- (IBAction)haveDepositeAction:(UIButton *)sender {
self.block(sender.titleLabel.text);
}
- (IBAction)haveCancelAction:(UIButton *)sender {
self.block(sender.titleLabel.text);
}
#pragma mark - methods
- (void)showSelf {
CGRect temp_frame = self.frame;
self.isShow = YES;
[UIView animateWithDuration:0.3 animations:^{
self.frame = CGRectMake(temp_frame.origin.x, temp_frame.origin.y + temp_frame.size.height, temp_frame.size.width, temp_frame.size.height);
}];
}
- (void)hideSelf {
CGRect temp_frame = self.frame;
self.isShow = NO;
[UIView animateWithDuration:0.3 animations:^{
self.frame = CGRectMake(temp_frame.origin.x, temp_frame.origin.y - temp_frame.size.height, temp_frame.size.width, temp_frame.size.height);
} completion:^(BOOL finished) {
}];
}
#end
In my ViewController.m:
#import "ViewController.h"
#import "BetTRecordAniChooserView.h"
#interface ViewController ()
{
BetTRecordAniChooserView *_chooser_view;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
_chooser_view = [[NSBundle mainBundle] loadNibNamed:#"BetTRecordAniChooserView" owner:self options:nil].firstObject;
//float width = self.view.bounds.size.width;
//float height = 100.f;
//_chooser_view.frame = CGRectMake(0, -height + 64, width, height);
_chooser_view.owener = self;
[self.view addSubview:_chooser_view];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)actionA:(UIButton *)sender {
if (_chooser_view.isShow) {
[_chooser_view hideSelf];
} else {
[_chooser_view showSelf];
}
}
#end
You can see in the BetRecordAniChooserView's awakeFromnNib method:
The frame height I set 100:
self.frame = CGRectMake(0, 0, self.bounds.size.width, 100);
But when I start my simulator it become 36(the gray color view under the buttons).
(lldb) po self.frame
(origin = (x = 0, y = 0), size = (width = 375, height = 36))
I found the reason:
At first I was use the trailing, leading, bottom, top of the gray back view to its superview, I get this issue.
And then I delete the Bottom Space Constraint, and add the height constraint to it.
Then I do not have the issue again, and I can drag out the height Constraint to the .m file too, convenience to change the height.
But I don't know if there is a method I do not use my set height constraint method, still use the trailing, leading, bottom, top constraints to get the requirement effect.

Custom UIButton's setIsSelected method not called

I have a custom class based on UIButton, and I have difficulties calling the custom setter method in this custom class. I will list the codes in these files:
CallMyMethod.h (subclass of UIButton)
CallMyMethod.m
CallOtherClassMethod.h (to call setter method in CallMyMethod)
CallOtherClassMethod.m
CallMyMethod.h
#interface CallMyMethod : UIButton
#property (nonatomic, setter=setIsSelected:) BOOL isSelected;
#property (nonatomic, retain) UIImageView *checkmarkImageView;
- (void)setIsSelected:(BOOL)aIsSelected; //this is unnecessary, I guess
#end
CallMyMethod.m
#implementation CallMyMethod
#synthesize isSelected = _isSelected;
#synthesize checkmarkImageView = _checkmarkImageView;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
[self loadView];
}
return self;
}
- (void) loadView
{
[self.checkmarkImageView setHidden:YES];
}
- (UIImageView *)checkmarkImageView
{
if (_checkmarkImageView == nil) {
UIImage *checkmarkImage = [UIImage imageNamed:#"checkmark.png"];
_checkmarkImageView = [[UIImageView alloc]initWithImage:checkmarkImage];
[_checkmarkImageView setFrame:CGRectMake(10, 10, 32, 32)];
[self addSubview:_checkmarkImageView];
}
return _checkmarkImageView;
}
- (void)setIsSelected:(BOOL)aIsSelected
{
_isSelected = aIsSelected;
[self.checkmarkImageView setHidden:!_isSelected];
[self addSubview:_checkmarkImageView];
}
#end
CallOtherClassMethod.h
#class CallMyMethod;
#interface CallOtherClassMethod : UIViewController
#property (nonatomic,retain) CallMyMethod *btnCMM;
#end
CallOtherClassMethod.m
#import "CallMyMethod.h"
#implementation CallOtherClassMethod
#synthesize btnCMM;
- (void)viewDidLoad
{
[super viewDidLoad];
self.btnCMM = [[CallMyMethod alloc]initWithFrame:CGRectMake(0, 30, 50, 70)];
//somewhere in my code I will add btnCMM to the view
[someView bringSubviewToFront: btnCMM];
[someView addSubview: btnCMM];
}
//somewhere where I pressed a button to trigger this method
- (IBAction) pressMe:(id)sender
{
NSLog(#"self.btnCMM %#", self.btnCMM); //returned as btnCMM is nil ?!
[self.btnCMM setIsSelected:YES];
}
#end
The issue lies in the program not able to run the codes in setIsSelected method, I have traced btnCMM to be nil in NSLog. I wonder why is this so, because when I call CallOtherClassMethod as a UIViewController, the viewDidLoad would have initialised my custom button. Am I doing something wrong here?
Why not override setSelected, which is a method on UIButton and then use button.selected = YES?
If you want to debug why your button becomes nil, implement dealloc in your UIButton subclass, put a breakpoint there, and see the stack trace to find the reason.

Set zoom for UIScrollView subclass

I am trying to subclass UIScrollView as "ImageScrollView". My class is pretty simple. It has an imageView as one of it's subviews that I want the class to zoom to.
ImageScrollView.h
#import <UIKit/UIKit.h>
#interface ImageScrollView : UIScrollView
#property (nonatomic, strong) UIImageView *imageView;
- (id)initWithFrame:(CGRect)frame andImage:(UIImage *)image;
#end
ImageScrollView.m
#import "ImageScrollView.h"
#interface ImageScrollView()
#property CGFloat scaleWidth;
#property CGFloat scaleHeight;
#end
#implementation ImageScrollView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
- (id)initWithFrame:(CGRect)frame andImage:(UIImage *)image
{
self = [super init];
if(self)
{
self.frame = frame;
self.imageView = [[UIImageView alloc]initWithImage:image];
[self addSubview:self.imageView];
self.contentSize = self.imageView.bounds.size;
self.scaleWidth = self.frame.size.width / image.size.width;
self.scaleHeight = self.frame.size.height / image.size.height;
CGFloat minScale = MIN(self.scaleWidth, self.scaleHeight);
self.maximumZoomScale = 1.0f;
self.minimumZoomScale = minScale;
[self setZoomScale:minScale];
[self zoomToRect:self.imageView.frame animated:NO];
}
return self;
}
#end
Adding the subclass as a subview of my viewcontroller works just fine except for the scrolling:
#import "ViewController.h"
#import "ImageScrollView.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
ImageScrollView *imageScrollView = [[ImageScrollView alloc]initWithFrame:self.view.bounds andImage:[UIImage imageNamed:#"1.jpg"]];
[self.view addSubview:imageScrollView];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
My first guess is that it has something to do with the delegate not implemented correctly for the subclass. Any suggestions?
Basics for zooming in a UIScrollView
Set scroll view delegate (making sure the class you set as delegate conforms to UIScrollViewDelegate. In your case this is something like self.delegate = self
Set minimumZoomScale or maximumZoomScale (or both)
Implement viewForZoomingInScrollView: to return view to zoom
Figured it out. I had to add the delegate declaration and remove the - (void)zoomToRect:(CGRect)rect animated:(BOOL)animated. Here's the answer in case anyone needs it:
ImageScrollView.h
#import <UIKit/UIKit.h>
#interface ImageScrollView : UIScrollView <UIScrollViewDelegate>
#property (nonatomic, strong) UIImageView *imageView;
- (id)initWithFrame:(CGRect)frame andImage:(UIImage *)image;
#end
ImageScrollView.m
#import "ImageScrollView.h"
#interface ImageScrollView()
#property CGFloat scaleWidth;
#property CGFloat scaleHeight;
#end
#implementation ImageScrollView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
- (id)initWithFrame:(CGRect)frame andImage:(UIImage *)image
{
self = [super init];
if(self)
{
self.frame = frame;
self.delegate = self;
self.imageView = [[UIImageView alloc]initWithImage:image];
[self addSubview:self.imageView];
self.contentSize = self.imageView.bounds.size;
self.scaleWidth = self.frame.size.width / image.size.width;
self.scaleHeight = self.frame.size.height / image.size.height;
CGFloat minScale = MIN(self.scaleWidth, self.scaleHeight);
self.maximumZoomScale = 1.0f;
self.minimumZoomScale = minScale;
[self setZoomScale:minScale];
}
return self;
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return self.imageView;
}

Get the current value of UISlider in drawRect: method

I'm trying to move a point drawn in a UIView based on the value of a UISlider. The code below is for a UIView (subview ?) with a custom class (WindowView) on a UIViewController.
WindowView.h
#import <UIKit/UIKit.h>
#interface WindowView : UIView
- (IBAction)sliderValue:(UISlider *)sender;
#property (weak, nonatomic) IBOutlet UILabel *windowLabel;
#end
WindowView.m
#import "WindowView.h"
#interface WindowView ()
{
float myVal; // I thought my solution was using an iVar but I think I am wrong
}
#end
#implementation WindowView
#synthesize windowLabel;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
- (void)sliderValue:(UISlider *)sender
{
myVal = sender.value;
windowLabel.text = [NSString stringWithFormat:#"%f", myVal];
}
- (void)drawRect:(CGRect)rect
{
// I need to get the current value of the slider in drawRect: and update the position of the circle as the slider moves
UIBezierPath *circle = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(myVal, myVal, 10, 10)];
[circle fill];
}
#end
OK, you need to store the slider value in an instance variable and then force the view to redraw.
WindowView.h:
#import <UIKit/UIKit.h>
#interface WindowView : UIView
{
float _sliderValue; // Current value of the slider
}
// This should be called sliderValueChanged
- (IBAction)sliderValue:(UISlider *)sender;
#property (weak, nonatomic) IBOutlet UILabel *windowLabel;
#end
WindowView.m (modified methods only):
// This should be called sliderValueChanged
- (void)sliderValue:(UISlider *)sender
{
_sliderValue = sender.value;
[self setNeedsDisplay]; // Force redraw
}
- (void)drawRect:(CGRect)rect
{
UIBezierPath *circle = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(_sliderValue, _sliderValue, 10, 10)];
[circle fill];
}
You probably want to initialise _sliderValue to something useful in the view's init method.
Also _sliderValue probably isn't the name you want to choose; perhaps something like _circleOffset or some such.

View Delegate Not Being Called

I'm building a graphing app, and I have a view and a view controller, which acts as a delegate for the view (to retrieve information). While I haven't started the actual drawing yet, I am currently trying to store values in a dictionary; however, I have certain NSLogs placed methodically across the view controller and I noticed that the delegate methods I call from the view don't get called at all. For example, I call my scaleForGraph function, but it does not execute. Being new to this, I'm not sure if there's something I'm missing. FYI: I have no errors, it compiles and executes. I've tried to slim the code down as much as possible. Thank you for your help!
Here's the .h for my view, where I define the protocol:
// GraphView.h
#import <UIKit/UIKit.h>
#class GraphView;
#protocol GraphViewDelegate <NSObject>
- (float)scaleForGraph:(GraphView *)requestor;
-(NSMutableDictionary*) valuesForGraph:(GraphView *)requestor withWidth:(float) width;
#end
#interface GraphView : UIView
#property (nonatomic) id <GraphViewDelegate> delegate;
#property (nonatomic) id expressionCopy;
#end
And here's the .m:
#import "GraphView.h"
#implementation GraphView
#synthesize expressionCopy = _expressionCopy;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
self.contentMode = UIViewContentModeRedraw;
}
return self;
}
- (void)awakeFromNib
{
self.contentMode = UIViewContentModeRedraw;
}
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
CGContextRef c = UIGraphicsGetCurrentContext();
CGRect screenBound = [[UIScreen mainScreen] bounds];
CGSize screenSize = screenBound.size;
CGFloat width = screenSize.width;
CGFloat height = screenSize.height;
float scale = [self.delegate scaleForGraph:self];
NSLog([NSString stringWithFormat:#"My Scale: %f",scale]); //always returns 0
NSMutableDictionary *graphValues = [self.delegate valuesForGraph:self withWidth:width];
}
#end
And here's my view controller .h:
#import <UIKit/UIKit.h>
#import "GraphView.h"
#interface GraphingViewController : UIViewController <GraphViewDelegate>
#property (weak, nonatomic) IBOutlet GraphView *graphView;
#property (strong, nonatomic) IBOutlet UIStepper *stepper;
- (IBAction) changedScale:(UIStepper *)stepper;
#property (nonatomic) int scale;
#property (nonatomic) id expressionCopy;
#end
And here's the .m for the controller:
#import "GraphingViewController.h"
#interface GraphingViewController ()
#end
#implementation GraphingViewController
#synthesize expressionCopy = _expressionCopy;
- (void)updateUI
{
self.stepper.value = self.scale;
[self.graphView setNeedsDisplay];
}
- (void)setScale:(int)scale
{
if (scale < 0) scale = 0;
if (scale > 100) scale = 100;
_scale = scale;
[self updateUI];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(IBAction)changedScale:(UIStepper *)stepper {
self.scale = stepper.value; //this function works fine, but is not delegate/does not get called by view
}
-(float) scaleForGraph:(GraphView *)requestor {
NSLog(#"HI"); //never gets here
}
-(NSMutableDictionary*) valuesForGraph:(GraphView *)requestor withWidth:(float) width {
NSLog(#"Hello2"); //never gets here
}
return xyVals;
}
#end
Nowhere in the code you've posted do you tell your GraphView that the GraphingViewController is it's delegate. So, you are sending a message to nil.
You'll want to do something like:
self.graphView.delegate = self;
In your GraphingViewController setup code.
Make your controller actual delegate of GraphView. You can do it in interface builder by Ctrl-dragging from GraphView to the object (orange circle in the bottom) and than choose "delegate"

Resources