Issue while implementing MVC - iphone

I am facing an issue while implementing MVC. I created a UIView subclass and have designed my custom view. I created a UIViewController subclass and pointed its view to my custom view class. Finally I created a NSObject subclass and created a model for my controller. When i am running the app, i am getting a black screen... Any idea on this?
==My Model==
- (id) init
{
imgArray = [[NSMutableArray alloc] initWithObjects: [UIImage imageNamed:#"scene.jpg"],
[UIImage imageNamed:#"scene1.jpg"],
[UIImage imageNamed:#"scene2.jpg"], nil];
return self;
}
==My Controller==
- (void)viewDidLoad {
[super viewDidLoad];
NSNotification
CGRect mainFrame = [[UIScreen mainScreen] applicationFrame];
// Get the view
MVCView *myView = [[MVCView alloc] initWithFrame:mainFrame];
// Get the data
MVCModel *myModel = [[MVCModel alloc] init];
myView.myImgView.image = [myModel.imgArray objectAtIndex:0];
//[self.view addSubview:myView];
[myView setNeedsDisplay];
self.view = myView;
self.title = #"MVC";
}
==My View==
- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
// Initialization code
CGRect imgFrame = CGRectMake(5, 20, 150, 150);
//myImgView.image = [UIImage imageNamed:#"scene.jpg"];
myImgView.frame = imgFrame;
CGRect lblFrame = CGRectMake(5, 150, 50, 50);
myLabel.text = #"Nature is beautiful";
myLabel.frame = lblFrame;
CGRect sldFrame = CGRectMake(5, 200, 50, 50);
mySlider.minimumValue = 0;
mySlider.maximumValue = 100;
mySlider.frame = sldFrame;
}
return self;
}
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
// Drawing code
CGPoint imgPoint = CGPointMake(10, 20);
[self.myImgView drawAtPoint:imgPoint];
CGPoint lblPoint = CGPointMake(10, 160);
[self.myLabel drawAtPoint:lblPoint];
CGPoint sldPoint = CGPointMake(10, 210);
[self.mySlider drawAtPoint:sldPoint];
}

Have you set your UIViewController's view as a subview of the Window's view that comes with your AppDelegate in your application:didFinishLaunchingWithOptions:?

I got the issue... Actually, i was not allocating memory to my UIView subclass components and was trying to use drawAtPoint method. Once i allocated memory to and added them as a subview of my view class, i got the correct screen displayed.

Related

UIView in NSCache being overriden

I have a UIView that contains drop shadows and corners which I am loading four of in my UIViewController and I am seeing a performance hit when the screen loads. Since I am using the same white background with shadows and corner radii I figured I would store the UIView in NSCache.
When I run the app there is a large gap where the first UIView should be, however, it is not showing up. What does show up is the last view in my list of views. If I comment out the last one and run it again, the third one shows up. It seems like I am having an issue with the pointer in memory but not sure. Perhaps I am using NSCache incorrectly?
(Note: The first view shown is not using the NSCache)
Here is how I am using the NSCache:
.h file
#interface LunchDetailViewController : UIViewController <UIScrollViewDelegate>
#property (nonatomic) IBOutlet UIScrollView *scrollView;
#property (nonatomic, strong) NSCache *entreeViewsCache;
#end
.m file
#synthesize scrollView;
#synthesize entreeViewsCache;
- (void)viewDidLoad
{
[super viewDidLoad];
self.entreeViewsCache = [[NSCache alloc] init];
UIView *entreeView = [[UIView alloc] init];
entreeView.backgroundColor = [UIColor whiteColor];
entreeView.layer.masksToBounds = NO;
entreeView.layer.cornerRadius = 3.0;
entreeView.layer.shadowOffset = CGSizeMake(1.1, 2.1);
entreeView.layer.shadowOpacity = 0.2;
[self.entreeViewsCache setObject:entreeView forKey:#"EntreeView"];
}
- (void) configureScrollView
{
// This line of code allows the scroll view to be 'scrollable'.
self.scrollView.contentSize = CGSizeMake(320, 620);
UIView *elementaryRoundedCornerView = [self.entreeViewsCache objectForKey:#"EntreeView"];
elementaryRoundedCornerView.frame = CGRectMake(15,15,290,180);
UIView *middleRoundedCornerView = [self.entreeViewsCache objectForKey:#"EntreeView"];
middleRoundedCornerView.frame = CGRectMake(15,210,290,180);
UIView *highRoundedCornerView = [self.entreeViewsCache objectForKey:#"EntreeView"];
highRoundedCornerView.frame = CGRectMake(15,404,290,180);
NSMutableArray *entreeItems = [[NSMutableArray alloc] initWithObjects:#"Pancakes w/ Sausage Patties", #"Corn Dog", #"Grilled Cheese Sandwhich", #"Chicken Tender Wraps", nil];
UIView *elementaryLunchMenuDetails = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 240, 160)];
[elementaryLunchMenuDetails addSubview:[self returnNativeCode:entreeItems rectDimensions:CGRectMake(2, 5, 215, 160) schoolType:#"Elementary"]];
[elementaryRoundedCornerView addSubview:elementaryLunchMenuDetails];
UIView *middleLunchMenuDetails = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 240, 160)];
[middleLunchMenuDetails addSubview:[self returnNativeCode:entreeItems rectDimensions:CGRectMake(2, 2, 215, 160) schoolType:#"Middle"]];
[middleRoundedCornerView addSubview:middleLunchMenuDetails];
UIView *highLunchMenuDetails = [[UIView alloc] initWithFrame:CGRectMake(10,10, 240, 160)];
[highLunchMenuDetails addSubview:[self returnNativeCode:entreeItems rectDimensions:CGRectMake(2, 2, 215, 160) schoolType:#"High"]];
[highRoundedCornerView addSubview:highLunchMenuDetails];
[self.scrollView addSubview:elementaryRoundedCornerView];
[self.scrollView addSubview:middleRoundedCornerView];
[self.scrollView addSubview:highRoundedCornerView];
}
Wow. That's clever. But not correct.
Instead of using NSCache to duplicate a view, you probably want to create a UIView subclass that formats the view the way you want. Then just throw a bunch of those views on your scrollview.
ABCView.m
#implementation ABCDayView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor whiteColor];
self.layer.masksToBounds = NO;
self.layer.cornerRadius = 3.0;
self.layer.shadowOffset = CGSizeMake(1.1f, 2.1f);
self.layer.shadowOpacity = 0.2f;
}
return self;
}
- (void)setItems:(NSArray *)items
{
if ([_items isEqualToArray:items] == NO) {
_items = items;
[self createItemViews];
[self setNeedsLayout];
}
}
// You'll also need to add -createItemViews and -setNeedsLayout methods.
.m file
- (void)configureScrollView
{
NSMutableArray *entreeItems = #[#"Pancakes w/Sausage Patties",
#"Corn Dog",
#"Grilled Cheese Sandwhich",
#"Chicken Tender Wraps"];
CGRect frame = CGRectMake(15,15,290,180);
ABCDayView *elementaryView = [[ABCDayView alloc] initWithFrame:frame];
elementaryView.items = entreeItems;
CGFloat y = CGRectGetMaxY(elementaryView.frame) + 10.0f;
frame = CGRectMake(15, y, 290, 180);
ABCDayView *middleView = [[ABCDayView alloc] initWithFrame:frame];
middleView.items = entreeItems;
...
CGFloat length = // Use CGRectGetMaxY on the last frame to get the length.
self.scrollView.contentSize = CGSizeMake(320, length);
}
That's by no means perfect code. But hopefully it will give you an idea of a better way to implement this.

Programmatically created button not firing event in custom view in iOS

On iOS, I created a button programmatically but the event is not firing.
UIButton * anyButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[anyButton addTarget:self action:#selector(handleAnyButton:) forControlEvents:UIControlEventTouchUpInside];
anyButton.frame = CGRectMake(150, 350, 22, 22);
[self addSubview:anyButton];
The code is placed inside a custom view (not custom view controller), but I cannot make it fire the event. The press animation is not showing. The custom view has userInteractionEnabled enabled. I also tried using storyboard to create another button on the same view and that one is working. The button code is done in initWithFrame. Must be some simple error I haven't caught and I have been pounding my head over this one for hours.
EDIT:
The event handler:
-(void) handleAnyButton:(UIButton *)button
{
NSLog(#"handleAnybutton called");
}
EDIT2:
The above button codes is done within a [self setup] of class PKLocationsSelectionView.
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
[self setup];
}
return self;
}
And this view was created programmatically within the view controller (PKLocSelectionViewController) responsible for this hierarchy:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
CGFloat fieldsHeight = 88;
UIView * view = [[PKLocationsSelectionView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, fieldsHeight)];
[self.view addSubview:view];
}
It looks like your button frame
anyButton.frame = CGRectMake(150, 350, 22, 22);
is outside of parent bounds
CGFloat fieldsHeight = 88;
UIView * view = [[PKLocationsSelectionView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, fieldsHeight)];
Here is the code that works for me:
MyCustomView.m:
#import "MyCustomView.h"
#implementation MyCustomView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(0, 0, 100, 100);
[button addTarget:self action:#selector(greet:) forControlEvents:UIControlEventTouchUpInside];
[button setTitle:#"Greet" forState:UIControlStateNormal];
[self addSubview:button];
self.backgroundColor = [UIColor greenColor];
}
return self;
}
-(void) greet:(id) sender
{
NSLog(#"greet!");
}
And here is the ViewController.m:
- (void)viewDidLoad
{
[super viewDidLoad];
MyCustomView *view = [[MyCustomView alloc] init];
view.frame = CGRectMake(0, 0, 100, 100);
[self.view addSubview:view];
}
EDIT2: Could it be the Button is not fully enclosed within the coordinates of the container (PKLocationsSelectionView) view?
The height of the PKLocationsSelectionView is 88 from your code and the position of the button seems to be outside this. I think if the button is not enclosed within the frame of the superview then it won't receive touches.
Try and change your View initialization code in viewDidLoad, to give a static frame and see if it works..
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
CGFloat fieldsHeight = 88;
//See the change in below line.. instead of using self.view.bounds.size.width
// I used a static width.. 320 pixel for the moment..
UIView * view = [[PKLocationsSelectionView alloc] initWithFrame:CGRectMake(0, 0, 320.0, fieldsHeight)];
[self.view addSubview:view];
}
In viewDidLoad view hierarchy of controller will not be drawn completely..So self.view.bounds.size.width may be giving incorrect values.. To access self.view.frame and self.view.bounds, you should atleast wait until viewWillAppear gets called.
Also, your button origin.y is at 350 which in a view which has maximum height of only 88.. Any control outside parent's frame won't receive touches..

iPhone: Change UIImageView frame

I have a custom UIView. So myView class extend UIView. In initWithFrame:(CGRect)frame method I set UIImageView for my UIView as a background image.
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.bgImage = [[[UIImageView alloc] initWithFrame:
CGRectMake(0, 0, frame.size.width , frame.size.height)] autorelease];
int stretchableCap = 20;
UIImage *bg = [UIImage imageNamed:#"myImage.png"];
UIImage *stretchIcon = [bg
stretchableImageWithLeftCapWidth:stretchableCap topCapHeight:0];
[self.bgImage setImage:stretchIcon];
}
return self;
}
So when I create my view everything is fine.
MyCustomView *customView = [[MyCustomView alloc] initWithFrame:CGRectMake(10, 10, 100, 50)];
But if I want to change my view size to bigger or smaller:
customView.frame = CGRectMake(10, 10, 50, 50)];
then I have the problem with my background image. Because it's size didn't changed. What to do ? Ho to change bg image size together with view frame ?
Try setting the autoresizing mask of the UIImageView, it will resize according to the size changes of the super view.
My suggestion is use update function to update your custom view when you want to change the frame:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self UpdateViewWithFrame:frame];
}
return self;
}
- (void)UpdateViewWithFrame:(CGRect)frame
{
self.frame = frame;//set frame
if(!self.bgImage)
{
//initialize your imageview
self.bgImage = [[[UIImageView alloc] initWithFrame:
CGRectMake(0, 0, frame.size.width , frame.size.height)] autorelease];
}
int stretchableCap = 20;
UIImage *bg = [UIImage imageNamed:#"myImage.png"];
UIImage *stretchIcon = [bg
stretchableImageWithLeftCapWidth:stretchableCap topCapHeight:0];
[self.bgImage setImage:stretchIcon];
}
When you want change frame , just call this function.Have a try man.
Set the required Autoresizingmask property attributes for the imageview correctly as it must be adjusted along with the view frames.
So the suggestions was right. I should add autoresizing mask. Now my initWithFrame looks like that:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.bgImage = [[[UIImageView alloc] initWithFrame:
CGRectMake(0, 0, frame.size.width , frame.size.height)] autorelease];
int stretchableCap = 20;
UIImage *bg = [UIImage imageNamed:#"myImage.png"];
UIImage *stretchIcon = [bg
stretchableImageWithLeftCapWidth:stretchableCap topCapHeight:0];
[self.bgImage setImage:stretchIcon];
self.bgImage.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
self.autoresizesSubviews = YES;
}
return self;
}

