resize the Hosting View through addSubview in Core-Plot in XCode 4 - iphone

I'm running into a wall trying to resize the Hosting View. The problem is I either get a full-screen plot or a blank screen. I'm hoping to get some leads to fix this problem:
I'm using Xcode 4 | IOS 4.3 | Recently downloaded core plot using hg:
I have two xib files (MainWindow & my ViewController)
My ViewController.xib file contains two objects: a View and Hosting View both at the same level:
+-View
+-Graph Hosting View
I get no erros in my code, but all I get a blank screen. I've searched for 3 days how to get around this problem, but haven't found something that works.
My xAppDelegate.h
#import <UIKit/UIKit.h>
#class CorePlotTestViewController;
#interface CorePlotTestAppDelegate : NSObject <UIApplicationDelegate> {
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet CorePlotTestViewController *viewController;
#end
My ViewController.h
#import <UIKit/UIKit.h>
#import "CorePlot-CocoaTouch.h"
#interface CorePlotTestViewController : UIViewController <CPTPlotDataSource>
{
CPTXYGraph *graph;
NSMutableArray *dataForPlot;
CPTGraphHostingView *graphView;
}
#property(readwrite, retain, nonatomic) NSMutableArray *dataForPlot;
#property(nonatomic, retain)IBOutlet CPTGraphHostingView* graphView;
My ViewController.m
#import "CorePlotTestViewController.h"
#interface CorePlotTestViewController(private)
- (void) configureTableHeader;
#end
#implementation CorePlotTestViewController
#synthesize dataForPlot;
#synthesize graphView;
-(void)dealloc
{
[dataForPlot release];
[super dealloc];
}
- (void)viewDidLoad {
[super viewDidLoad];
[self configureTableHeader];
}
- (void) configureTableHeader
{
// here I implement the contents of the Hosting View
graph = [[CPTXYGraph alloc] initWithFrame: CGRectZero];
CPTGraphHostingView *hostingView = [(CPTGraphHostingView *)[CPTGraphHostingView alloc]
initWithFrame:CGRectZero];
[self.view addSubview:hostingView];
...
// etc
...
}

In your code, you initialize the hosting view using a CGRectZero frame, which is basically a frame with an origin at (0,0) and both a width and a height of 0 px. It is the reason why you don't see the graph at all when you run your project.
If you gave a custom size and location to the hosting view in Interface Builder, it is overridden by this code.
By the way, I'm not sure why you want to add the hosting view to the controller's view in the code. You just need to layout both components using Interface Builder, giving the hosting view the size and the location you want it to have.
Last thing : why do you add a 'T' to Core-Plot class names ? CPTPlotDataSource should simply be CPPlotDataSource; CPTXYGraph: CPXYGraph; etc.

Related

How to add a popup UIView (of a customized class) on a UIViewController

I'm new on this, and I would like to get some advice because I don't know what I'm doing wrong.
I want to make an app in xcode, with a UIView with some items, and when you do something, another UIView (smaller than the first) pops up above the first UIView. The popup UIView would be a customized class.
I have started with the UIViewController template and the initial UIView, and I have linked all the items in the .storyboard, and it works. But when I create my own UIView class (from objective-C class), put the second UIView over the first in the storyboard and link it to my class, something goes wrong.
The UIView appears, but when I try to set it to hidden, it doesn't answer. It's like it's not receiving the messages, so I think I don't link it well programmatically and just appears because of the storyboard.
I don't know if I have to create another UIViewController instead of the UIView, or if this is the correct path.
Can anybody explain me a little, or just write a little code snippet with the instantiation of the second view and adding it?
Lots of thanks!!
(I paste some code, of the declaration in .h and instantiation in .m)
#import <UIKit/UIKit.h>
#import "EditView.h"
#interface ReleaseViewController : UIViewController <UIWebViewDelegate, UISearchBarDelegate> {
IBOutlet UIWebView *web;
IBOutlet UISearchBar *search;
IBOutlet EditView *evHack;
}
#property (nonatomic, retain) IBOutlet UIWebView *web;
#property (nonatomic, retain) IBOutlet UISearchBar *search;
#property (nonatomic, retain) IBOutlet EditView *evHack;
#end
- (void)viewDidLoad
{
[super viewDidLoad];
search.delegate = self;
web.delegate = self;
evHack = [evHack initWithFrame:CGRectMake(0, 44, 320, 377)];
[evHack setHidden:YES];
}
EditView Class (I still have nothing):
#import <UIKit/UIKit.h>
#interface EditView : UIView
#end
#import "EditView.h"
#implementation EditView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
NSLog(#"View created");
}
return self;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
#end
initWithFrame only works when you alloc/init an app. If its already initialized, in this case by the storyboard, just set its frame:
evHack.frame = CGRectMake(0,44, 320, 377);
I don't know what it looks like in IB, But setting its frame in code may be redundant if you set it in IB too. To check whether evHack is hooked up right, NSLog evHack in viewDidLoad. If you get nil back, it's not hooked up right.

