How to init a UIView - iphone

In my main viewController, I have this:
// .h
#import "YNSlidingMenu.h"
#interface YNAddNoteViewController : UIViewController
#property (nonatomic, strong) YNSlidingMenu *slidingMenu;
#end
// .m
- (void)setUpSlidingMenu{
_slidingMenu = [[YNSlidingMenu alloc]init];
[self.view addSubview:_slidingMenu];
}
In YNSlidingMenu.m, I have this:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self configureView];
}
return self;
}
- (id)init{
self = [super init];
if (self) {
NSLog(#"init");
}
return self;
}
- (void)configureView{
NSLog(#"configureView");
self.rect = CGRectMake(0, 0, [[UIScreen mainScreen] bounds].size.width, 40);
}
YNSlidingMenu will get its frame for itself based on its contents, so I don't want to init it on my viewController with initWithFrame.
What do I need to do? NSLog(#"init"); doesn't get called. How can I initialize my custom view without setting the frame from my viewController?

Move [self configureView] out of your initWithFrame: method and into your init method as your calling init when you initialize your view. At least that's what your sample code looks like.

I don't think it can get its frame base on its content, unless of cause you're using auto layout.
A proper approach is that you init you view with CGRectZero. Then set the frame latter when you are ready.
Or you can adopting auto layout.

Related

UIPopOverScreen troubles

Recently I have taken interest in making a popover screen. In my Navigation bar I made this button and when I click on it it should make a popover screen appear.
So I started searching for a usefull tutorial and yet I found mostly tutorials made with interface builder, which is not what I want. So I started experimenting on my own.
This is my result:
First I set the necessary properties in the MainVC.h
Also mind the
#import <UIKit/UIKit.h>
#import "ThePopOverVC.h"
#interface PopoverPrototypeViewController : UIViewController <UIPopoverControllerDelegate>
{
ThePopOverVC *popover;
UIPopoverController *popoverController;
UIButton *popoverButton;
}
#property (nonatomic,retain) ThePopOverVC *popover;
#property (nonatomic,retain) UIPopoverController *popoverController;
#property (nonatomic,retain) UIButton *popoverButton;
- (void)popoverActivation;
#end
Then I set up my view in the MainVC.m
It prepares the view for the popoverscreen when pressing a button.
#import "PopoverPrototypeViewController.h"
#implementation PopoverPrototypeViewController
#synthesize popover;
#synthesize popoverController;
#synthesize popoverButton;
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)loadView
{
[super loadView];
self.view.backgroundColor = [UIColor blueColor];
popover = [[ThePopOverVC alloc] init];
popoverController = [[UIPopoverController alloc] initWithContentViewController:popover];
popoverController.popoverContentSize = CGSizeMake(300, 300);
popoverController.delegate = self;
self.popoverButton = [[UIButton alloc] initWithFrame:CGRectMake(100, 100, 400, 100)];
self.popoverButton.backgroundColor = [UIColor lightGrayColor];
[self.popoverButton setTitle:#"Click me!" forState:UIControlStateNormal];
[self.popoverButton addTarget:self action:#selector(popoverActivation) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.popoverButton];
}
- (void)popoverActivation
{
if ([self.popoverController isPopoverVisible]) {
[self.popoverController dismissPopoverAnimated:YES];
} else {
UIBarButtonItem *settingsBarButton = [[UIBarButtonItem alloc] initWithCustomView:self.popoverButton];
[self.popoverController presentPopoverFromBarButtonItem:settingsBarButton permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}
}
- (BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController
{
return YES;
}
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
{
NSLog(#"something");
}
Ok, the MainVC should be setup, now it's time to show the popoverContentViewController.
For my experiment I just want it to be an empty view with just a different backgroundColor.
So the popoverVC.h is empty:
#import <UIKit/UIKit.h>
#interface ThePopOverVC : UIViewController
#end
My popoverVC.m is equally empty except for the backgroundColor change:
#import "ThePopOverVC.h"
#implementation ThePopOverVC
- (void)loadView
{
[super loadView];
self.view.backgroundColor = [UIColor yellowColor];
}
You would say this shouldn't be too hard. But yet I'm experiencing problems loading the project.
I'm getting the following warning: warning: Unable to restore previously selected frame.
Well here comes the question:
What have I overlooked? What have I done wrong and how can I make this simple prototype work?
//---EDIT---//
OK, I'm a bloody idiot for overlooking this one.
[super loadView];
The super loadView wasn't called and gave me this simple problem.
I edited the code so it works properly now.
Use this as a tutorial on how to make UIPopOverScreens if you will (or whatever).
Ref: http://www.raywenderlich.com/1056/ipad-for-iphone-developers-101-uipopovercontroller-tutorial
[super loadView];
Was missing from ThePopOverVC.m
Pretty silly to overlook.. but yeah, it works now.

Very Simple Custom UIView, drawRect not getting called

I have this super simple example, and I'm not sure why it is not working. drawRect Never gets called. I just want a square to draw and be red. What am I doing wrong?
//Controller.h
#import <Foundation/Foundation.h>
#class CustomView;
#interface Controller : NSObject
#property (nonatomic, retain) CustomView *cv;
#end
//Controller.m
#import "Controller.h"
#import "CustomView.h"
#implementation Controller
#synthesize cv;
- (void) awakeFromNib {
NSLog(#"awakeFromNib called");
CGRect theFrame = CGRectMake(20, 20, 100, 100);
cv = [[CustomView alloc] initWithFrame:theFrame];
UIWindow *theWindow = [[UIApplication sharedApplication] keyWindow];
[theWindow addSubview:cv];
[cv setNeedsDisplay];
}
#end
//CustomView.h
#import <UIKit/UIKit.h>
#interface CustomView : UIView
#end
//CustomView.m
#import "CustomView.h"
#implementation CustomView
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
NSLog(#"initWithFrame called");
}
return self;
}
- (void)drawRect:(CGRect)rect {
NSLog(#"drawRect called");
self.backgroundColor = [UIColor redColor];
}
#end
You aren't drawing anything in your drawRect. You are just setting a property on the view. If you have overridden drawRect, nothing will be drawn - try calling [super drawRect:rect] (after setting your background colour) or simply draw the square yourself using:
[[UIColor redColor] set];
[[UIBezierPath bezierPathWithRect:self.bounds] fill];
EDIT:
I see your drawRect is not even being called. I'm not sure of your nib structure, but try adding cv as a subview to self.view in your controller rather than adding it to the window. Also, note that you are not retaining cv (use self.cv = rather than cv =) but this shouldn't be an issue since your view will retain it.
Rather than doing a forward reference to your CustomView class in your Controller implementation:
#class CustomView;
Trying importing the class header file:
#import "CustomView.h"
Because you require access to the API you have defined when you call:
cv = [[CustomView alloc] initWithFrame:theFrame];
A forward reference tells the compiler that there will be an implementation for the class you are using at compile time and it is best used in header files. In implementation files, I find it best to import the header.

InitWithFrame not executed if view is a property

I have GraphicView class that inherits from UIView. Its initWithFrame method is:
#implementation GraphicsView
- (id)initWithFrame:(CGRect)frameRect
{
self = [super initWithFrame:frameRect];
// Create a ball 2D object in the upper left corner of the screen
// heading down and right
ball = [[Object2D alloc] init];
ball.position = [[Point2D alloc] initWithX:0.0 Y:0.0];
ball.vector = [[Vector2D alloc] initWithX:5.0 Y:4.0];
// Start a timer that will call the tick method of this class
// 30 times per second
timer = [NSTimer scheduledTimerWithTimeInterval:(1.0/30.0)
target:self
selector:#selector(tick)
userInfo:nil
repeats:YES];
return self;
}
Using Interface Builder I've added a UIView (class = GraphicView) to ViewController.xib. And I've added GraphicView as a property:
#interface VoiceTest01ViewController : UIViewController {
IBOutlet GraphicsView *graphView;
}
#property (nonatomic, retain) IBOutlet GraphicsView *graphView;
- (IBAction)btnStartClicked:(id)sender;
- (IBAction)btnDrawTriangleClicked:(id)sender;
#end
But with this code doesn't work, I need to call [graphView initWithFrame:graphView.frame] to make it works.
- (void)viewDidLoad {
[super viewDidLoad];
isListening = NO;
aleatoryValue = 10.0f;
// Esto es necesario para inicializar la vista
[graphView initWithFrame:graphView.frame];
}
Am I doing well? Is there a better way to do that?
I don't know why initWitFrame is not called if I add GraphicView as a property.
initWithFrame is not called when loading from a NIB, it's initWithCoder instead.
If you may be using both loading from a NIB and programmatic creation, you should make a common method (initCommon maybe?) that you would call from both initWithFrame and initWithCoder.
Oh, and your init method is not using the recommended practices:
- (id)initWithFrame:(CGRect)frameRect
{
if (!(self = [super initWithFrame:frameRect]))
return nil;
// ...
}
You should always check the return value of [super init...].

UIView not retaining subviews

I made this play/pause/stop control but it doesn't work as expected. at load time it creates three views and stores them in an array, each view represents one state of the control. In the stopped state it contains a play button that is a member of a simple class cluster I made. In the other two states it contains a UIView with two of the buttons as subviews. In the first state it works and does exactly what it's supposed to, but when it tries to go to the next state it looks in the array and finds views at the playing state and paused state positions with no subviews. In fact, if you trace it through the execution of the loadView function the array never gets a view with subviews in it even though I called addSubview:(UIView *)view which the documentation says this about: This method retains view and sets its next responder to the receiver, which is its new superview.
I would really like some help trying to understand why this is happening. To be more clear, why don't the UIViews that are passed to the array have subviews when the local variables for them do.
Thanks in advance,
Rich
Here's the source:
// IMSpeechControl.h
#import <UIKit/UIKit.h>
#import "IMSpeechEngine.h"
typedef enum {
IMSpeechControlStateStopped = 0,
IMSpeechControlStatePlaying = 1,
IMSpeechControlStatePaused = 2
} IMSpeechControlState;
/* State Stopped: speech control should show a Play button.
State Playing: speech control should show a Pause button and a Stop button.
State Paused : speech control should show a Play button and a Stop button.
*/
#class IMSpeechControl;
#protocol IMSpeechControlDelegate <NSObject>
- (NSString *)speechControlNeedsText:(IMSpeechControl *)sender;
#end
#interface IMSpeechControl : UIViewController {
IMSpeechControlState controlState;
id delegate;
IMSpeechEngine *speechEngine;
NSMutableArray *controlButtons_;
CGRect frame_;
}
#property (nonatomic, readonly) IMSpeechControlState controlState;
#property (nonatomic, assign) id<IMSpeechControlDelegate> delegate;
// Designated initilazer
- (IMSpeechControl *)initWithFrame:(CGRect)frame;
// This must be here, do not call it from outside it's control buttons
- (void)changeToState:(IMSpeechControlState)controlState;
- (void)play;
- (void)pause;
- (void)stop;
#end
This is the important one.
// IMSpeechControl.m
#import "IMSpeechControl.h"
#import "IMSpeechControlButton.h"
#interface IMSpeechControl ()
#property (nonatomic, assign) IMSpeechEngine *speechEngine;
#property (nonatomic, retain) NSMutableArray *controlButtons;
// Used only for initialization, do not change after calling initWithFrame
// to change the view size after creation
#property (nonatomic) CGRect frame;
- (void)speechEngineDidFinishSpeaking:(NSNotification *)notifictation;
#end
#implementation IMSpeechControl
#synthesize controlState, delegate, speechEngine, frame=frame_;
#synthesize controlButtons=controlButtons_;
/* State Stopped: speech control should show a Play button.
State Playing: speech control should show a Pause button and a Stop button.
State Paused : speech control should show a Play button and a Stop button.
*/
- (IMSpeechControl *)initWithFrame:(CGRect)aFrame {
if (self = [super init]) {
self.frame = aFrame;
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(speechEngineDidFinishSpeaking:) name:kDidFinishSpeakingNotificationName object:self.speechEngine];
}
return self;
}
- (void)loadView {
// Initialization code.
// Create the main view.
UIView *aView = [[UIView alloc] initWithFrame:self.frame];
self.view = aView;
[aView release];
// Create the sub-views and store them in an array.
NSMutableArray *controls = [[NSMutableArray alloc] initWithCapacity:3];
// The stopped state play button view can be used directly since it is the only button shown.
IMSpeechControlButton *button = [[IMSpeechControlButton alloc] initWithFrame:self.frame forControl:self style:IMSpeechControlButtonStylePlay];
[controls insertObject:button atIndex:(NSUInteger)IMSpeechControlStateStopped];
[button release];
// The other two states require two buttons each, so the two buttons must be grouped into a UIView that can be easily switched out.
// Make two frames, one for the left and one for the right. Both are half the width of the main view
// The one on the left has the same origin as the main view...
CGRect halfFrameLeft = CGRectMake(frame_.origin.x, frame_.origin.y, frame_.size.width / 2, frame_.size.height);
// and the one on the right starts half-way across the main view
CGRect halfFrameRight = CGRectMake((frame_.origin.x + (frame_.size.width / 2)), frame_.origin.y, frame_.size.width / 2, frame_.size.height);
// Playing state
// Pause button
UIView *playingState = [[UIView alloc] initWithFrame:self.frame];
IMSpeechControlButton *plsPauseButton = [[IMSpeechControlButton alloc] initWithFrame:halfFrameLeft forControl:self style:IMSpeechControlButtonStylePause];
[playingState addSubview:plsPauseButton];
[plsPauseButton release];
// Stop button
IMSpeechControlButton *plsStopButton = [[IMSpeechControlButton alloc] initWithFrame:halfFrameRight forControl:self style:IMSpeechControlButtonStyleStop];
[playingState addSubview:plsStopButton];
[plsStopButton release];
[controls insertObject:playingState atIndex:(NSUInteger)IMSpeechControlStatePlaying];
[playingState release];
// Paused state
// Play button
UIView *pausedState = [[UIView alloc] initWithFrame:self.frame];
IMSpeechControlButton *pasPlayButton = [[IMSpeechControlButton alloc] initWithFrame:halfFrameLeft forControl:self style:IMSpeechControlButtonStylePlay];
[pausedState addSubview:pasPlayButton];
[pasPlayButton release];
// Stop button
IMSpeechControlButton *pasStopButton = [[IMSpeechControlButton alloc] initWithFrame:halfFrameRight forControl:self style:IMSpeechControlButtonStyleStop];
[pausedState addSubview:pasStopButton];
[pasStopButton release];
[controls insertObject:pausedState atIndex:(NSUInteger)IMSpeechControlStatePaused];
[pausedState release];
// store the array in an instance variable
self.controlButtons = controls;
[controls release];
// Set the view to it's first state (stopped)
IMSpeechControlButton *stoppedState = (IMSpeechControlButton *)[self.controlButtons objectAtIndex:(NSUInteger)IMSpeechControlStateStopped];
[self.view addSubview:stoppedState];
controlState = IMSpeechControlStateStopped;
}
- (IMSpeechEngine *)speechEngine {
if (nil == speechEngine) {
self.speechEngine = [IMSpeechEngine sharedManager];
}
return speechEngine;
}
- (void)changeToState:(IMSpeechControlState)state {
// This line caused my problem
// IMSpeechControlButton *currentView = [[self.view subviews] objectAtIndex:0];
// It should look like this
UIView *currentView = [[self.view subviews] objectAtIndex:0];
switch (state) {
case IMSpeechControlStateStopped:
{
UIView *stoppedState = (UIView *)[self.controlButtons objectAtIndex:(NSUInteger)IMSpeechControlStateStopped];
[self.view addSubview:stoppedState];
[UIView animateWithDuration:0.15
animations:^{
currentView.alpha = 0.5;
stoppedState.alpha = 0.15;
}
completion:^(BOOL finished)
currentView.alpha = 0.0;
[currentView removeFromSuperview];
[UIView animateWithDuration:0.15 animations:^{stoppedState.alpha = 0.5;}];
}];
controlState = IMSpeechControlStateStopped;
break;
}
case IMSpeechControlStatePlaying:
{
UIView *playingState = [self.controlButtons objectAtIndex:(NSUInteger)IMSpeechControlStatePlaying];
[self.view addSubview:playingState];
[UIView animateWithDuration:0.15
animations:^{
currentView.alpha = 0.5;
playingState.alpha = 0.15;
}
completion:^(BOOL finished){
currentView.alpha = 0.0;
[currentView removeFromSuperview];
[UIView animateWithDuration:0.15 animations:^{playingState.alpha = 0.5;}];
}];
controlState = IMSpeechControlStatePlaying;
break;
}
case IMSpeechControlStatePaused:
{
UIView *pausedState = (UIView *)[self.controlButtons objectAtIndex:(NSUInteger)IMSpeechControlStatePaused];
[self.view addSubview:pausedState];
[UIView animateWithDuration:0.15
animations:^{
currentView.alpha = 0.5;
pausedState.alpha = 0.15;
}
completion:^(BOOL finished){
currentView.alpha = 0.0;
[currentView removeFromSuperview];
[UIView animateWithDuration:0.15 animations:^{pausedState.alpha = 0.5;}];
}];
controlState = IMSpeechControlStatePaused;
break;
}
default:
NSLog(#"Error %lu is not a recognized IMSpeechControlState", state);
break;
}
}
- (void)speechEngineDidFinishSpeaking:(NSNotification *)notifictation {
// This notification is only sent if it has finished speaking and is therefore stopped.
[self changeToState:IMSpeechControlStateStopped];
}
- (void)play {
NSString *text = [delegate speechControlNeedsText:self];
[self.speechEngine speakText:text];
[self changeToState:IMSpeechControlStatePlaying];
}
- (void)pause {
[self.speechEngine pauseSpeaking];
[self changeToState:IMSpeechControlStatePaused];
}
- (void)stop {
[self.speechEngine stopSpeaking];
[self changeToState:IMSpeechControlStateStopped];
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self forKeyPath:kDidFinishSpeakingNotificationName];
[super dealloc];
}
#end
// IMSpeechControlButton.h
#import "IMSpeechControl.h"
typedef enum {
IMSpeechControlButtonStylePlay,
IMSpeechControlButtonStylePause,
IMSpeechControlButtonStyleStop
}IMSpeechControlButtonStyle;
#interface IMSpeechControlButton: UIView {
IMSpeechControl *speechControl;
UIImageView *imageView;
}
#property (nonatomic, assign) IMSpeechControl *speechControl;
#property (nonatomic, retain) UIImageView *imageView;
- (IMSpeechControlButton *)initWithFrame:(CGRect)aRect
forControl:(IMSpeechControl *)control
style:(IMSpeechControlButtonStyle)style;
#end
// IMSpeechControlButton.m
#import "IMSpeechControlButton.h"
#import <Foundation/NSObjCRuntime.h>
#implementation IMSpeechControlButton
#synthesize speechControl;
#synthesize imageView;
- (IMSpeechControlButton *)initWithFrame:(CGRect)aRect
forControl:(IMSpeechControl *)control
style:(IMSpeechControlButtonStyle)style
{
NSString *str;
switch (style) {
case IMSpeechControlButtonStylePlay:
str = #"IMSpeechControlPlay";
break;
case IMSpeechControlButtonStylePause:
str = #"IMSpeechControlPause";
break;
case IMSpeechControlButtonStyleStop:
str = #"IMSpeechControlStop";
break;
default:
break;
}
isa = NSClassFromString(str);
// the speechControl must be set before calling subclass implementation of initWithFrame
self.speechControl = control;
return [self initWithFrame:aRect];
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
// Drawing code.
}
*/
- (void)dealloc {
[super dealloc];
}
#end
All the control buttons have the exact same code as the play button, except that the handleGesture method calls the appropriate play/pause/stop function on the speechControl. The only reason I created all of them was so each of them could have their own images and so they can play different animations before changing state, but I didn't get to that yet.
// IMSpeechControlPlay.h
#import "IMSpeechControlButton.h"
#interface IMSpeechControlPlay : IMSpeechControlButton {
}
- (void)handleGesture:(UIGestureRecognizer *)gestureRecognizer;
#end
// IMSpeechControlPlay.m
#import "IMSpeechControlPlay.h"
#implementation IMSpeechControlPlay
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// Initialization code.
// TODO: set the image view
UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleGesture:)];
gestureRecognizer.numberOfTapsRequired = 1;
gestureRecognizer.numberOfTouchesRequired = 1;
gestureRecognizer.delaysTouchesBegan = YES;
[self addGestureRecognizer:gestureRecognizer];
[gestureRecognizer release];
}
return self;
}
- (void)handleGesture:(UIGestureRecognizer *)gestureRecognizer {
if (gestureRecognizer.state == UIGestureRecognizerStateEnded) {
[speechControl play];
}
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
// Drawing code.
}
*/
- (void)dealloc {
[super dealloc];
}
#end
I found the problem, it was in this line:
IMSpeechControlButton *currentView = (IMSpeechControlButton *)[[self.view subviews] objectAtIndex:0]; in the changeState method.
I'd changed and moved this line several times during development, and had an older version of the file where it was correctly stated as:
UIView *currentView = [[self.view subviews] objectAtIndex:0];
but I just noticed that the file I was building has the first version. The version that I copied the source from turned out to be an old version that looked like this:
UIView *currentView = (IMSpeechControl *)[[self.view subviews] objectAtIndex:0];
Changing that to a UIView pointer makes it work. Looking at the debug info it looks like I was wrong about the subviews not getting retained, they were actually just unavailable in the debugger being cast away when the play control was pressed. Setting the speechControl variable before calling init actually works fine.
Thanks for all the advice and so quickly.
This method is just really wrong
- (IMSpeechControlButton *)initWithFrame:(CGRect)aRect
forControl:(IMSpeechControl *)control
style:(IMSpeechControlButtonStyle)style
Basically there is nothing to return here
self.speechControl = control;
return [self initWithFrame:aRect];
Because you haven't actually inited "self" yet. You need to rewrite that function to have a proper initializer like the one you have in IMSpeechControlPlay.