how to pushViewController to another view with images in a scrollview

I have a scrollview of images, I will like to tab them and will pushed to another view.
once i tab on the image, the whole view should push to another view.
From this View to another view
Detail view
Sorry for not asking the question clearly.
my scrollview
-(void)pictureScrolling
{
//init scrollview in location on screen
scrollview = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 100, 320, 290)];
scrollview.backgroundColor = [UIColor redColor];
//pass image filenames
NSMutableArray *fileNames = nearbyFrog.imageFiles; //[[[NSMutableArray alloc] init] autorelease];
//setup the array of uiimageviews
NSMutableArray *imgArray = [[NSMutableArray alloc] init];
UIImageView *imageView;
//loop through the array imgNames to add file names to imgArray
for (NSString *imageName in fileNames) {
imageView = [[UIImageView alloc] init];
imageView.image = [UIImage imageNamed:imageName];
imageView.contentMode = UIViewContentModeScaleAspectFit;
[imgArray addObject:imageView];
[imageView release];
}
CGSize pageSize = scrollview.frame.size;
NSUInteger page = 0;
for (UIView *viewForScrollView in imgArray) {
[scrollview addSubview:viewForScrollView];
viewForScrollView.frame = CGRectMake(pageSize.width * page++ +10, 0, pageSize.width -20 , pageSize.height);
// making use of the scrollView's frame size (pageSize) so we need to;
// +10 to left offset of image pos (1/2 the gap)
// -20 for UIImageView's width (to leave 10 gap at left and right)
}
//add scroll view to view
[self.view addSubview:scrollview];
scrollview.contentSize = CGSizeMake(pageSize.width * [imgArray count], pageSize.height);
//scrollview.contentSize = CGSizeMake(320 *viewcount + 20, 290 );
scrollview.showsHorizontalScrollIndicator =NO;
[scrollview setPagingEnabled:YES];
scrollview.delegate =self;
//paging function for scrollview
CGRect frame = [[UIScreen mainScreen] applicationFrame];
self.pageControl = [[[UIPageControl alloc] initWithFrame:CGRectMake(0, 100, 100, 50)] autorelease];
self.pageControl.center = CGPointMake(frame.size.width/2, frame.size.height-60);
self.pageControl.numberOfPages = [fileNames count];
[self.view addSubview:self.pageControl];
//handle Touch Even
[pageControl addTarget:self action:#selector(changePage:) forControlEvents:UIControlEventValueChanged];
[imgArray release];
}
anybody knows how to do it or can show me a tutorial?
Thanks
I think this is the best way to implement it
Create your own Custom UIImageView class. This is required to store an additional property which will help you identify which image for clicked.
Create a delegate for that class which is called with the single tap event is raised in the UIImageView
Add the Images inside the scrollview using this custom class. The delegate of this class will tell you which image was tapped. You can use this to push a new view controller passing the image details (if necessary).
You can find some sample code in the ThumbImageView class in the scrollviewSuite sample
http://developer.apple.com/library/ios/#samplecode/ScrollViewSuite/Introduction/Intro.html#//apple_ref/doc/uid/DTS40008904-Intro-DontLinkElementID_2

Why does initWithFrame have the wrong frame value?

I have a subclass of UIButton called INMenuCard and I am overriding the initWithFrame to include an activity indicator. The menuCard places correctly but any internal reference to "frame" give me "inf,inf,0,0" which means my activityIndicator subview is not placed correctly. What might I be missing?
#implementation INMenuCard
- (id)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame])
{
CGRect innerFrame = CGRectInset(frame, 50.0f, 100.0f);
activityIndicator = [[UIActivityIndicatorView alloc]
initWithFrame:innerFrame];
activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhite;
[self addSubview:activityIndicator];
}
return self;
}
I am instantiating INMenuCard with (debugging shows the CGRect values are correct):
CGRect cardFrame = CGRectMake(cardX, cardStartY, cardWidth, cardHeight);
INMenuCard *menuCard = [[INMenuCard buttonWithType:UIButtonTypeCustom] initWithFrame:cardFrame];
[theView addSubView:menuCard];
Should you be calling initWithFrame on something that is already init'ed?
It seems to me that the line [INMenuCard buttonWithType:UIButtonTypeCustom] is calling the UIButton's shortcut which does the [[UIButton alloc] init] for you.