Custom UINavigationController with button

I would like the NavigationBar to behave the same but would like to change the appearance of it. I've found so many ways of doing this online but I'm not sure which one is the best result for iOS 5.0. The navigation bar will look like this:
Since you are targeting iOS 5 i would definitely go for customizing UINavigationBar using the Appearance proxy. Then you can easily set your own images and they will apply to all navigation bars in your application without subclassing.
You can also customize the buttons in the navigation bar by customizing UIBarButtonItem. There are method like backButtonBackgroundImageForState:barMetrics: for the back button and backgroundImageForState:barMetrics: for the other buttons.
I had been looking for this thing for ages, too, without finding a straightforward solution! Thanks to an friend of mine, and sample codes, we made it with a custom navigation bar class that can be imported into any view controller class.
The .h file:
#import <UIKit/UIKit.h>
#interface NATitleBar : UIView {
NSInteger tag;
}
#property ( nonatomic) IBOutlet UIImageView *imageView;
#property ( nonatomic) IBOutlet UILabel *label;
#property ( nonatomic) IBOutlet UIButton *back;
#property ( nonatomic) IBOutlet UIButton *home;
/**
* Supports UIButton-style adding targets
*/
#end
The .m file:
#import "NATitleBar.h"
#implementation NATitleBar
#synthesize imageView;
#synthesize label;
#synthesize back;
#synthesize home;
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
NSArray *views = [[NSBundle mainBundle] loadNibNamed:#"NATitleBar" owner:self options:nil];
[self addSubview:[views objectAtIndex:0]];
// customize the view a bit
//self.imageView.layer.borderWidth = 1.0;
//self.imageView.layer.borderColor = [UIColor colorWithWhite:0.4 alpha:0.4].CGColor;
//self.imageView.clipsToBounds = YES;
//self.imageView.layer.cornerRadius = 5.0;
}
return self;
}
#pragma mark - Overriden Setters / Getters
- (void)setTag:(NSInteger)aTag {
self.back.tag = aTag;
}
- (NSInteger)tag {
return self.back.tag;
}
#end
and then for the Nib file we have the following:
You can add or delete images in the Nib file to make the GUI as you wish.
Now you must import the class into any view controller you wish to have with custom navigation controller, and also define two methods (or one, if you don't want the 'home' button. in .h :
- (void) back;
in .m:
- (void)back {
[self.navigationController popViewControllerAnimated:YES];
}

Subclassed? UITabBarController wont autorotate

Noobie so bear with me.
I've have been following the O'Rielyy Learning iPhone Programming and various threads on here to build my first iPhone App. So far so good, but the final stumbling block at the projects end is getting the App to autorotate (the beta using only uiwebviews was rejected for not auto-rotating)
I have the mail App delegate, which adds a UITabBarController
// myNewsUKDelegate.h
#interface myNewsUKDelegate : NSObject <UIApplicationDelegate, UITabBarControllerDelegate> {
UIWindow *window;
UITabBarController *tabBarController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;
#end
// myNewsUKDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Add the tab bar controller's view to the window and display.
[self.window addSubview:tabBarController.view];
[self.window makeKeyAndVisible];
return YES;
}
There is are .h and .m files for tabBarController - I added all the UINavigationControllers in IB, which in turn add a UITableView
See image at http://flatearth.co.uk/nib.png (too noob to post images in questions!)
From my reading I understand that the issue is the UITabBarController I added to the main view needs to be 'subclassed' and have this code added.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
The next view down/in/subclassed (whatever the correct terminology is), which has .h and .m files is the FirstViewController which adds the table view, this has shouldAutorotateToInterfaceOrientation already set.
#interface FirstViewController : UIViewController <UITableViewDataSource, UITableViewDelegate> {
UITableView *tableView;
NSArray *userList;
}
#property (nonatomic, retain) IBOutlet UITableView *tableView;
#property (nonatomic, retain) NSArray *userList;
#end
#implementation FirstViewController
#synthesize tableView;
- (void)viewDidLoad {
[super viewDidLoad];
// I tried adding
self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
// lots of other code ; )
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
So the problem appears to be that when [self.window addSubview:tabBarController.view]; adds the tab bar it doesn't add the shouldAutorotateToInterfaceOrientation returning YES bit.
It appears that I need to add a tabBarController subclass, with the shouldAutorotateToInterfaceOrientation in it. So I read up and tried this, as suggested on the interwebs...
// tabBarController.h
#import <UIKit/UIKit.h>
#interface tabBarController : UITabBarController {
}
#end
// tabBarController.m
#import "tabBarController.h"
#implementation tabBarController
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
#end
and adding
#import "tabBarController.h"
to myNewsUKDelegate.m
But that fails with "error: accessing unknown 'view' class method" at the
[self.window addSubview:tabBarController.view];
line in myNewsUKDelegate.m
Further searching hasn't produced anything helpful and my recent Xcode knowledge has now ran dry : ( Any help appreciated.
From my reading I understand that the issue is the UITabBarController I added to the main view needs to be 'subclassed' and have this code added.
No, you don't need to do that. The tab bar controller determines if it supports a specific interface orientation or not by asking all its child controllers if they support this orientation. In your case, these seem to be navigation controllers, which in turn ask their current child controller if it supports the orientation.
In other words, you have to make sure that all your custom view controllers return YES for the desired interface orientation.
You don't need a subclass, you need a Category on UITabBarController. Basically you create a file called UITabBarController + Autoresize.h (and .m)
In the .h:
#import <UIKit/UIKit.h>
#interface UITabBarController (Autoresize)
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation;
#end
in the .m:
#import "UITabBarController + Autoresize.h"
#implementation UITabBarController (Autoresize)
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
//do custom checks here if you only want to autorotate it in certain views or whatever
}
#end
but as the other poster pointed out, ALL the parent views of the view you wish to rotate must support rotation.

