I've seen several apps do this, and i've been wondering how it's done. If you look at the Wunderkit app, when it loads something, there's a blue animated bar that slides down to cover the status bar until it finishes loading. How is this done?
you can subclass UIWindow.
And set it windowLevel = UIWindowLevelStatusBar;
code:
#interface CHLoadingWindow : UIWindow
#implementation CHLoadingWindow
- (id)init
{
self = [super init];
if (self) {
self.windowLevel = UIWindowLevelStatusBar;
// then draw your UI
}
return self;
}
#end
use it:
CHLoadingWindow *loading = [[CHLoadingWindow alloc] init];
[loading makeKeyAndVisible];
discover it:
[loading release];
loading = nil;
[[[[UIApplication sharedApplication] windows] objectAtIndex:0] makeKeyWindow];
Related
I'm having some glitchy bugs when I'm using my menu bar application on a low resolution screen. Please see screenshots below as illustration! Because of the reduced height of the lo-res screen my total NSMenu does not fit in the screen, and so automatically a scrollview appears so i can still get to all the different items.
The problem is that my cutsom NSMenuItems, which thus have custom NSViews with their own draw [drawRect:(NSRect)dirtyRect] method, are behaving glitchy when scrolling down, and back up. It's as if there are some drawing calls missing. I unfortunately do not know how to detect when the NSMenu is effectively scrolling, or simply to access this automagically created scrollview on the NSMenu class...
Any help much appreciated !
the drawing code of my view in my NSMenuItem.
- (void)drawRect:(NSRect)dirtyRect
{
if (self.enabled)
{
if (self.isHighlighted)
{
[self colorRectHighlighted:dirtyRect];
[self drawTextInRect:dirtyRect withState:CustomCheckMenuItemViewStateHiglighted];
[self drawStateIconWithColor:[NSColor whiteColor]];
}
else
{
[self drawTextInRect:dirtyRect withState:CustomCheckMenuItemViewStateNormal];
AppDelegate *appDelegate = (AppDelegate *)[[NSApplication sharedApplication] delegate];
if(appDelegate.menuIsInDarkMode)
{
[self drawStateIconWithColor:[NSColor colorWithWhite:1.0 alpha:0.9]];
}
else
{
[self drawStateIconWithColor:[NSColor selectedMenuItemIndicatorColor:([NSColor currentControlTint]==NSBlueControlTint)?YES:NO]];
}
}
}
else
{
[self drawTextInRect:dirtyRect withState:CustomCheckMenuItemViewStateNormal];
AppDelegate *appDelegate = (AppDelegate *)[[NSApplication sharedApplication] delegate];
if(appDelegate.menuIsInDarkMode)
{
[self drawStateIconWithColor:[NSColor colorWithRed:136/256.0 green:136/256.0 blue:136/256.0 alpha:0.9]];
}
else
{
[self drawStateIconWithColor:[NSColor colorWithWhite:0 alpha:0.1]];
}
}
}
EDIT:
I initialise the NSMenuItems with the sliders as this:
self.tiltSliderViewController = [[SlidingViewController alloc] initWithNibName:#"SlidingViewController" bundle:nil];
self.tiltSliderViewController.delegate = self;
[tiltSliderMenuItem setView:[self.tiltSliderViewController view]];
self.rotationSliderViewController = [[SlidingViewController alloc] initWithNibName:#"SlidingViewController" bundle:nil];
self.rotationSliderViewController.delegate = self;
[rotationSliderMenuItem setView:[self.rotationSliderViewController view]];
The viewcontrollers used here have the following implementation:
#interface SlidingViewController ()
#end
#implementation SlidingViewController
- (IBAction)valueChanged:(id)sender
{
float slider_value = [_slider floatValue];
[_slider setToolTip:[NSString stringWithFormat:#"%ld",
_slider.integerValue]];
[_delegate sliderValueChanged:slider_value sender:self];
}
#end
screenshots:
NORMAL
DOWN
UP AGAIN = GLITCH!!
I am developing multiplayer for my game and I have encountered following issue
I am using Cocos 2d 2.1 , iOS 6 and following code to show matchmaker (Landscape orientation)
AppController *app = (AppController*) [[UIApplication sharedApplication] delegate];
[[GCHelper sharedInstance] findMatchWithMinPlayers:2 maxPlayers:4 viewController:[app navController] delegate:self];
And thats how it appears
Following code is used for that function
- (void)findMatchWithMinPlayers:(int)minPlayers maxPlayers:(int)maxPlayers
viewController:(UIViewController *)viewController
delegate:(id<GCHelperDelegate>)theDelegate {
if (!gameCenterAvailable) return;
matchStarted = NO;
self.match = nil;
self.presentingViewController = viewController;
delegate = theDelegate;
[presentingViewController dismissModalViewControllerAnimated:NO];
GKMatchRequest *request = [[[GKMatchRequest alloc] init] autorelease];
request.minPlayers = minPlayers;
request.maxPlayers = maxPlayers;
GKMatchmakerViewController *mmvc =
[[[GKMatchmakerViewController alloc] initWithMatchRequest:request] autorelease];
mmvc.matchmakerDelegate = self;
[presentingViewController presentViewController:mmvc animated:YES completion:nil];
}
is this code in HelloWorldLayer? if so is that the first layer that the director calls? I have the same problem but it's fixes if I follow strictly the cocos2d template that was created for me. Meaning that I use the IntroLayer as the initial layer and from there it transitions into the HelloWorldLayer where I have the game center code. I think it has something to do with the director being loaded too late but I'm not sure
This happens when you try to push on a UIViewController, but you only have a UIView in your app, and no UIViewController. Let me guess, you do not have a rootViewController.
If you are working from the EAGLView template, you must declare a UIViewController for the UIView. This can be as simple as,
- (void) applicationDidFinishLaunching:(UIApplication *)application
{
window.rootViewController = [[UIViewController alloc] init];
window.rootViewController.view = glView; // MUST SET THIS UP,
// NOW THE EAGLView HAS A UIViewController.
[glView startAnimation];
}
Then, anytime you want to push on one of those GameKit UIViewControllers, use the presentViewController method of your Window object's rootViewController
For example:
[self.window.rootViewController presentViewController:vc animated:TRUE completion:^(void){puts("DONE");} ] ;
The bugginess will go away and the window will be correctly formed.
I am making a game for the iPhone that consists of 4 mini games. Each mini game is a standalone xib. Each game consists of its own menu and the game levels. You go to the main menu and select which game you want to load.
This is how I am currently loading each xib.
MainGameViewController.h
#interface MainGameViewController : UIViewController {
UIViewController *currentView;
int currentViewId;
}
#property (nonatomic, retain) UIViewController *currentView;
- (void)displayView:(int)intNewView;
#end
MainGameViewController.m
#implementation MainGameViewController
#synthesize currentView;
- (void)viewDidLoad {
[super viewDidLoad];
currentView = [[LogoScreen alloc] init];
[self.view addSubview:currentView.view];
}
- (void)displayView :(int)intNewView
{
currentViewId = intNewView;
currentView = nil;
[currentView release];
switch (intNewView) {
case SCR_GAME1:
currentView = [[Game1View alloc] init];
break;
case SCR_GAME1LEVEL:
currentView = [[Game1LevelView alloc] init];
break;
case SCR_GAME2:
currentView = [[Game2View alloc] init];
break;
case SCR_GAME2LEVEL:
currentView = [[Game2LevelView alloc] init];
break;
case SCR_GAME3:
currentView = [[Game3View alloc] init];
break;
case SCR_GAME3LEVEL:
currentView = [[Game3LevelView alloc] init];
break;
case SCR_GAME4:
currentView = [[Game4View alloc] init];
break;
case SCR_GAME4LEVEL:
currentView = [[Game4LevelView alloc] init];
break;
default:
currentView = [[MainView alloc] init];
break;
}
[self.view addSubview:currentView.view];
}
- (void)dealloc {
[currentView release];
currentView = nil;
[super dealloc];
}
#end
And this is how the levels are launched.
Game1View.m
#implementation Game1View
-init {
if (self == [super init]) {
MainGameAppDelegate *appdelegate = [[UIApplication sharedApplication] delegate];
isSoundOn = (appdelegate.gvar.soundstate == 1);
gamestate = GAME_STATUS_START;
}
return self;
}
...
...
- (void)launchgame {
MainGameAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
appDelegate.gvar.currentId = objectid;
[appDelegate displayView:SCR_GAME1LEVEL_GAME];
}
- (void)returnToMain {
MainGameAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
[appDelegate displayView:SCR_MAIN];
}
#end
MainGameAppDelegate.m
#implementation MainGameAppDelegate
#synthesize window;
#synthesize viewController;
- (void) displayView:(int)intNewView {
[viewController displayView:intNewView];
}
#end
Currently I'm getting memory warnings when I keep switching between the views and then the app crashes.
My question is, is this the correct way to load these views? I've released everything that I've allocated for the duration of the game's lifespan and I am now at a loss at what's hogging up the memory. Any help would be much appreciated.
You're not releasing your game views properly, since your code will actually set currentView to nil before calling release, meaning you'll be leaking every game view created.
- (void)displayView :(int)intNewView
{
currentViewId = intNewView;
currentView = nil;
[currentView release];
switch (intNewView) {
You probably want to do this instead:
- (void)displayView :(int)intNewView
{
currentViewId = intNewView;
[currentView release];
currentView = nil;
switch (intNewView) {
Also, you naming your view controllers "View"s is confusing. Consider giving them more descriptive names, like xxxController.
Edit 1:
You also need to make sure the old game is removed from the view hierarchy before you release it. Call [currentView.view removeFromSuperview] before releasing your view to remove it first.
I've a sample project, where I'm creating an custom UIViewController.
#import "ViewController.h"
#implementation ViewController
#synthesize webViews = _webViews;
#synthesize webView = _webView;
- (void)setWebView:(UIWebView *)webView {
if (webView!=_webView) {
[self.webView removeFromSuperview];
_webView = nil;
_webView = webView;
[self.view addSubview:self.webView];
[self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.google.com/"]]];
}
}
- (IBAction)newWebView:(id)sender {
self.webView = [self.webViews objectAtIndex:1];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
UIWebView *webView1 = [[UIWebView alloc] initWithFrame:self.view.bounds];
webView1.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
UIWebView *webView2 = [[UIWebView alloc] initWithFrame:self.view.bounds];
webView2.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.webViews = [NSArray arrayWithObjects: webView1, webView2, nil];
self.webView = [self.webViews objectAtIndex:0];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
#end
Two UIWebView's are created inside the viewWillAppear:animated and stored in an array -- and than the first UIWebView is added to the subview of self.view. When a button in the navigation bar is pressed, the first UIWebView will be removed from the subview and the next one will be added instead.
The problem is, that if I'm running the application in landscape (both iPhone and iPad) after the second UIWebView is added, the WebView is not filling the entire screen. Why?
You can download the small sample project here: http://uploads.demaweb.dk/WebView.zip.
I dont know why but this inside your action method will do the trick...
UIWebView *newWebView=[[UIWebView alloc] init];
newWebView=[self.webViews objectAtIndex:1] ;
newWebView.frame=self.view.frame;
self.webView = newWebView;
hope this helps.. :/
I have an NSDocument subclass with two NSWindowControllers corresponding to 2 different xib.
Following the Document-Based Application Guide I have added the following in my document.m implementation
- (void)makeWindowControllers
{
NSLog(#"in MakeWindowControllers");
MainWindowController *mainWindowController = [[MainWindowController alloc] init];
[mainWindowController autorelease];
[self addWindowController:mainWindowController];
csvWindowController = [[CSVWindowController alloc] init];
[csvWindowController autorelease];
[self addWindowController:csvWindowController];
}
Problem is I want the second window controller csvWindowController to hide its window initially, I will show the same instance of the window later on. To do so I have written:
#implementation CSVWindowController
- (id) init {
if ( ! (self = [super initWithWindowNibName:#"CSVWindow"]) ) {
NSLog(#"CSVWindowController init failed");
return nil;
}
window = [self window];
NSLog(#"CSVWindowController init");
[window orderOut:nil]; // to hide it
NSLog(#"CSVWindowController hiding the window");
return self;
}
But the window is there, showing up.
Please not I have the VisibleAtLaunch not flagged, that console it's showing my messages correctly, and that even if I change:
[window orderOut:nil]; // to hide it
to
[window orderOut:self]; // to hide it
The result is the same, window showing up.
Any help is appreciated, thanks :)
Ok, again I reply to my own question, but this time with a positive remark. I think what I was doing wrong had something to do with the hidden - for me - implications of the Document-based architecture of the default Document Application template.
I have tried with a different approach, creating an application from scratch NOT flagging "Document-based Application" and providing it with:
1 NSDocument subclass
2 NSWindowControllers subclasses
1 MainMenu.xib
2 window.xib
and I have forced instantiation of the NSWindowController subclasses in the MyDocument code.
I have also put the IBActions for the MenuItems in the MyDocument and I have bound the MyDocument Object to the MenuItems in the MainMenu.xib.
This time I was able to do whatever, hiding/showing windows starting with one hidden one not, enabling menu items automatically at will.
Here follows the code, for any newbie like me who might have to fight with this in the future.
// MyDocument.h
#import <Cocoa/Cocoa.h>
#import "testWindowController.h"
#import "test2WindowController.h"
#interface MyDocument : NSDocument {
testWindowController *test;
test2WindowController *test2;
}
- (IBAction)showWindow1:(id)pId;
- (IBAction)showWindow2:(id)pId;
- (IBAction)hideWindow1:(id)pId;
- (IBAction)hideWindow2:(id)pId;
#end
// MyDocument.m
#import "MyDocument.h"
#import "testWindowController.h"
#import "test2WindowController.h"
#implementation MyDocument
- (id)init
{
self = [super init];
if (self) {
// Initialization code here.
NSLog(#"MyDocument init...");
[self makeWindowControllers];
}
return self;
}
- (void)dealloc
{
[super dealloc];
}
- (void)makeWindowControllers
{
test = [[testWindowController alloc] init];
test2 = [[test2WindowController alloc] init];
[self addWindowController:test];
[self addWindowController:test2];
// start hiding the first window
[[test window] orderOut:self];
}
- (IBAction)hideWindow1:(id)pId
{
NSLog(#"hideWindow1");
[[test window] orderOut:self];
}
- (IBAction)showWindow1:(id)pId
{
NSLog(#"showWindow1");
[test showWindow:self];
[[test window] makeKeyAndOrderFront:nil]; // to show it
}
- (IBAction)hideWindow2:(id)pId
{
NSLog(#"hideWindow2");
[[test2 window] orderOut:self];
}
- (IBAction)showWindow2:(id)pId
{
NSLog(#"showWindow2");
[test2 showWindow:self];
[[test2 window] makeKeyAndOrderFront:nil]; // to show it
}
-(BOOL)validateMenuItem:(NSMenuItem *)menuItem {
NSLog(#"in validateMenuItem for item: %#", [menuItem title]);
if ([[menuItem title] isEqualToString:#"Show Window"]
&& [[test window] isVisible]){
return NO;
}
if ([[menuItem title] isEqualToString:#"Hide Window"]
&& ![[test window] isVisible]){
return NO;
}
if ([[menuItem title] isEqualToString:#"Show Window2"]
&& [[test2 window] isVisible]){
return NO;
}
if ([[menuItem title] isEqualToString:#"Hide Window2"]
&& ![[test2 window] isVisible]){
return NO;
}
return [super validateMenuItem:menuItem];
}
This is another method to prevent NSDocument's window(s) to show up early:
Subclass NSDocuments's window in IB
Use a flag to signal when window content is ready
Override makeKeyAndOrderFront method.
#interface DocWindow : NSWindow
#property BOOL inited;
#end
#implementation DocWindow
- (void)makeKeyAndOrderFront:(id)sender
{
if ( _inited )
[super makeKeyAndOrderFront:sender];
}
#end
#implementation Document
- (void)windowControllerDidLoadNib:(NSWindowController *)windowController
{
// prepare window content here.
...
// show doc's window when ready
DocWindow *win = (DocWindow *)self.window;
win.inited = YES;
[win makeKeyAndOrderFront:self];
}
#end