I'm trying to set a launch image to my application, however, it will not work the right way no matter what I do.
My app is landscape only(left or right), but I though I would just put a portrait launch image anyways.
The launch image only shows up if I check the "portrait" box and uncheck the "Landscape left" and "Landscape right" boxes in the "Deployment Info" settings. Obviously I can't do that because it will mess up my whole app.
I tried changing shouldAutorotateToInterfaceOrientation: to return YES in all of my view controllers, but that didn't work.
Any help is appreciated. Thanks!
-Xerif
I was having the same exact probably as your having and unfortunately i have found out that this is a glitch/bug in the Xcode software. I have come up with code that can display a launch image in landscape mode without any size requirements! Try to keep up with me and message me if you have any problems. Here are the steps:
Create a new objective-c file with a subclass of NSObject. Name it GameData.
inside GameData.h enter this code:
#import <Foundation/Foundation.h>
#interface GameData : NSObject
#property (assign, nonatomic) int Mainint;
+(instancetype)sharedGameData;
#end
Now inside of GameData.m enter this code:
#import "GameData.h"
#implementation GameData
+ (instancetype)sharedGameData
{
static id sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
-(void)launchImage
{
[GameData sharedGameData].Mainint = [[NSUserDefaults standardUserDefaults] integerForKey:#"mainint"];
[[NSUserDefaults standardUserDefaults] setInteger:0 forKey:#"mainint"];
}
Now go into your AppDelegate.h file and enter this:
#import "GameData.h"
Now go into your AppDelegate.m file and enter this in the below method:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions
{
[[NSUserDefaults standardUserDefaults] setInteger:0 forKey:#"mainint"]; //Add This
// Override point for customization after application launch.
return YES;
}
Now go into your storyboard and drag a UILabel onto your initial View Controller or the View controller that shows first when app is launched. Don't worry we will hide this label so you will not see it.
Now drag a UIImageView across the entire screen of your initial View Controller
Now go into your initial View Controllers .h file (mine is called ViewController.h) and add the following:
#import <UIKit/UIKit.h>
#import "GameData.h" //Add this
#interface ViewController : UIViewController
#property (weak, nonatomic) IBOutlet UIImageView *launchImage; //Add this
#property IBOutlet UILabel *seconds; //Add this
#property NSTimer *timer; //Add this
#end
Now go into your initial view controller .m file (mine is ViewController.m) and add the following:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize launchImage;
#synthesize timer;
#synthesize seconds;
- (void)viewDidLoad
{
[GameData sharedGameData].Mainint = [[NSUserDefaults standardUserDefaults] integerForKey:#"mainint"];
seconds.hidden = YES;
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(countUp) userInfo:nil repeats:YES];
if ([GameData sharedGameData].Mainint > 3) {
launchImage.hidden = YES;
}
[self countUp];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)countUp
{
[GameData sharedGameData].Mainint += 1;
seconds.text = [NSString stringWithFormat:#"%i", [GameData sharedGameData].Mainint];
if ([GameData sharedGameData].Mainint == 3) {
launchImage.hidden = YES;
[GameData sharedGameData].Mainint = 4;
[[NSUserDefaults standardUserDefaults] setInteger:[GameData sharedGameData].Mainint forKey:#"mainint"];
}
}
If you follow those steps exactly it should work and you should have no problems. If something does not work just let me know i'd be happy to help. I searched for days and days trying to find the answer and then finally figured it out through testing this code. Good Luck!
Related
I am trying to update the contents of an NSTextView that is connected to myViewController as a referencing outlet to the Files Owner which is the subclass myViewController.
When I use an IBAction from a button, or use the viewDidLoad method of the controller, I can update the text fine. However, when I try run the method from another class (referred to in this example as anotherViewController), it runs the method, but the textview does not change.
myViewController.h:
#import <Cocoa/Cocoa.h>
#import "anotherViewController.h"
#interface myViewController : NSViewController { }
#property (unsafe_unretained) IBOutlet NSTextView *outText;
#property (weak) IBOutlet NSButton *updateMeButton;
- (void)updateTextView:(NSString *)argText;
- (void)updateTextViewWithoutArg;
#end
myViewController.m:
#import "myViewController.h"
#interface myViewController ()
#end
#implementation myViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.outText.string = #"I work successfully";
}
- (IBAction)updateMeButton:(id)sender {
self.outText.string = #"I am updated text! I also work!";
}
- (void)updateTextView:(NSString *)argText {
self.outText.string = #"I don't make it to the NSTextView :(";
NSLog(#"Should have updated text view");
}
- (void)updateTextViewWithoutArg {
self.outText.string = #"I don't make it to the NSTextView :(";
NSLog(#"Should have updated text view");
}
#end
In anotherViewController.m , which has all the relevant imports, I call this:
myViewController *viewtask = [[myViewController alloc] init];
[viewtask updateTextViewWithoutArg];
Nothing happens. The method runs and logs that it should have updated, but no text updates. I have tried many different approaches, including textstorage and scrollrange methods, they all work the already working sections, but make no difference in the sections not working.
I've also tried just for fun:
myViewController *viewtask;
[viewtask updateTextViewWithoutArg];
Also using the instance variable _outText
Also using [self.outText setString:#"string"];
Also using [_outText setString:#"string"];
Again, they work but only in the already working sections.
This should be simple but isn't logical to me. In swift all I need to do is
self.outText.string = "I update whenever I'm called!"
Views you create in Interface Builder are lazily created, so if you access them before viewDidLoad is called they are nil.
If your case, calling
myViewController *viewtask = [[myViewController alloc] init];
does not cause the views to be created so when you call
[viewtask updateTextViewWithoutArg];
self.outText is nil.
You can see that this is what is happening by updating your code as below:
- (void)updateTextView:(NSString *)argText {
NSAssert(self.outText != nil, #"self.outText must not be nil");
self.outText.string = #"I don't make it to the NSTextView :(";
NSLog(#"Should have updated text view");
}
you should see the assert fire.
I appear to have found a solution by making myViewController a singleton class and using sharedInstance. For this particlar app, myViewController is a debug output window and will never need to be placed in another view.
I won't accept this answer yet, as it's not the best one I'm sure. There may still be a proper solution presented that allows finding the applicable myViewController instance, and modifying the outText property attached to it. Using this singleton makes subclassing tedious as I would have to make a new class for every instance if I wanted to be able to address say 10 View Controllers.
Anyway - the way I've been able to satisfy my simple requirement:
myViewController.h:
#import <Cocoa/Cocoa.h>
#import "anotherViewController.h"
#interface myViewController : NSViewController { }
#property (unsafe_unretained) IBOutlet NSTextView *outText;
#property (weak) IBOutlet NSButton *updateMeButton;
- (void)updateTextView:(NSString *)argText;
- (void)updateTextViewWithoutArg;
+ (id)sharedInstance;
#end
myViewController.m:
#import "myViewController.h"
#interface myViewController ()
#end
#implementation myViewController
static myViewController *sharedInstance = nil;
+ (myViewController *)sharedInstance {
static myViewController *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[myViewController alloc] init];
});
return sharedInstance;
}
- (void)viewDidLoad {
[super viewDidLoad];
sharedInstance = self;
}
- (void)viewDidUnload {
sharedInstance = nil;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.outText.string = #"I work successfully";
}
- (IBAction)updateMeButton:(id)sender {
sharedInstance.outText.string = #"Button Pressed";
}
- (void)updateTextView:(NSString *)argText {
sharedInstance.outText.string = argText;
}
- (void)updateTextViewWithoutArg {
sharedInstance.outText.string = #"I make it to the TextView now";
}
#end
Now when I use this code from within anotherViewController.m it updates the right instance:
[myViewController.sharedInstance updateTextView:#"Updating with this string"];
I'm using the latest Xcode (4.4.1) and developing for iOS 5.1. I am utilizing the bottom tab bar interface provided by Apple. One of the tabs uses a UIWebView that utilizes the full screen space. When I try to add a standard banner provided by AdMob, it does not add a banner at all. I was following along with: https://developers.google.com/mobile-ads-sdk/docs/admob/fundamentals. Code attached below
About.h
#import <UIKit/UIKit.h>
#import "GADBannerView.h"
#interface About : UIViewController <UIWebViewDelegate> {
IBOutlet UIWebView *webView;
// Declare one as an instance variable
GADBannerView *bannerView_;
}
#property (nonatomic, retain) UIWebView *webView;
#end
About.m
#import "About.h"
#import "GADBannerView.h"
#import "GADRequest.h"
#import "constants.h"
#implementation About
#synthesize webView;
//#synthesize bannerView = bannerView_;
+ (void)initialize {
// Set user agent (the only problem is that we can't modify the User-Agent later in the program)
NSDictionary *dictionary = [[NSDictionary alloc] initWithObjectsAndKeys:UserAgent, #"UserAgent", nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:dictionary];
}
- (void)viewDidLoad {
[super viewDidLoad];
NSString *fullURL = ([IsBeta isEqualToString: #"true"]) ? #"http://beta.wouldyouratherapp.com/questions/index/0/1" : #"http://wouldyouratherapp.com/questions/index/0/1";
NSURL *url = [NSURL URLWithString:fullURL]; NSURLRequest *requestObj = [NSURLRequest requestWithURL:url]; [webView loadRequest:requestObj];
// Create a view of the standard size at the bottom of the screen.
// Available AdSize constants are explained in GADAdSize.h.
bannerView_ = [[GADBannerView alloc] initWithAdSize:kGADAdSizeBanner];
// Specify the ad's "unit identifier." This is your AdMob Publisher ID.
bannerView_.adUnitID = MyAdUnitID;
// Let the runtime know which UIViewController to restore after taking
// the user wherever the ad goes and add it to the view hierarchy.
bannerView_.rootViewController = self;
[self.view addSubview:bannerView_];
// Initiate a generic request to load it with an ad.
[bannerView_ loadRequest:[GADRequest request]];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
#end
Yes, I have added all the frameworks already, and MyAdUnitID is already defined in the constants file, so everything SHOULD be working, but I guess I am missing something. Any help?
If you're adding the bannerView_, you'll have to decrease the height of your webView accordingly to make room for the bannerView_. Since the origin of the ad looks like its at (0,0), you probably want something similar to this in your adView:DidReceiveAd: callback:
webView.frame = CGRectMake (0, bannerView_.frame.size.height, webView.frame.size.width, webView.frame.size.height - bannerView_.frame.size.height);
I have put together a simple quote generator, storing the quotes in an array. Following are the quote view controller interface and implementation files:
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property(nonatomic, retain)NSArray *myQuotes;
#property(nonatomic, retain)NSMutableArray *movieQuotes;
#property (nonatomic, retain) IBOutlet UITextView *quote_text;
-(IBAction)quote_btn_touch:(id)sender;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize myQuotes;
#synthesize movieQuotes;
#synthesize quote_text;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.myQuotes = [NSArray arrayWithObjects:
#"Live and let live",
#"Don't cry over spilt milk",
#"Always look on the bright side of life",
#"Nobody's perfect",
#"Can't see the woods for the trees",
#"Better to have loved and lost than not loved at all",
#"The early bird catches the worm",
#"As slow as a wet week",
nil];
quote_text = nil;
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
-(IBAction)quote_btn_touch:(id)sender {
// 1 - Get number of rows in array
int array_tot = [self.myQuotes count];
// 2 - Get random index
int index = (arc4random() % array_tot);
// 3 - Get the quote string for the index
NSString *my_quote = [self.myQuotes objectAtIndex:index];
// 4 - Display the quote in the text view
self.quote_text.text = [NSString stringWithFormat:#"Quote:\n\n%#", my_quote];
}
#end
In the xib file, I connected the text view and button to the File's Owner, using quote_text and quote_btn_touch respectively.
Trouble is that when I click on the button, nothing happens. Any idea what I missed?
Thanks in advance!
your setting quote text to nil on viewDidLoad. If you get rid of that your code should work as long as you correctly bound the button to the viewcontroller function
quote_text = nil;
I am having an issue with ARC. It is not retaining the webview. The scenario is I have to send a webview from one viewcontroller to another one. The reason is when the user searches for something I want to take him to a new screen with some other options. (I have to use the same webview)
Here is the sample code: I have a ViewController1 which has a webview (I added it in the xib.) I am loading say google in it and once the user searches for something and when its done loading I have to take him to a new view controller and show the same webview in the new viewcontroller.
//ViewController1
#interface ViewController1 : UIViewController <UIWebViewDelegate>
#property (nonatomic, retain) UIWebView* testWebView;
#end
#implementation ViewController1
#synthesize testWebView;
- (void)viewDidLoad
{
[super viewDidLoad];
testWebView = [[UIWebView alloc]init];
testWebView.delegate = self;
[testWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"https://www.google.com"]]];
}
-(void)webViewDidFinishLoad:(UIWebView *)webView{
NSString *html = [testWebView stringByEvaluatingJavaScriptFromString:
#"document.body.innerHTML"];
if ([self.testWebView.request.url.absoluteString rangeOfString:#"output=search"].location != NSNotFound) {
ViewController2* newViewController = [[ViewController2 alloc] init];
[newViewController setTestWebView:self.testWebView];
[self.navigationController setViewControllers:[NSArray arrayWithObject:newViewController] animated:NO];
}
}
- (void)dealloc{
[self.testWebView stopLoading];
self.testWebView.delegate = nil;
self.testWebView = nil;
}
In the second view controller I am loading stackoverflow.com after a delay of 10 secs. The problem is it is loading stackoverflow fine, but it is not calling any of the delegate methods. Why?
#interface ViewController2 : UIViewController <UIWebViewDelegate>
#property (nonatomic, retain) UIWebView* testWebView;
#end
#implementation ViewController2
#synthesize testWebView;
- (void)viewDidLoad
{
[super viewDidLoad];
self.testWebView.delegate = self;
[self.view addSubview:testWebView];
[self performSelector:#selector(loadDifferentPage) withObject:nil afterDelay:10];
}
-(void)loadDifferentPage{
[self.testWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.stackoverflow.com/"]]];
}
-(void)webViewDidStartLoad:(UIWebView *)webView{
NSLog(#"%s", __PRETTY_FUNCTION__);
}
-(void)webViewDidFinishLoad:(UIWebView *)webView{
NSLog(#"%s", __PRETTY_FUNCTION__);
}
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
NSLog(#"%s", __PRETTY_FUNCTION__);
return YES;
}
ViewController2 is retaining the webview but the delegate methods are not being called. Why?
Thanks
Sai
ViewController1 delloc method was causing the issue:
If I uncomment out self.textWebView.delegate = nil it works fine. The reason is first we are setting the webview for newViewController and later in dealloc of ViewController1 we are setting its delegate to nil.
- (void)dealloc{
[self.testWebView stopLoading];
if(self.testWebView.delegate == self)
self.testWebView.delegate = nil;
self.testWebView = nil;
}
First thing I noticed is you're not specifying the instance variable name when synthesizing a property. That's just asking for collisions. Here's an example of how that should look:
#interface ViewController1 : UIViewController <UIWebViewDelegate>
#property (nonatomic, strong) IBOutlet UIWebView* testWebView;
#end
#implementation ViewController1
#synthesize testWebView=_testWebView;
Also, I noticed in ViewController1 you used IBOutlet so everything is probably wired up in Interface Builder. Try making sure that you set the delegate property in Interface Bulider because you don't set it in the implementation. That would be why you're not receiving any messages.
ViewController2 looks like you set the delegate in code. The problem is, you DON'T have IBOutlet in front of the property. Normally this would mean that you simply setup the WebView in code, but in your example you do not ever create a new instance of a UIWebView control and assign it to self.testWebView. This means that if it does display on the page, it's because Interface Builder was used to create it. You couldn't set the delegate in code without using IBOutlet in front of the testWebView declaration so that's probably why it's not working in exmaple two.
#interface ViewController2 : UIViewController <UIWebViewDelegate>
#property (nonatomic, strong) UIWebView* testWebView; // Mising IBOutlet
#end
#implementation ViewController2
#synthesize testWebView;
- (void)viewDidLoad
{
[super viewDidLoad];
// missing any code that would create the webview [[UIWebView alloc] init]
self.testWebView.delegate = self; // You set the delegate in code here
[self.view addSubview:testWebView];
[self performSelector:#selector(loadDifferentPage) withObject:nil afterDelay:10];
}
Hope this helps, I'd have to see your full implementation to get more specific than this.
Ok, so I'm a relative noob with Objective-C/iOS programming, so hopefully someone with more knowledge here can help me out.
I have an iPad application using the SplitViewController template (with Core Data). I created another UIViewController (with xib file) called PlayerViewController. This View has several UILabel components on it.
I have a list of players that show up in the RootViewController (UITableView) and when you select a player, I programmatically create a PlayerViewController (in DetailViewController), pass it the NSManagedObject that was passed to the DetailViewController, try to set the text of one of the labels on the PlayerViewController's view, and then add it as a subview to the DetailViewController.
All of this works great except for the setting the text of the label on the PlayerViewController's view. I'm not sure what I'm doing wrong. I have used NSLog to confirm that the NSManagedObject is not nil and that the NSManagedObject property I'm trying to use has the correct text.
I'm at a loss here. Any help would be greatly appreciated. (Code follows):
This method is in the DetailViewController.m file:
- (void)configureView {
// Update the user interface for the detail item.
PlayerViewController *player = [[PlayerViewController alloc] init];
player.player = detailItem;
[self.view addSubview:player.view];
}
This method is called when the user selects an item from the RootViewController (This functionality, calling of configureView, is setup by the template and I haven't changed it).
Setting the player property of the PlayerViewController to object detailItem is handled in the setPlayer method of that class.
- (void)setPlayer:(NSManagedObject *)managedObject {
if (player != managedObject) {
[player release];
player = [managedObject retain];
// Update the view.
[self configureView];
}
}
I then have a configureView method as well in PlayerViewController that sets the text of the label:
- (void)configureView {
nickName.text = [[player valueForKey:#"Nickname"] description];
NSLog(#"Nickname %#", [[player valueForKey:#"Nickname"] description]);
NSLog(#"Nickname %#", nickName.text);
}
Ok, so the first NSLog statement prints the desired value, but the text of the UILabel (called nickName) returns nil.
The following is the full PlayerViewController.h & .m files:
PlayerViewController.h:
#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>
#interface PlayerViewController : UIViewController {
NSManagedObject *player;
IBOutlet UILabel *nickName;
IBOutlet UILabel *goalCount;
IBOutlet UILabel *assistCount;
IBOutlet UILabel *timeInGame;
}
#property (nonatomic, retain) IBOutlet UILabel *nickName;
#property (nonatomic, retain) IBOutlet UILabel *goalCount;
#property (nonatomic, retain) IBOutlet UILabel *assistCount;
#property (nonatomic, retain) IBOutlet UILabel *timeInGame;
#property (nonatomic, retain) NSManagedObject *player;
#end
PlayerViewController.m:
#import "PlayerViewController.h"
#implementation PlayerViewController
#synthesize nickName, goalCount, assistCount, timeInGame, player;
#pragma mark -
#pragma mark Managing the detail item
/*
When setting the player item, update the view
*/
- (void)setPlayer:(NSManagedObject *)managedObject {
if (player != managedObject) {
[player release];
player = [managedObject retain];
// Update the view.
[self configureView];
}
}
- (void)configureView {
nickName.text = [[player valueForKey:#"Nickname"] description];
NSLog(#"Nickname %#", [[player valueForKey:#"Nickname"] description]);
NSLog(#"Nickname %#", nickName.text);
}
/*
// The designated initializer. Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
// Custom initialization
}
return self;
}
*/
/*
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
}
*/
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Overriden to allow any orientation.
return YES;
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
}
#end
I'm sure I'm just missing something trivial, but I can't figure it out, and haven't been able to find any answers searching the web.
Thanks for any help!
Ok, so after playing with this for a bit and searching and searching around, I have gotten the answer to my problem. It turns out all the code I had was fine except the location of one statement. My call to configureView in PlayerViewController.m needed to be in viewDidLoad() not in the setPlayer() method. It all works great now.
Change the configureView method to that :
- (void)configureView {
nickName.text = (NSString*)[player valueForKey:#"Nickname"];
}
Yes, better place to call method is
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self configureView];
}
(void)setPlayer:(NSManagedObject *)managedObject called before your nib files loaded.