Objective-C Programmatic title not showing - ios

I have set my self.navigationItem.title = #"Hello"; in ViewController.m but it's not showing:
AppDelegate.m
#import "AppDelegate.h"
#import "ViewController.h"
#interface AppDelegate ()
#end
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
ViewController *viewController = [[ViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:viewController];
self.window.rootViewController = navController;
[self.window makeKeyAndVisible];
return YES;
}
#pragma mark - UISceneSession lifecycle
- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options API_AVAILABLE(ios(13.0)) {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return [[UISceneConfiguration alloc] initWithName:#"Default Configuration" sessionRole:connectingSceneSession.role];
}
- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet<UISceneSession *> *)sceneSessions API_AVAILABLE(ios(13.0)) {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}
#end
ViewController.m
#import "ViewController.h"
#import <UIKit/UIKit.h>
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = #"Hello";
self.view.backgroundColor = [UIColor systemBlueColor];
}
#end
Thanks in advance!

I'm considering that you're not using storyboard.
In your case, you have to do everything programmatically, including allocating the navbar.
- (void)viewDidLoad {
[super viewDidLoad];
UINavigationBar *navbar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 20, self.view.frame.size.width, 44)];
UINavigationItem *title = [[UINavigationItem alloc] initWithTitle:#"Hello"];
self.view.backgroundColor = [UIColor systemBlueColor];
[navbar setItems:#[title]];
[self.view addSubview:navbar];
}
If you were using storyboard, this simple command would be working, without needing anything in the appDelegate.
self.navigationItem.title = #"Hello";

It is enough to say: viewController.title = #“Hello”;
https://developer.apple.com/documentation/uikit/uiviewcontroller/1621364-title

Related

EXC_BAD_ACCESS while textField becomeFirstResponder

I am getting EXE_BAD_ACCESS exception when I hit "back" button on NavigationBar of my CreateViewController which is pushed on UINavigationController
When I enable following line in CreateViewController.m (full code at the bottom)
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.navigationController.navigationBar.hidden = NO;
//[self.textField becomeFirstResponder];
}
I start getting Thread1:EXE_BAD_ACCESS(code=1, address=...)
int main(int argc, char * argv[])
{
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
If I keep the above line of code disabled, then hitting back button takes me to MainViewController as expected.
I am a newbie to iOS. What I am doing wrong? Please see my code below.
Appdelegate.h
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#end
Appdelegate.m
import "AppDelegate.h"
import "MainViewController.h"
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
id controller = [[MainViewController alloc] initWithNibName:#"MainView" bundle:nil];
id navController = [[UINavigationController alloc] initWithRootViewController:controller];
self.window.rootViewController = navController;
[self.window makeKeyAndVisible];
return YES;
}
#end
MainViewController.h
#interface MainViewController : UIViewController
- (IBAction)create:(id)sender;
#end
MainViewController.m
import "MainViewController.h"
import "CreateViewController.h"
#implementation MainViewController
#pragma mark - View lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)viewDidUnload {
[super viewDidUnload];
}
- (void)viewWillAppear:(BOOL)animated {
self.navigationController.navigationBar.hidden = YES;
}
- (IBAction)create:(id)sender {
id controller = [[CreateViewController alloc] initWithNibName:#"CreateView" bundle:nil];
[self.navigationController pushViewController:controller animated:YES];
}
#end
CreateView.h
#interface CreateViewController : UIViewController <UITextFieldDelegate>
#end
CreateView.m
- (void)viewDidLoad {
[super viewDidLoad];
[self.navigationController.navigationBar setTintColor:[UIColor purpleColor]];
self.textField=[[UITextField alloc] initWithFrame:CGRectMake(80, 10, 160, 30)];
[self.textField setBorderStyle:UITextBorderStyleRoundedRect];
self.textField.placeholder = #"Name";
[self.textField setBackgroundColor:[UIColor clearColor]];
self.textField.delegate = self;
[self.navigationController.navigationBar addSubview:self.textField];
self.navigationController.navigationBar.hidden = NO;
}
- (void)viewDidUnload {
[super viewDidUnload];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.navigationController.navigationBar.hidden = NO;
//[self.textField becomeFirstResponder];
}
Go to breakpoint navigator and add exceptions breakpoint as shown below , 1st option :
Instead of adding self.textField as subview to navigation bar, set the textField as titleView of navigation item of the view controller.
[self.navigationItem setTitleView:self.textField];
This must help...

Change the starting View in a tabbed iOS application

i have created a tabbed application and created another file, called LogInScreen,
I want to change the usual view which comes up at the application launch to this new LogInFile, but everything I tried didn't work.
This is the AppDelegate.h file:
#import <UIKit/UIKit.h>
#import "LogInScreen.h"
#interface LogInScreen : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) LogInScreen *logInView;
#end
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#end
At the first #implementation appears an error message: Duplicate interface definition for class 'LogInScreen', I guess because of the LogInScreen.h file. I don't know how to get it to work properly.
And this the start of the AppDelegate.m:
#import "AppDelegate.h"
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions
{
[self.logInView addSubview:_logInView.view];
[self.logInView makeKeyAndVisible];
[self.logInView setRootViewController:_logInView];
// Override point for customization after application launch.
return YES;
}
I found this code on this website, but it didn't work...
Here's the LogInScreen.h file:
#import <UIKit/UIKit.h>
#interface LogInScreen : UIViewController{
NSString *password;
IBOutlet UITextField *passwordField;
}
- (IBAction)enterPassword;
- (IBAction)savepassword:(id)sender;
- (IBAction)returnKey:(id)sender;
- (IBAction)switchView:(id)sender;
#end
and the LogInScreen.m:
#import "LogInScreen.h"
#import "FirstViewController.h"
/* #import "AppDelegate.h"
int main(int argc, char * argv[])
{
#autoreleasepool {
return UIApplicationMain()(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
*/
#interface LogInScreen ()
#end
#implementation LogInScreen
- (IBAction)enterPassword
{
NSString *passwordString = [NSString stringWithFormat:#"12345"];
if ([passwordField.text isEqualToString:passwordString]) {
/*[self switchView:nil]; */
}
else {
UIAlertView *incorrectPassword = [[UIAlertView alloc] initWithTitle:#"Falsches Passwort" message:#"Dieses Passwort ist falsch! Geben Sie bitte das korrekte Passwort ein!" delegate:self cancelButtonTitle:#"Zurück" otherButtonTitles:nil, nil];
[incorrectPassword show];
}
}
- (IBAction)savepassword:(id)sender {
password = [[NSString alloc] initWithFormat:passwordField.text];
[passwordField setText:password];
NSUserDefaults *stringDefault = [NSUserDefaults standardUserDefaults];
[stringDefault setObject:password forKey:#"stringKey"];
}
- (IBAction)returnKey:(id)sender {
[sender resignFirstResponder];
}
- (IBAction)switchView:(id)sender {
FirstViewController *main = [[FirstViewController alloc] initWithNibName:nil bundle:nil];
[self presentViewController:main animated:YES completion:NULL];
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[passwordField setText:[[NSUserDefaults standardUserDefaults] objectForKey:#"stringKey"]];
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Would be cool if someone could help me
Following my comment, you can use this code to show a modal login view before your main tabbed view:
// Main menu view controller
MainViewController *mainViewController = [[MainViewController alloc] initWithNibName:#"MainViewController" bundle:nil];
UINavigationController *mainNavigationController = [[UINavigationController alloc] initWithRootViewController:mainViewController];
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.delegate = self;
self.tabBarController.viewControllers = [NSArray arrayWithObjects:mainNavigationController, nil];
self.window.rootViewController = self.tabBarController;
[self.window.rootViewController.view setOpaque:NO];
self.window.rootViewController.view.backgroundColor = [UIColor clearColor];
self.tabBarController.selectedIndex = 0;
[self.window setRootViewController:self.tabBarController];
[self.window makeKeyAndVisible];
// Login modal view controller
LoginViewController *loginController = [[LoginViewController alloc] initWithNibName:#"LoginViewController" bundle:nil];
[self.tabBarController presentViewController:loginController animated:NO completion:nil];
Place your login screen as intial view in MainStoryBoard .Drag a drop a uitabbarcontroller connect a segue from loginscreen to uitabbar and present modal that tabbar from a button in the login screen .

UIViewController being pushed down on screen when displayed using insertSubview

Having a bit of a problem, here's the breakdown:
My AppDelegate uses as it's rootViewController a view controller. This view controller's purpose is to swap a couple of other view controllers in and out, call it login and main screens. For the sake of simplicity I've removed any swapping code from the code that I will post and am having the rootViewController simply show it's first content view controller, say login.
The issue I'm having is that the content view controller seems to be pushed down a little bit inside the rootViewController. I've given the rootViewController a blue background and the content view controller an orange background. Here's my code:
AppDelegate.h
#import <UIKit/UIKit.h>
#class MainViewController;
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) MainViewController *main;
#end
AppDelegate.m
#import "AppDelegate.h"
#import "MainViewController.h"
#implementation AppDelegate
#synthesize main;
- (void)dealloc
{
[_window release];
[main release];
[super dealloc];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
MainViewController *mainVC = [[MainViewController alloc] init];
self.main = mainVC;
self.window.rootViewController = self.main;
[self.window makeKeyAndVisible];
return YES;
}
MainViewController.h
#import <UIKit/UIKit.h>
#class ContentViewController;
#interface MainViewController : UIViewController
#property (nonatomic, retain) ContentViewController *content;
#end
MainViewController.m
#import "MainViewController.h"
#import "ContentViewController.h"
#implementation MainViewController
#synthesize content;
- (id)init
{
self = [super init];
if (self ) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor blueColor];
ContentViewController *viewController = [[ContentViewController alloc] init];
self.content = viewController;
[self.view insertSubview:self.content.view atIndex:0];
}
- (void)dealloc {
[content release];
[super dealloc];
}
#end
ContentViewController.h
#import <UIKit/UIKit.h>
#interface LoginVC : UIViewController
#end
ContentViewController.m
#import "ContentViewController.h"
#implementation ContentViewController
- (id)init
{
self = [super init];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor orangeColor];
}
- (void)dealloc {
[super dealloc];
}
#end
The above codes gives me a status bar with a blue strip (approximately the height of the status bar) under it (which is the main view controller) followed by the orange content view controller taking up the rest of the screen. For some reason that main view controller seems to be pushing the content view controller down a little.
Strangely, if I create a view controller and use a XIB for drawing the view, it looks just fine and the content view it right up against the top of the main view.
If anybody could shed some light on this issue I'd very much appreciate it.
Cheers
I suppose that you shouldn't be doing
ContentViewController *viewController = [[ContentViewController alloc] init];
self.content = viewController;
[self.view insertSubview:self.content.view atIndex:0];
but rather:
ContentViewController *viewController = [[ContentViewController alloc] init];
self.content = viewController;
[self presentViewController:self.content animated:YES completion:nil];

Multiple PDFs in different tabs

I have a Tabbar iOS application with three tabs. I have each tab set up to be a UIWebView. I want each web view to display a different PDF. How do I assign, through code, each webview to its corresponding pdf?
It will look something like this in your AppDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
WebViewController *webViewController1 = [[WebViewController alloc] initWithPDFAtURL:#"urlToPDF1"];
WebViewController *webViewController2 = [[WebViewController alloc] initWithPDFAtURL:#"urlToPDF2"];
WebViewController *webViewController3 = [[WebViewController alloc] initWithPDFAtURL:#"urlToPDF3"];
UITabBarController *tabBarController = [[UITabBarController alloc] init];
[tabBarController setViewControllers:[NSArray arrayWithObjects:webViewController1, webViewController2, webViewController3, nil]];
self.window.rootViewController = tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
You will need to have a view controller that holds the UIWebView, and could look something like:
// WebViewController.h
#interface WebViewController : UIViewController
#end
// WebViewController.m
#interface WebViewController ()
#property (nonatomic, strong) NSURL *_pdfURL;
#end
#implementation WebViewController
#synthesize _pdfURL;
- (id)initWithPDFAtURL:(NSURL *)url {
self = [super init];
if (self) {
_pdfURL = url;
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Load the PDF into a UIWebView
}

Why can't I force landscape orientation when use UINavigationController?

I find many question to force UIViewController to landscape as default:
How to force a UIViewController to Portrait orientation in iOS 6
And try this:
- (BOOL)shouldAutorotate
{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationLandscapeLeft;
}
But when I use UIViewController inside UINavigationController, I can't force to landscape.Please help!
*Work NOT ok
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
UINavigationController *navControl = [[UINavigationController alloc] initWithRootViewController:self.viewController];
[navControl setNavigationBarHidden:YES];
self.window.rootViewController = navControl;
[self.window makeKeyAndVisible];
return YES;
}
*Work OK:
self.window.rootViewController = self.viewController;
Best way to do this is the create extend UINavigationController and write your orientation function inside the extended class.
Class Declaration:
#interface MyNavigationControllerViewController : UINavigationController
#property(nonatomic, assign) UIInterfaceOrientation orientation;
#property(nonatomic, assign) NSUInteger supportedInterfaceOrientatoin;
#end
Implementation of MyNavigationController
#implementation MyNavigationController
#synthesize supportedInterfaceOrientatoin = _supportedInterfaceOrientatoin;
#synthesize orientation = _orientation;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
_supportedInterfaceOrientatoin = UIInterfaceOrientationMaskLandscape;
_orientation = UIInterfaceOrientationLandscapeLeft;
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (BOOL)shouldAutorotate
{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
return _supportedInterfaceOrientatoin;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return self.orientation;
}
#end
and use your extended like MyNavigationController as navigation controller to your rootviewcontroller.
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) ViewController *viewController;
#property (strong, nonatomic) MyNavigationControllerViewController *myNavController;
- (void) reloadAppDelegateRootViewControllerLandscape;
- (void) reloadAppDelegateRootViewController;
#end
So your application delegate didfinishlounchingwithoptions code will be as follow.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
self.myNavController = [[MyNavigationController alloc] initWithRootViewController:self.viewController];
[self.myNavController setNavigationBarHidden:YES];
self.window.rootViewController = self.myNavController;
[self.window makeKeyAndVisible];
return YES;
}
Only way you can provide different orientation for two different view with same navigation controller isto reload the navigation controller itself. So if you add two methods
- (void) reloadAppDelegateRootViewController{
[[[UIApplication sharedApplication].delegate window] setRootViewController:nil];
[(MyNavigationControllerViewController *)self.myNavController setOrientation:UIInterfaceOrientationPortrait];
[(MyNavigationControllerViewController *)self.myNavController setSupportedInterfaceOrientatoin:UIInterfaceOrientationMaskAll];
[[[UIApplication sharedApplication].delegate window] setRootViewController:self.myNavController];
}
- (void) reloadAppDelegateRootViewControllerLandscape{
[[[UIApplication sharedApplication].delegate window] setRootViewController:nil];
[(MyNavigationControllerViewController *)self.myNavController setOrientation:UIInterfaceOrientationLandscapeLeft];
[(MyNavigationControllerViewController *)self.myNavController setSupportedInterfaceOrientatoin:UIInterfaceOrientationMaskLandscape];
[[[UIApplication sharedApplication].delegate window] setRootViewController:self.myNavController];
}
and call these function after pushing and pop views.
Note:- I don't know whether it is a good way or bad way.
You need to go to your plist file and set the orientations. You can also do this on your project file. The plist orientations settings will override all though.
In your plist you can set both orientation options to landscape button left and landscape button right.

Resources