Displaying a Custom UIView on Springboard (Jailbreak) - objective-c

I created a custom UIView programmatically. Does anyone know what class and what method I would use to display this on the springboard? I want my UIView to display on the springboard, and when a user opens an app I want it to show up there too. I have been searching through the private headers for some time and I can't seem to find what I'm looking for. I am developing a jailbreak tweak with iosopendev. Also could you tell me if the class is a viewcontroller or just a view?

If you want the UIView to show anywhere (on SpringBoard and in apps), you should create a new UIWindow above the others and show your view in it like this :
UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
window.windowLevel = UIWindowLevelAlert + 2;
[window setHidden:NO];
[window setAlpha:1.0];
[window setBackgroundColor:[UIColor clearColor]];
[window addSubview:yourView];

You can hook some methods of SpringBoard such as :
- (void)applicationDidFinishLaunching:(id)arg1
And then, your code should be like this :
- (void)applicationDidFinishLaunching:(id)arg1
{
%orig;
NSLog(#"----- applicationDidFinishLaunching -----");
UIWindow *_uiwindow = [[UIWindow alloc] initWithFrame:CGRectMake(100,100,120,100)];
_uiwindow.windowLevel = UIWindowLevelStatusBar;
_uiwindow.hidden = NO;
[_uiwindow setBackgroundColor:[UIColor redColor]];
}
To add more custom views,just add subview to _uiwindow. Hope that will help you.

Related

Executing ViewController's methods from UINavigationController

I have created several ViewControllers in a storyboard that each have their own class files. In AppDelegate I have programatically generated a UINavigationController that exists at the top of the app for every page. This will have two buttons that will be the same for every ViewController, one will load a ViewController called 'settings' and one will fire a method that reveals a side menu.
Screen shots to illustrate:
Currently, each ViewController has a button in the top left, that when pressed moves the current ViewController across revealing the menu below.
This works fine but what I want is for this button to be removed and replaced with the button that is on the NavigationController (currently place holder menu button seen in the purple NavigationController).
How do I implement the code that moves the ViewController in the AppDelegate, what the UINavigationController is generated?
AppDelegate.m
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
MainViewController* mainVC = [mainStoryboard instantiateInitialViewController];
UINavigationController *navVC = [[UINavigationController alloc] initWithRootViewController:mainVC];
[mainVC setTitle:#"Congress app"];
UIBarButtonItem *showSettingsButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:#selector(showSettings:)];
UIBarButtonItem *showMenuButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"menuButton.png"] style:UIBarButtonItemStylePlain target:self action:#selector(revealMenu:)];
mainVC.navigationItem.leftBarButtonItem = showMenuButton;
mainVC.navigationItem.rightBarButtonItem = showSettingsButton;
[self.window setRootViewController:navVC];
[_window makeKeyAndVisible];
return YES;
}
- (IBAction)revealMenu:(id)sender
{
// This obviously won't work but what should go here instead?
// Something like get instance of MainViewController and fire it's reveal menu
// method but passing the current ViewController Id and running slidingViewController anchorTopViewTo:ECRight on that?
[self.slidingViewController anchorTopViewTo:ECRight];
}
MainViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.layer.shadowOpacity = 0.75f;
self.view.layer.shadowRadius = 10.0f;
self.view.layer.shadowColor = [UIColor blackColor].CGColor;
if (![self.slidingViewController.underLeftViewController isKindOfClass:[MenuViewController class]]) {
self.slidingViewController.underLeftViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"MenuVC"];
}
[self.view addGestureRecognizer:self.slidingViewController.panGesture];
self.menuBtn = [UIButton buttonWithType:UIButtonTypeCustom];
_menuBtn.frame = CGRectMake(8, 80, 34, 24);
[_menuBtn setBackgroundImage:[UIImage imageNamed:#"menuButton.png"] forState:UIControlStateNormal];
[_menuBtn addTarget:self action:#selector(revealMenu:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.menuBtn];
NSLog(#"MainVC loaded");
}
- (IBAction)revealMenu:(id)sender
{
[self.slidingViewController anchorTopViewTo:ECRight];
}
You're better off not doing that...
This isn't app delegate responsibility
There are 3rd party implementations on github / CocoaControls which offer this and manage the navigation bar
It is much better to rework your current view hierarchy than to force a connection from the app delegate.
The responsibility of the app delegate is to respond to app level events (like foreground / background notifications). It might be involved in setting up the initial UI but other than that is should do basically nothing.

Initiate self.window in appDelegate init method

I'm a web developer creating an Apache Cordova application so my knowledge with Objective-C is very little. Everything is going fine until i try to supplement the splash screen with a video. It sort of does it, but not fully.. It starts with displaying the Default.png followed by the SplashScreenLoader. It then actually plays the video and I know this because the audio is emitted, but the video layer isn't shown.
What I've found out is that the self.window or self.viewController are both defined in didFinishLaunchingWithOptions, so they don't exist in the - (id) init method. Therefore I can't find a way to place it on top of the loading splash.
My init method currently looks like this in AppDelegate.m:
- (id) init {
NSString *moviePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"Splash_v1.mp4"];
NSURL *movieURL = [NSURL fileURLWithPath:moviePath];
MPMoviePlayerController* moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL: movieURL];
moviePlayer.controlStyle = MPMovieControlStyleNone;
[moviePlayer.view setFrame: self.window.bounds];
[self.window addSubview:moviePlayer.view];
[self.window makeKeyAndVisible];
[moviePlayer play];
NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
[cookieStorage setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways];
[CDVURLProtocol registerURLProtocol];
return [super init];
}
Here the self.window is null, and I've also attempted to set the self.window with this code:
CGRect screenBounds = [[UIScreen mainScreen] bounds];
self.window = [[[UIWindow alloc] initWithFrame:screenBounds] autorelease];
...without prevail. It actually sets it, but for the subsequent code it doesn't wanna do it.
So what I'm wondering is, how would I place this video on top of the splash's content, before didFinishLaunchingWithOptions kicks in?
Thanks in advance,
//Peter
So what I'm wondering is, how would I place this video on top of the splash's content, before didFinishLaunchingWithOptions kicks in?
actually, you do that in didFinishLaunchingWithOptions. put this statements in there (in the bolierplate code that Xcode generates for you, you should already have a call to makeKeyAndVisible, so just complement it):
[self.window addSubview:moviePlayer.view];
[self.window makeKeyAndVisible];
having previously instantiated your moviePlayer.
One way to avoid the blank screen could be this:
create a UIImageView containing your Default.png image;
display such UIImageView by adding it to your self.window as a subview (this will create no black screen effect);
initialize your player (I assume it takes some time, hence the black screen) and add it below the UIImageView;
when the player is ready (viewDidLoad) push it on top of the UIImageView.
Finally, I don't know how your player will signal the end of the video play, but I assume you have some delegate method; make you appDelegate be also your player delegate and from there, remove UIImageView and player from self.window and add you other view to self.window.
Hope this helps.
EDIT:
This is a rough sketch of what I would try and do in your app delegate appDidFinishLaunching:
self.moviePlayer = <INIT MOVIEW PLAYER CONTROLLER>
self.backgroundImage = <INIT UIImageView with Default.png>
[self.window addSubview:self.moviePlayer.view];
[self.window addSubview:self.backgroundImage];
[self.window makeKeyAndVisible];
In your movie Player viewDidLoad:
- (void)viewDidLoad {
[super viewDidLoad];
...
[self.view.superview addSubview:self.view]; //-- this will just move the player view to the top
...
}
If that helps anyone else, I had the same issue which was resolved by moving '[self.window makeKeyAndVisible];' above the subview like this, so in appdelegate.m:
UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 300)];
myView.backgroundColor = [UIColor blueColor];
[self.window makeKeyAndVisible];
[self.window addSubview:myView];
This works fine, but if I swap the last two statements around, the subview does not display.

