How to attach more than one controller to views its subviews - iphone

plz help me out
I am a newbie in iphone development its my second sample code. I am trying to add sub-views to a View and generate events according to the view/subview which is touched.i have added subviews in main view and all are showing all at one time. The projects I am experimenting with is a newly created, clean Window-Base application.
I wrote the following code into the one and only viewController's code:
#interface testViewController : UIViewController {
IBOutlet UIView *blueView1;
IBOutlet UIView *blueView2;
: :
IBOutlet UIView *blueView6;
}
//---expose the outlet as a property---
#property (nonatomic, retain) IBOutlet UIView *blueView1;
#property (nonatomic, retain) IBOutlet UIView *blueView2;
: : *blueView6;
//---declaring the action---
-(IBAction) viewClicked: (id) sender;
#end
And its .m file contains (loadView method in which i am attaching subviews to it. They are displaying very well all at one time.what i am trying to do is when my view/subview are touched they will generate an event which should be treated by this single method according to their object which will change the back color of the view/subview accordingly.
- (void)loadView {
self.view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 80)];
self.view.backgroundColor = [UIColor greenColor];
// Create a simple blue square
CGRect blueFrame0 = CGRectMake(5, 115, 100, 100);
UIView *blueView0 = [[UIView alloc] initWithFrame:blueFrame0];
blueView0.backgroundColor = [UIColor blueColor];
// Create a simple blue square
CGRect blueFrame1 = CGRectMake(110, 115, 100, 100);
UIView *blueView1 = [[UIView alloc] initWithFrame:blueFrame1];
blueView1.backgroundColor = [UIColor blueColor];
// Create a simple blue square
CGRect blueFrame2 = CGRectMake(215, 115, 100, 100);
UIView *blueView2 = [[UIView alloc] initWithFrame:blueFrame2];
blueView2.backgroundColor = [UIColor blueColor];
//-----------------------------------------------------------------------------------------------------------
// Create a simple blue square
CGRect blueFrame3 = CGRectMake(5, 220, 100, 100);
UIView *blueView3 = [[UIView alloc] initWithFrame:blueFrame3];
blueView3.backgroundColor = [UIColor blueColor];
// Create a simple blue square
CGRect blueFrame4 = CGRectMake(110, 220, 100, 100);
UIView *blueView4 = [[UIView alloc] initWithFrame:blueFrame4];
blueView4.backgroundColor = [UIColor blueColor];
// Create a simple blue square
CGRect blueFrame5 = CGRectMake(215, 220, 100, 100);
UIView *blueView5 = [[UIView alloc] initWithFrame:blueFrame5];
blueView5.backgroundColor = [UIColor blueColor];
[self.view addSubview:blueView0];
[self.view addSubview:blueView1];
[self.view addSubview:blueView2];
[self.view addSubview:blueView3];
[self.view addSubview:blueView4];
[self.view addSubview:blueView5];
[blueView0 release];
[blueView1 release];
[blueView2 release];
[blueView3 release];
[blueView4 release];
[blueView5 release];
[self.view release];
}
-(IBAction) viewClickedid) sender {
{view/subview}.backgroundColor = [UIColor blackColor];
}
i worte the delegate in this way
#interface testAppDelegate : NSObject <UIApplicationDelegate>
{
UIWindow *window;
testViewController *viewController; //for main view
testViewController *viewController1;//for subview1
testViewController *viewController2;//for subview2
testViewController *viewController3;//for subview3
**upto 6 controllers
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet testViewController viewController;
#property (nonatomic, retain) IBOutlet testViewController viewController1;
**upto 6 controllers
#end
In testAppdelegate.m i am making a controller for main view but i dont know how to attach other controllers to other subviews.right now when i touch anywhere on the view the main view color changes.
how can i uniquely identify different subviews touch and make their color change??How to do this????
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// Override point for customization after application launch
checkAppController *rootController = [checkAppController alloc];
[window addSubview:[rootController view]];
[window makeKeyAndVisible];
}
i am getting all the touches events in this method
- (void)touchesBeganNSSet *)touches withEventUIEvent *)event {
UITouch* touch = [touches anyObject];
NSUInteger numTaps = [touch tapCount];
if ([touches count] > 1)
NSLog(#"mult-touches %d", [touches count]);
if (numTaps < 2) {
}
else {
NSLog(#"double tap");
}
}

It is to do with the way you are structuring your application. For the BlueView1..6 to be handled by a separate view controller, it is that view controller which needs to create the view.
You need to create the view controllers for each blue view inside the main view controller, and then create each blue view inside the blue view inside each blue view controller.

Related

touchesBegan not functioning on programmatically created view and imageview

I am programmatically creating a view and a imageview while in viewControllerA for an another viewControllerB before I then goto viewControllerB. I have to do this, as I am using an image from the imagePickerController. However by doing this, touchesBegan does not function in viewControllerB
I have set UserInteractionEnabled to true/yes in both the attributes inspector of the xib and programmatically everywhere!
My xib is just a blank canvas, with one View. I have tried different settings with the connections inspector, but still no luck.
Here is my code.
viewControllerA.m
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
CGRect screenRect = [[UIScreen mainScreen] applicationFrame];
view = [[UIView alloc] initWithFrame:screenRect];
image = [info valueForKey:UIImagePickerControllerEditedImage];
SSViewController *psView = [[SSViewController alloc] initWithNibName:#"SSViewController" bundle:nil];
psView.view = [[UIView alloc] initWithFrame:screenRect];
[psView.view setUserInteractionEnabled:YES];
[picker pushViewController:psView animated:YES];
imageView = [[UIImageView alloc] initWithImage:image];
imageView.frame = CGRectMake(20, 20, 280, 280);
[imageView setUserInteractionEnabled:YES];
[psView.imageView setUserInteractionEnabled:YES];
[psView.view addSubview:imageView];
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:psView action:#selector(endPS:) forControlEvents:UIControlEventTouchUpInside];
[button setTitle:#"done" forState:UIControlStateNormal];
button.frame = CGRectMake(140.0, 330.0, 80.0, 25.0);
[psView.view addSubview:button];
}
viewControllerB.h (SSViewController.h)
#interface SSViewController : UIViewController
{
IBOutlet UIImageView *imageView;
IBOutlet UIView *view;
}
#property (nonatomic,strong) IBOutlet UIImageView *imageView;
#property (nonatomic,strong) IBOutlet UIImage *image;
#property (nonatomic, strong) IBOutlet UIView *view;
- (IBAction)endPS:(id)sender;
#end
viewControllerB.m (SSViewController.m)
#implementation SSViewController
#synthesize imageView;
#synthesize image;
#synthesize view;
:
:
- (void)viewDidLoad
{
[view setUserInteractionEnabled:YES];
[imageView setUserInteractionEnabled:YES];
:
:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(#"touchesBegan");
:
You're doing a number of things wrong:
Don't push a view controller on to the UIImagePickerController. If you've presented it modally, which I hope you have, you need to dismiss it (in viewControllerA) and push your new view controller (viewControllerB) onto your own navigation controller. The fact that you're pushing onto this highly customised navigation controller is most likely why touchesBegan is not being called.
Why are you manually creating the view for viewControllerB? If you're loading it from a XIB file, it will have a perfectly good view ready for you. And don't define the view property in viewControllerB.h, it's already defined in UIViewController.h.
Don't forget to call [super viewDidLoad] in viewControllerB.m. This is a classic mistake that will cause you many headaches.
EDIT:
What I would personally have done is added a method on viewControllerB as such:
viewControllerB.h
#interface SSViewController : UIViewController
{
- (void)setImage:(UIImage *)image;
}
#end
viewControllerB.m
#implementation SSViewController
{
- (void)setImage:(UIImage *)image
{
// In case the image view already exists, remove it first.
[_imageView removeFromSuperview];
_imageView = [[UIImageView alloc] initWithImage:image];
_imageView.frame = CGRectMake(20, 20, 280, 280);
[self.view addSubview:_imageView];
}
}
#end
This way, in viewControllerA.m you can just create viewControllerB.m and call this setImage: method to let viewControllerB do all the work.

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.

Simple Custom UIView Class Broken

I have made a simple subclass of UIView which has a few subviews but its breaking for a reason I can't see.
In my storyboard view controller I have added a UIView and made it the shape I want it, and added my custom class to it. The contents of my subclass is below:
#implementation PersonDetailCell
#synthesize button, requiredMarker, textField;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
-(void)layoutSubviews
{
[self setBackgroundColor:[UIColor colorWithRed:87.0f/255.0f green:153.0f/255.0f blue:191.0f/255.0f alpha:1.0f]];
textField = [[DetailTextField alloc] initWithFrame:CGRectMake(10, 0, self.frame.size.width -20, self.frame.size.height)];
[textField setFont:[UIFont fontWithName:#"Helvetica" size:14.0f]];
[textField setTextColor:[UIColor whiteColor]];
[textField setHidden:YES];
[self addSubview:textField];
button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
[button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[button setHidden:YES];
[self addSubview:button];
requiredMarker = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 4, 22)];
[requiredMarker setBackgroundColor:[UIColor redColor]];
[requiredMarker setHidden:YES];
[self addSubview:requiredMarker];
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
#end
Then in my view controller code I have imported my subclass and hooked up an IBOutlet of it to my view in my storyboard. In my viewDidLoad of my view controller I also try setting background colour of this view but nothing happens.
All of my code runs without crashing, but my issues:
I can't set the background colour from my view controller, (or any other properties for that matter).
When I run the app, the height is more than that I set in my storyboard (width is fine), but I change the height of the view nowhere.
Any ideas? Am i using the wrong approach somehow?
Thanks.
If it is a table cell, then the class should be extending UITableViewCell. Buttons and textfields can be added on the storyboard - then you can use struts and springs (Size Inspector pane) to ensure the view resizes properly. I don't think layoutSubviews should be used for adding new UI elements (maybe for resizing if you need to do it manually).
Here is some working code:
#interface ChildView()
#property (strong, nonatomic) UITextField *textField;
#property (strong, nonatomic) UIButton *button;
#property (strong, nonatomic) UIImageView *requiredMarker;
#end
#implementation ChildView
#synthesize textField= _textField;
#synthesize button = _button;
#synthesize requiredMarker = _requiredMarker;
-(id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self)
{
[self setBackgroundColor:[UIColor colorWithRed:87.0f/255.0f green:153.0f/255.0f blue:191.0f/255.0f alpha:1.0f]];
self.textField = [[UITextField alloc] init];
[self.textField setFont:[UIFont fontWithName:#"Helvetica" size:14.0f]];
[self.textField setTextColor:[UIColor whiteColor]];
self.textField.text = #"Test text";
[self addSubview:self.textField];
self.button = [[UIButton alloc] init];
self.button.backgroundColor = [UIColor greenColor];
[self addSubview:self.button];
self.requiredMarker = [[UIImageView alloc] init];
[self.requiredMarker setBackgroundColor:[UIColor redColor]];
[self addSubview:self.requiredMarker];
}
return self;
}
-(void)layoutSubviews
{
CGSize hostSize = self.frame.size;
float length = 22;
self.textField.frame = CGRectMake(10, length, hostSize.width, hostSize.height-length);
self.button.frame = CGRectMake(0, 0, hostSize.width, length);
self.requiredMarker.frame = CGRectMake(0, 0, 4, length);
}
#end

1 UIViewController and 2 switching UIViews programmatically

I am bit stack with creating two UIViews which are switchable (each UIView has some of subviews). Since I do not IB, I wanna do that programmatically.
I have tried adding my subviews to my first UIView, then the same with second one and then switching to view like this.
if ([self.setView superview]) {
[self.setView removeFromSuperview];
[self.view addSubview:contentView];
self.navigationItem.title = #"BaseLine";
} else {
[self.contentView removeFromSuperview];
self.view = setView;
self.navigationItem.title = #"Settings";
}
but only thing which works correctly was "title" and nothing appeared on the UIViews. The UIView seems to be OK because when I use
self.view = contentView;
or
self.view = setView;
both showing subviews correctly.
Pls someone kick me to the right direction about this.
tnx
EDIT:
Also pointing the solution, perhaps something wrong with my initialization in the loadView
CGRect screenRect = [[UIScreen mainScreen] applicationFrame];
contentView = [[UIView alloc] initWithFrame:screenRect];
setView = [[UIView alloc] initWithFrame:screenRect];
self.view = contentView;
I tried to add it first [self. view add..] but the app crashed, so I used this
EDIT2
the root controller is UITableViewController..it is in navigation view and after choosing a cell this UIVieController (percView) with two UIVies is allocated
ShakeControl *percView = [[ShakeControl alloc] init];
[self.navigationController pushViewController:percView animated:YES];
[percView release];
EDIT3
switch is done by button, but it is fine done because I used that many times and it worked
Here is an example of a view controller that does what you want (I think). It is very basic, just switching between two views with different color backgrounds. But, you could further customize those subviews in the loadView method to display whatever you need.
The interface file:
#interface SwapViewController : UIViewController {
UIView *firstView;
UIView *secondView;
BOOL displayingFirstView;
UIButton *swapButton;
}
#property (nonatomic, retain) UIView *firstView;
#property (nonatomic, retain) UIView *secondView;
#property (nonatomic, retain) UIButton *swapButton;
- (void)swap;
#end
The implementation file:
#import "SwapViewController.h"
#implementation SwapViewController
#synthesize firstView;
#synthesize secondView;
#synthesize swapButton;
- (void)loadView
{
CGRect frame = [[UIScreen mainScreen] applicationFrame];
UIView *containerView = [[UIView alloc] initWithFrame:frame];
containerView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.view = containerView;
[containerView release];
frame = self.view.bounds;
firstView = [[UIView alloc] initWithFrame:frame];
firstView.backgroundColor = [UIColor redColor];
secondView = [[UIView alloc] initWithFrame:frame];
secondView.backgroundColor = [UIColor blueColor];
self.swapButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
self.swapButton.frame = CGRectMake(10, 10, 100, 50);
[swapButton addTarget:self action:#selector(swap) forControlEvents:UIControlEventTouchUpInside];
displayingFirstView = YES;
[self.view addSubview:firstView];
[self.view addSubview:swapButton];
}
- (void)swap
{
if(displayingFirstView) {
[self.firstView removeFromSuperview];
[self.view addSubview:secondView];
displayingFirstView = NO;
} else {
[self.secondView removeFromSuperview];
[self.view addSubview:firstView];
displayingFirstView = YES;
}
[self.view bringSubviewToFront:self.swapButton];
}
#end
sample code;
BOOL firstview = YES; // First, I have added view1 as a subview;
if (firstview) {
[view1 removeFromSuperview];
[self.view addSubview:view2];
} else {
[view2 removeFromSuperview];
self.view addSubview:view1];
}

Trying to get a UILabel to Show in a View, without a NIB

I'm new to iPhone programming, and I'm trying to make a simple program without a NIB. I have worked through some NIB tutorials, but I'd like to try some things programmatically.
My code loads without errors, makes the status bar black, and makes the background white. But, I don't think I'm loading my view with a label correctly after that. I presume I'm doing something just fundamentally wrong, so if you could point me in the right direction, I'd appreciate it. I think if I can get the label to show, I'll get some understanding. Here's my code:
//helloUAppDelegate.h
#import <UIKit/UIKit.h>
#import "LocalViewController.h"
#interface helloUAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
LocalViewController *localViewController;
}
#property (nonatomic, retain) UIWindow *window;
#property (nonatomic, retain) LocalViewController *localViewController;
#end
//helloUApDelegate.m
#import "helloUAppDelegate.h"
#implementation helloUAppDelegate
#synthesize window, localViewController;
- (void)applicationDidFinishLaunching:(UIApplication *)application {
application.statusBarStyle = UIStatusBarStyleBlackOpaque;
window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
if (!window) {
[self release];
return;
}
window.backgroundColor = [UIColor whiteColor];
localViewController = [[LocalViewController alloc] init];
[window addSubview:localViewController.view];
// Override point for customization after application launch
[window makeKeyAndVisible];
}
//LocalViewController.h
#import <UIKit/UIKit.h>
#interface LocalViewController : UIViewController {
UILabel *myLabel;
}
#property (nonatomic, retain) UILabel *myLabel;
#end
//LocalViewController.m
#import "LocalViewController.h"
#implementation LocalViewController
#synthesize myLabel;
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
self.myLabel = [[UILabel alloc] initWithFrame:CGRectMake(50, 100, 200, 100)];
self.myLabel.text = #"Lorem...";
self.myLabel.textColor = [UIColor redColor];
}
- (void)dealloc {
[super dealloc];
[myLabel release];
}
Add your label to your LocalViewController's view:
- (void)loadView {
[super loadView];
self.myLabel = [[UILabel alloc] initWithFrame:CGRectMake(50, 100, 200, 100)];
self.myLabel.text = #"Lorem...";
self.myLabel.textColor = [UIColor redColor];
[self addSubview:self.myLabel];
[self.myLabel release]; // since it's retained after being added to the view
}