How do I add a custom view to iPhone app's UI?

I'm diving into iPad development and I'm still learning how everything works together. I understand how to add standard view (i.e. buttons, tableviews, datepicker, etc.) to my UI using both Xcode and Interface Builder, but now I'm trying to add a custom calendar control (TapkuLibrary) to the left window in my UISplitView application which doesn't involve Interface Builder, right? So if I have a custom view (in this case, the TKCalendarMonthView), how do I programmatically add it to one of the views in my UI (in this case, the RootViewController)? Below are some relevant code snippets from my project...
RootViewController interface
#interface RootViewController : UITableViewController <NSFetchedResultsControllerDelegate> {
DetailViewController *detailViewController;
NSFetchedResultsController *fetchedResultsController;
NSManagedObjectContext *managedObjectContext;
}
#property (nonatomic, retain) IBOutlet DetailViewController *detailViewController;
#property (nonatomic, retain) NSFetchedResultsController *fetchedResultsController;
#property (nonatomic, retain) NSManagedObjectContext *managedObjectContext;
- (void)insertNewObject:(id)sender;
TKCalendarMonthView interface
#class TKMonthGridView,TKCalendarDayView;
#protocol TKCalendarMonthViewDelegate, TKCalendarMonthViewDataSource;
#interface TKCalendarMonthView : UIView {
id <TKCalendarMonthViewDelegate> delegate;
id <TKCalendarMonthViewDataSource> dataSource;
NSDate *currentMonth;
NSDate *selectedMonth;
NSMutableArray *deck;
UIButton *left;
NSString *monthYear;
UIButton *right;
UIImageView *shadow;
UIScrollView *scrollView;
}
#property (readonly,nonatomic) NSString *monthYear;
#property (readonly,nonatomic) NSDate *monthDate;
#property (assign,nonatomic) id <TKCalendarMonthViewDataSource> dataSource;
#property (assign,nonatomic) id <TKCalendarMonthViewDelegate> delegate;
- (id) init;
- (void) reload;
- (void) selectDate:(NSDate *)date;
Thanks in advance for all your help! I still have a ton to learn, so I apologize if the question is absurd in any way. I'm going to continue researching this question right now!
Assuming you have initialized the custom UIView, you need to add it as a subview of the viewController's view.
- (void)addSubview:(UIView *)view
So an example would be if you have a plain viewController called myVC, which has simply a blank white UIView as its view, you would say this:
CGRect customViewsFrame = CGRectMake(10, 30, 5, 2);
MyCustomView *myView = [[MyCustomView alloc] initWithFrame:customViewsFrame];
[[myVC view] addSubview:myView];
[myView release]; //Since you called "alloc" on this, you have to release it too
Then it will show up in the viewController's view, taking up the space indicated by the CGRect.
The CGRect's coordinates specify a location in the local coordinate system of the superview you are adding to, if I'm not mistaken.
CGRect CGRectMake (CGFloat x, CGFloat y, CGFloat width, CGFloat height);
I'm not booted into Mac OS X so I can't verify this completely, but this is your general pattern:
RootViewController.h:
...
#interface RootViewController : UITableViewController <NSFetchedResultsControllerDelegate>
{
...
TKCalendarMonthView* calendarView;
...
}
...
#property (nonatomic, retain) TKCalendarMonthView* calendarView;
...
RootViewController.m:
...
#synthesize calendarView;
...
- (void)dealloc
{
...
[calendarView release];
...
}
...
- (void)viewDidLoad
{
...
TKCalendarMonthView* aCalendarView = [[TKCalendarMonthView alloc] init]; // <-- possibly initWithFrame here
self.calendarView = aCalendarView;
[aCalendarView release];
[self addSubview:self.calendarView];
...
}