UIWebview scrollsToTop not working when a UIScrollview is present as subview

I'm having an issue with setScrollsToTop: on UIWebView. the webview is a subview of the root view controller and on viewDidLoad I set:
[self.webView.scrollView setScrollsToTop:YES];
However when I then tap the status bar the webview won't scroll to the top. On another modal tableViewController inside the app it works fine, without even setting setScrollsToTop:YES. This is the code in applicationDidFinishLaunching inside the app delegate:
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.f = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
self.window.rootViewController = self.f;
[self.window makeKeyAndVisible];
return YES;
How can I make it work?
EDIT: It seems like a UIScrollview that is in the same view is causing the problem. How can I make it work with the UIScrollView?
Try setting setScrollsToTop:NO on the UIScrollView.
According to the docs on setScrollsToTop: in UIScrollView,
This gesture works on a single visible scroll view; if there are
multiple scroll views (for example, a date picker) with this property
set, or if the delegate returns NO in scrollViewShouldScrollToTop:,
UIScrollView ignores the request.
use the answer here: UIScrollView + UIWebView = NO scrollsToTop
worked for me like a charm.
i had a UIScrollView with a UIWebView embedded.
Maybe those code will solve you problem if I get the problem.
self.automaticallyAdjustsScrollViewInsets = NO;
CGSize containerSize = self.view.frame.size;
self.webView.frame = CGRectMake(0, 64, containerSize.wdith, containerSize.height - 65);
Sometime the self.automaticallyAdjestsScrollViewInsets is not wokring as usual. So, just turn off it.