Using TTImageView with AQGridView

I created a custom AQGridViewCell.
By using UIImageView everything works. The image appears and is clickable, but when I change the UIImageView to TTImageView I can't click on the image.
The same example as here below by just changing the imageview to UIImageView and the the setter message to an image, everything works as expected.
Here is my ImageGridCell.h
#import "AQGridViewCell.h"
#import <Three20/Three20.h>
#interface ImageGridCell : AQGridViewCell
{
TTImageView * _imageView;
NSString *urlPath;
}
#property (nonatomic, retain) NSString *urlPath;
#end
And here is my ImageGridCell.m
#import "ImageGridCell.h"
#implementation ImageGridCell
#synthesize urlPath;
- (id) initWithFrame: (CGRect) frame reuseIdentifier: (NSString *) aReuseIdentifier
{
self = [super initWithFrame: frame reuseIdentifier: aReuseIdentifier];
if ( self == nil )
return ( nil );
_imageView = [[TTImageView alloc] initWithFrame: CGRectMake(0, 0, 100, 100)];
[_imageView setContentMode:UIViewContentModeScaleAspectFit];
[self.contentView addSubview: _imageView];
return ( self );
}
- (void) dealloc
{
[_imageView release];
[super dealloc];
}
- (CALayer *) glowSelectionLayer
{
return ( _imageView.layer );
}
- (UIImage *) image
{
return ( _imageView.image );
}
-(void)setUrlPath:(NSString *)urlpath {
_imageView.urlPath = urlpath;
}
I faced the same situation, and here is the solution I came with.
My AQGridViewCell have both a TTImageView and a UIImageView.
I use the TTImageView to load the image, and when it's loaded, I pass it to the UIImageView which displays it.
To do that, my AQGridViewCell subclass implements the TTImageViewDelegate protocol. In my PostGridViewCell.h, I have :
#interface PostGridViewCell : AQGridViewCell <TTImageViewDelegate> {
#private
TTImageView *ttImageView_;
UIImageView *imageView_;
}
// #property here …
#end
In my implementation file, in the initWithFrame:reuseIdentifier: method, I init both my ttImageView and my imageView, but I only add the imageView as a subview of my cell. And I set the ttImageView delegate property to self (so I can be notified when the image is loaded) :
- (id)initWithFrame:(CGRect)frame reuseIdentifier:(NSString *)aReuseIdentifier {
if ((self = [super initWithFrame:frame reuseIdentifier:aReuseIdentifier])) {
// init image
ttImageView_ = [[TTImageView alloc] initWithFrame:CGRectZero];
ttImageView_.delegate = self;
imageView_ = [[UIImageView alloc] initWithFrame:CGRectZero];
[self.contentView addSubview:imageView_];
// …
}
return self;
}
When the TTImaveView has loaded the image, it calls the imageView:didLoadImage: method on the delegate (which is the PostGridViewCell). In my implementation file, I have this method :
- (void)imageView:(TTImageView*)imageView didLoadImage:(UIImage*)image {
self.imageView.image = image;
[self setNeedsLayout];
}
Does it help?
Cheers,
Thomas.
Not quite sure what you mean by "clickable" - like a UIButton? What behavior do you want to accomplish when a user taps one of the images?
I can't see the immediate problem here, but I can give you information that may help.
Foremost, TTImageView and UIImageView both descend from UIView, TTImageView does not descend from UIImageView (important to note):
UIImageView : UIView
TTImageView : TTView : UIView
We don't know what is going on behind the scenes in UIImageView, so I can't see what is different there, but the documentation seems to make clear that the UIImageView's default behavior for userInteractionEnabled is NO - which is odd, because you are saying that it is working with UIImageView, not the other way around.
Have you tried setting the userInteractionEnabled property to YES on TTImageView?
The problem here is that TTImageView has userInteractionEnabled to YES. So the touch event is being held by the TTImageView, and AQGridView expects touches in cell Views. Simply add userInteractionEnabled=NO to the TTImageView in your cell and you are ready to go.