iPhone MVC. Need some help with understanding how to correctly pass data from Controller to View

A little background:
I'm a C# developer starting to mess with the iPhone (have an idea for a simple 2D game). The only MVC programming I've done was for the web (ASP.NET MVC) so although I do have an understanding in MVC, I can't wrap my mind around one thing. Here's an example to illustrate.
Say I have a simple app where all I want to do is display a big circle on the screen. I created a "View Based Application" and it gave me the basic classes to start with:
MVCConfusionAppDelegate
MVCConfusionViewController
Now since I'll be doing some custom drawing (I know I can add a subview and show the circle that way, but this is just a sample of a larger piece) I've added a class called MyCustomView and in Interface Builder set the View of the MVCConfusionViewController to be a MyCustomView.
Now here's the problem. I want to be able to set in code the size of how big the ball on the custom view should be. So I have a property on the MyCusomView like this:
#import <Foundation/Foundation.h>
#interface MyCustomView : UIView {
NSNumber *ballSize;
}
#property(nonatomic,retain)IBOutlet NSNumber *ballSize;
#end
#import "MyCustomView.h"
#implementation MyCustomView
#synthesize ballSize;
-(void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
[[UIColor redColor]set];
float floatValue = [self.ballSize floatValue];
CGRect ballRect = CGRectMake(50.0f, 50.0f,floatValue , floatValue);
CGContextFillEllipseInRect(context, ballRect);
}
#end
Then, here's my MVCConfusionViewController:
#import <UIKit/UIKit.h>
#import "MyCustomView.h"
#interface MVCConfusionViewController : UIViewController {
NSNumber *ballSize;
}
#property(nonatomic,retain)IBOutlet NSNumber *ballSize;
#end
#import "MVCConfusionViewController.h"
#import "MyCustomView.h"
#implementation MVCConfusionViewController
#synthesize ballSize;
- (void)viewDidLoad {
[super viewDidLoad];
MyCustomView *myView = (MyCustomView *)self.view;
myView.ballSize = self.ballSize;
}
And finally, the MVCConfusionAppDelegate:
#import <UIKit/UIKit.h>
#class MVCConfusionViewController;
#interface MVCConfusionAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
MVCConfusionViewController *viewController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet MVCConfusionViewController *viewController;
#end
#import "MVCConfusionAppDelegate.h"
#import "MVCConfusionViewController.h"
#import "MyCustomView.h"
#implementation MVCConfusionAppDelegate
#synthesize window;
#synthesize viewController;
- (void)applicationDidFinishLaunching:(UIApplication *)application {
viewController.ballSize = [NSNumber numberWithInt:200];
[window addSubview:viewController.view];
[window makeKeyAndVisible];
}
- (void)dealloc {
[viewController release];
[window release];
[super dealloc];
}
#end
As you can see, there's an ugly cast in my viewDidLoad method. I was hoping I'd be able to make the connection of the ballSize properties in IB, but it won't let me.
So my question simply is, what's the correct way of passing this data from my view controller to my view without doing that cast? I know I'm missing something fundamental, but I just don't see it. Any help would be greatly appreciated!
EDIT: Here's the source code. http://bit.ly/uKyp9 Maybe someone can have a look and see if I'm doing anything wrong.
Are you trying to connect one IBOutlet (in the controller) to another IBOutlet (in the view)? Unfortunately, I don't think it's that easy :-)
You're also storing the data (ballSize) in the controller and the view.
I'd make MVCConfusionViewController a data source for MyCustomView, and then let MyCustomView ask its datasource for the ballSize, inside the -drawRect: method.
#class MyCustomView;
#protocol MyCustomViewDataSource
- (NSNumber *)ballSizeForMyCustomView:(MyCustomView *)view;
#end
#interface MyCustomView {
id<MyCustomViewDataSource> dataSource;
}
#property (nonatomic, assign) IBOutlet id<MyCustomViewDataSource> dataSource;
#end
#implementation MyCustomView
- (void)drawRect:(CGRect) rect {
if (self.dataSource == nil) {
// no data source, so we don't know what to draw
return;
}
float floatValue = [[self.dataSource ballSizeForMyCustomView:self] floatValue];
// ...
}
#end
In Interface Builder, hook MVCConfusionViewController up to the view's dataSource property. Then implement the protocol:
#interface MVCConfusionViewController : UIViewController <MyCustomViewDataSource> {
[...]
}
[...]
#end
#implementation MVCConfusionViewController
- (NSNumber *)ballSizeForMyCustomView:(MyCustomView *)view {
return self.ballSize;
}
#end
This way your view controller could also be the data source for multiple MyCustomViews, because the protocol method takes a MyCustomView as an argument.
If you need more than one ball, have a look at the UITableViewDataSource and implement similar methods, something like:
-(NSInteger)numberOfBallsInMyCustomView:(MyCustomView *)view;
-(NSNumber *)myCustomView:(MyCustomView *) ballSizeAtIndex:(NSInteger)index;
Your view should already be set in IB, so you can use it as is. If you want to use MyCustomView, you can do it like this:
- (void)viewDidLoad {
[super viewDidLoad];
CGRect frame = CGRectMake(0, 0, 320, 480);
MyCustomView *myView = [[MyCustomView alloc] initWithFrame:frame];
myView.backgroundColor = [UIColor greenColor];
self.view = myView;
[myView release];
CGRect rectangle = CGRectMake(20, 20, 20, 20);
[self.view drawRect:rectangle];
}
I couldn't make your drawing code work, I don't know much about that.
One way to avoid the cast would be to add a separate outlet property for the custom view on the controller, and refer to that instead.
In Interface Builder, make an instance of MyCustomView and drag it into the existing view to make it a subview, then attach it to its own outlet on the controller.