ModalViewController for Single Subview

Ok, so bear with me: as this is an Objective-C related question, there's obviously a lot of code and subclassing. So here's my issue. Right now, I've got an iPad app that programmatically creates a button and two colored UIViews. These colored UIViews are controlled by SubViewControllers, and the entire thing is in a UIView controlled by a MainViewController. (i.e. MainViewController = [UIButton, SubViewController, SubViewController])
Now, all of this happens as it should, and I end up with what I expect (below):
However, when I click the button, and the console shows "flipSubView1", nothing happens. No modal view gets shown, and no errors occur. Just nothing. What I expect is that either subView1 or the entire view will flip horizontally and show subView3. Is there some code that I'm missing that would cause that to happen / is there some bug that I'm overlooking?
viewtoolsAppDelegate.m
#implementation viewtoolsAppDelegate
#synthesize window = _window;
#synthesize mvc;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
mvc = [[MainViewController alloc] initWithFrame:self.window.frame];
[self.window addSubview:mvc.theView];
[self.window makeKeyAndVisible];
return YES;
}
MainViewController.m
#implementation MainViewController
#synthesize theView;
#synthesize subView1, subView2, subView3;
- (id)initWithFrame:(CGRect) frame
{
theView = [[UIView alloc] initWithFrame:frame];
CGRect sV1Rect = CGRectMake(frame.origin.x+44, frame.origin.y, frame.size.width-44, frame.size.height/2);
CGRect sV2Rect = CGRectMake(frame.origin.x+44, frame.origin.y+frame.size.height/2, frame.size.width-44, frame.size.height/2);
subView1 = [[SubViewController alloc] initWithFrame:sV1Rect andColor:[UIColor blueColor]];
subView2 = [[SubViewController alloc] initWithFrame:sV2Rect andColor:[UIColor greenColor]];
subView3 = [[SubViewController alloc] initWithFrame:sV1Rect andColor:[UIColor redColor]];
[theView addSubview:subView1.theView];
[theView addSubview:subView2.theView];
UIButton *aButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[aButton addTarget:self action:#selector(flipSubView1:) forControlEvents:(UIControlEvents)UIControlEventTouchDown];
[aButton setFrame:CGRectMake(0, 0, 44, frame.size.height)];
[theView addSubview:aButton];
return self;
}
- (void)flipSubView1:(id) sender
{
NSLog(#"flipSubView1");
[subView3 setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal];
[subView1 presentModalViewController:subView3 animated:YES];
}
SubViewController.m
#implementation SubViewController
#synthesize theView;
- (id)initWithFrame:(CGRect)frame andColor:(UIColor *)color
{
theView = [[UIView alloc] initWithFrame:frame];
theView.backgroundColor = color;
return self;
}
TLDR: modal view not working. should see flip. don't.
It doesn't look like you're setting the 'view' property of the MainViewController anywhere, just 'theView'. The controllers view delegate must be connected to the root view it displays for it to work properly. You'll need to correct that on the Sub View Controller impl as well. If you want all the plumbing that framework classes bring, you have to set things up the way they expect.
Also, you're calling presentModalViewController on one of the sub view controllers; change that to call [self presentModalViewController:...], since the MainViewController is the one which will 'own' the modal view.
I think if you fix those points, you'll find -presentModalViewController will work.

Second UIWindow Not Displaying (iPad)

I am attempting to create two UIWindows because I would like two UINavigationControllers on screen at the same time on my app. I initialize two windows in my app delegate but only one window's view is displayed. Does anyone know why this is so?
Here is the code I used:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UIViewController * controller1 = [[UIViewController alloc] init];
[controller1.view setBackgroundColor:[UIColor grayColor]];
UINavigationController * nav1 = [[UINavigationController alloc] initWithRootViewController:controller1];
[window addSubview:nav1.view];
[window makeKeyAndVisible];
UIWindow * window2 = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
UIViewController * controller2 = [[UIViewController alloc] init];
[controller2.view setBackgroundColor:[UIColor yellowColor]];
UINavigationController * nav2 = [[UINavigationController alloc] initWithRootViewController:controller2];
[window2 addSubview:nav2.view];
[window2 makeKeyAndVisible];
NSLog(#"%#", [[UIApplication sharedApplication] windows]);
return YES;
}
The gray from the first window is visible, but the yellow from the second is not. The output from this is:
"<UIWindow: 0x591e650; frame = (0 0; 768 1024); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x591e7a0>>",
"<UIWindow: 0x5923920; frame = (0 0; 100 100); layer = <CALayer: 0x59239a0>>"
which means the second window is created and added to the application, but just not displayed. Does anyone know why this is so?
Thanks in advance!
The two UIWindow's windowLevel property is equal, they are all UIWindowLevelNormal.
If you want the second UIWindow display font of the first UIWindow, You should set the second UIWindow's windowLevel value bigger. Like:
window2.windowLevel = UIWindowLevelNormal + 1;
PS:
[window makeKeyAndVisible];
...
[window2 makeKeyAndVisible];
There is only one keyWindow at a time, The key window is the one that is designated to receive keyboard and other non-touch related events. Only one window at a time may be the key window.
Just use a UISplitViewController.
Or try MGSplitVIewController if you need to customization. It might have what you need.
I've discovered how to get the second UIWindow to display. You must set the clipsToBound property to YES. Otherwise, the view from one of the windows will completely cover the other view. The two windows were properly added and visible after all.
This might be a really old post but I just run into the same problem. Some coding mistakes where already answered but the main issue we have here is how you instantiating the UIWindow.
Here is a Swift example how to display another UIWindow correctly.
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow? = UIWindow(frame: UIScreen.mainScreen().bounds)
let newWindow = UIWindow(frame: UIScreen.mainScreen().bounds)
// save a reference to your Window so it won't be released by ARC
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
self.window!.rootViewController = SomeViewController()
self.window!.makeKeyAndVisible()
// in your example you have created the window inside this method,
// which executes correctly and at the end of this method just releases the window,
// because you never saved the reference to the window
self.newWindow.rootViewController = SomeOtherViewController()
self.newWindow.windowLevel = UIWindowLevelStatusBar + 1.0
self.newWindow.hidden = false
return true
}
}
Btw. you don't have to create a UIWindow in AppDelegate. It depends on your code behavior.
try this code...
id delegate = [[UIApplication sharedApplication] delegate];
[[delegate FirstView] presentModalViewController:SecondView animated:YES];