I have a UIView (inside a View Controller, of course), and inside this UIView, I have a UIScrollView. UIScrollView contains some images and buttons. One of the buttons uses the modal Action Segue and opens up a UIView with a MapView inside, and a "back" button at the bottom that takes you back to the previous UIView. But upon going "back" (from the MapView to the UIView), the UIScrollView does not scroll anymore like it did before going to the MapView and back. It's like it's locked in its top position. I feel like it has something to do with delegates? I dunno though, I'm not too clear on those yet. Anyway, any insight to my scrolling issue?? Thanks!!
Here's my .h file (where my scroll view is):
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#interface ThirdViewController : UIViewController <UIScrollViewDelegate, UIScrollViewAccessibilityDelegate>
#property (strong, nonatomic) IBOutlet UIView *findUsView;
#property (weak, nonatomic) IBOutlet UIScrollView *findUsScrollView;
- (IBAction)callButton:(id)sender;
- (IBAction)getDirButton:(id)sender;
#end
Here's my .m file (where my scroll view is):
#import "ThirdViewController.h"
#implementation ThirdViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"appBackgroundColor.png"]];
[self.view addSubview:self.findUsScrollView];
}
-(void)viewWillAppear:(BOOL)animated{
//this line creates the frame of the scrollview (dimensions)
[self.findUsScrollView setFrame:CGRectMake(0, 0, 0, 750)];
[super viewWillAppear:animated];
}
-(void)viewDidAppear:(BOOL)animated
{
//dimensions of content within scrollveiw. Scrolling enabaled.
[self.findUsScrollView setScrollEnabled:YES];
[self.findUsScrollView setContentSize:CGSizeMake(0, 751)];
[super viewWillAppear:animated];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)callButton:(id)sender {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"tel:0000000000"]];
}
- (IBAction)getDirButton:(id)sender {
}
#end
Here's the .h file for the Map View:
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface MyMapViewController : UIViewController <MKMapViewDelegate, MKAnnotation>
#property (weak, nonatomic) IBOutlet MKMapView *mapView;
#property (weak, nonatomic) IBOutlet UINavigationBar *titleBarMap;
#property (weak, nonatomic) IBOutlet UIToolbar *bottomNavBarMap;
#property (weak, nonatomic) IBOutlet UIView *topTitlesOverlay;
- (IBAction)backButtonMap:(id)sender;
#end
Here's the .m file for the Map View:
#import "MyMapViewController.h"
#implementation BountMapViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (IBAction)backButtonMap:(id)sender {
[self dismissViewControllerAnimated:YES completion: ^(void){
ThirdViewController *vc = (ThirdViewController *)[self presentingViewController];
[[vc findUsScrollView] becomeFirstResponder];
}];
}
#end
Try moving [self.findUsScrollView setFrame:CGRectMake(0, 172, 320, 680)]; and [self.findUsScrollView setContentSize:CGSizeMake(320, 680)]; to viewDidLoad as a first suggestion. You don't want those to be called everytime your view appears.
Second, your contentSize and frameSize are the same (320, 680). This means your UIScrollView does not need to scroll. Remember: for a UIScrollView to scroll it's content size must be bigger than it's frame size. That should be all, and of course: setScrollEnabled: YES;
Your override of viewDidAppear is calling [super viewWillAppear:] instead of [super viewDidAppear:]
Related
I have a really weird issue with UIScrollView and added UIViewControllers.
It looks like that when UIViewControllers are added to UIScrollView for paging, the UIViewController drops all its added objects.
In the project i have a storyboard with two views and they are connected correctly to the corresponding code.
I know that the code doesn't move the added UIViewController to the correct X, but in this test im only adding one UIViewController so it doesnt matter.
This is the scroll code .h:
#import <UIKit/UIKit.h>
#import "TestViewController.h"
#interface ViewController : UIViewController
#property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
#property (weak, nonatomic) IBOutlet UIPageControl *pageControl;
#property (strong, nonatomic) NSMutableArray *scrollController;
#end
This is the scroll code .m:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.scrollController = [[NSMutableArray alloc] init];
}
- (void)viewDidAppear:(BOOL)animated {
//just adding two controllers
TestViewController *first = [[TestViewController alloc] init];
[self.scrollView addSubview:first.view];
[self.scrollController addObject:first];
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * self.scrollController.count, self.scrollView.frame.size.height);
self.pageControl.numberOfPages = [self.scrollController count];
}
- (void)scrollViewDidScroll:(UIScrollView *)sender {
// Update the page when more than 50% of the previous/next page is visible
CGFloat pageWidth = self.scrollView.frame.size.width;
int page = floor((self.scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
self.pageControl.currentPage = page;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
This is the viewcontroller code .h:
#import <UIKit/UIKit.h>
#interface TestViewController : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *lblMsg;
#end
This is the viewcontroller code .m:
#import "TestViewController.h"
#interface TestViewController ()
#end
#implementation TestViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
NSLog(#"Label: %#", self.lblMsg);
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
The output in log is:
Label: (null)
Anybody able to see what im doing wrong?
If you create your ViewController using
TestViewController *first = [[TestViewController alloc] init];
your label (IBOutlet) won't be linked.
Navigate to your storyboard in Xcode, select your viewcontroller and assign a unique storyboard id ("myIdentifier") in the identity inspector in utilities on the right hand side.
Try
NSString *identifier = #"myIdentifier";
TestViewController *first = [self.storyboard instantiateViewControllerWithIdentifier:identifier];
Have a look at the documentation:
Each view controller object is the sole owner of its view. You must
not associate the same view object with multiple view controller
objects. The only exception to this rule is that a container view
controller implementation may add this view as a subview in its own
view hierarchy. Before adding the subview, the container must first
call its addChildViewController: method to create a parent-child
relationship between the two view controller objects.
I have two views and two classes. On the first view, controlled by the first class I have a textfield and a button. On the second view controlled by the second class I have two labels. I tried to make one label receive the value I put on the text field, and the other label this value divided by 100. But on both cases I get 0.00, I don't know why!
firstclass.h
#import <UIKit/UIKit.h>
#interface NotasViewController : UIViewController{
}
-(IBAction)calcular:(id)sender;
-(IBAction)clicarFora:(id)sender;
-(IBAction)recuarTeclado:(id)sender;
#property (strong, nonatomic) IBOutlet UITextField *inserirTF;
#end
fisrtclass.m
#import "NotasViewController.h"
#import "resultadoViewController.h"
#interface NotasViewController ()
#end
#implementation NotasViewController
#synthesize inserirTF;
- (void)viewDidLoad
{
[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.
}
-(IBAction)calcular:(id)sender{
float valor = [inserirTF.text floatValue];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
resultadoViewController *second = [storyboard instantiateViewControllerWithIdentifier:#"resultado"];
second.resultadoFloatValor = valor;
NSLog(#"%.2f", second.resultadoFloatValor);
}
-(IBAction)recuarTeclado:(id)sender{
[sender resignFirstResponder];
}
-(IBAction)clicarFora:(id)sender{
[inserirTF resignFirstResponder];
}
#end
secondclass.h
#import <UIKit/UIKit.h>
#interface resultadoViewController : UIViewController{
float resultadoFloatValor;
}
#property float resultadoFloatValor;
#property (strong, nonatomic) IBOutlet UILabel *resultadoLabelValor;
#property (strong, nonatomic) IBOutlet UILabel *resultadoLabelQtd100;
#end
secondclass.m
#import "resultadoViewController.h"
#interface resultadoViewController ()
#end
#implementation resultadoViewController
#synthesize resultadoFloatValor, resultadoLabelValor, resultadoLabelQtd100;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
NSString *resultadoStringValor = [[NSString alloc] initWithFormat:#"%.2f", resultadoFloatValor];
NSLog(#"%.2f", resultadoFloatValor);
NSLog(#"%#", resultadoStringValor);
resultadoLabelValor.text = resultadoStringValor;
int resultadoIntResto100 = resultadoFloatValor/100;
if (resultadoIntResto100 > 0) {
NSString *resultadoStringQtd100 = [[NSString alloc] initWithFormat:#"%i", resultadoIntResto100];
resultadoLabelQtd100.text = resultadoStringQtd100;
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
You'll see 3 NSLogs on my code. For testing, I put 54 on my textfield. The Output was like this:
2013-01-12 21:15:27.020 Divisorreal[21843:c07] 54.00
2013-01-12 21:15:27.023 Divisorreal[21843:c07] 0.00
2013-01-12 21:15:27.023 Divisorreal[21843:c07] 0.00
PS: All my Outlets are correctly connected to the UILabels.
Best guess:
It looks like you are setting resultadoFloatValor after viewDidLoad is called.
Implement prepareForSegue: and set the value there.
Make sure you set the UITextView's delegate to send those actions to your controller.
Try putting a breakpoint in
-(IBAction)calcular:(id)sender
method to ensure its actually being called
I can't quite figure out what's going on but I have a view that displays a subview when a users selects a button. This subview then also has a button the user can select to cancel and remove this subview. When all of this happens, my app crashes when you attempt to close the subview.
This is my code:
From the main view that shows the subview when a button is selected -
-(IBAction)sendMessage:(id)sender{
NSLog(#"Going to send a message....");
CGRect frameBounds = [self.view bounds];
float frameWidth = frameBounds.size.width;
float frameHeight = frameBounds.size.height;
float frameX = frameBounds.origin.x;
//float frameY = frameBounds.size.height / 2;
float frameY = frameBounds.size.height;
float finalY = frameBounds.size.height / 1.75;
MessageChooserController *chooser = [[MessageChooserController alloc] initWithNibName:#"MessageChooser" bundle:nil];
//Set the frame off the screen at the bottom
chooser.view.frame = CGRectMake(frameX, frameY, frameWidth, frameHeight);
[self.view addSubview:chooser.view];
[UIView animateWithDuration:0.5 animations:^{chooser.view.frame = CGRectMake(frameX, finalY, frameWidth, frameHeight);}];
}
As you can see this simply shows a new subview - MessageChooserController. Now this subview, MessageChooserController has a button to cancel this "action".
The header file for MessageChooserController:
#import <UIKit/UIKit.h>
#interface MessageChooserController : UIViewController
#property (weak, nonatomic) IBOutlet UIButton *btn_sendEmail;
#property (weak, nonatomic) IBOutlet UIButton *btn_sendText;
#property (weak, nonatomic) IBOutlet UIButton *btn_cancel;
-(IBAction)closeChooser:(id)sender;
#end
And its implementation:
#import "MessageChooserController.h"
#interface MessageChooserController ()
#end
#implementation MessageChooserController
#synthesize btn_cancel, btn_sendEmail, btn_sendText;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
/*
[btn_cancel setBackgroundImage:[[UIImage imageNamed:#"iphone_delete_button.png"] stretchableImageWithLeftCapWidth:8.0f topCapHeight:0.0f] forState:UIControlStateNormal];
*/
/*
UIImage *cancelButtonImage = [[UIImage imageNamed:#"iphone_delete_button"] resizableImageWithCapInsets:UIEdgeInsetsMake(30,0,30,0)resizingMode:UIImageResizingModeStretch];
[btn_cancel setBackgroundImage:cancelButtonImage forState:UIControlStateNormal];
*/
}
-(IBAction)closeChooser:(id)sender{
[self.view removeFromSuperview];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
As you can see I have a simple method to close this subview, closeChooser. All of this compiles but when I select the cancel button on the subview my app crashes. I can't find anything anywhere about this.
Essentially I want to have a view display like it does when you select "Send message" from your contacts.
The correct way of doing this is calling [self presentModalViewController:viewController] on the parent view controller and then calling [self dismissModalViewController] when you want to hide it.
I wanted to have the tab bar at the top.
So i created a new project in XCode. Added a view and then inside that view i added (scrollbar, text and another view). See picture.
What i wanted was to have my tab bar at the top. Then in the middle would be the contents from the tab bar and below it a small copyright text. See picture.
No idea how to make this correctly. I have tried to create the UITabBarController on the fly and then assign it into the view at the top. (Top white space on the picture dedicated for the tab bar).
Here is my code to init the MainWindow.
MainWindow.h
#import <UIKit/UIKit.h>
#class Intro;
#interface MainWindow : UIViewController
#property (strong, nonatomic) IBOutlet UIScrollView *mainContentFrame;
#property (strong, nonatomic) IBOutlet UIView *mainTabBarView;
#property (strong, nonatomic) UITabBarController *mainTabBar;
#property (nonatomic, strong) Intro *intro; // Trying to get this tab to show in the tab bar
#end
MainWindow.m
#import "MainWindow.h"
#import "Intro.h"
#interface MainWindow ()
#end
#implementation MainWindow
#synthesize mainContentFrame = _mainContentFrame;
#synthesize mainTabBarView = _mainTabBarView;
#synthesize mainTabBar = _mainTabBar;
#synthesize intro = _intro;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
_intro = [[Intro alloc] init];
NSArray *allViews = [[NSArray alloc] initWithObjects:_intro, nil];
[super viewDidLoad];
// Do any additional setup after loading the view.
_mainTabBar = [[UITabBarController alloc] init];
[_mainTabBar setViewControllers:allViews];
[_mainTabBarView.window addSubview:_mainTabBar.tabBarController.view];
}
- (void)viewDidUnload
{
[self setMainTabBar:nil];
[self setMainContentFrame:nil];
[self setMainContentFrame:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
What am i missing to get this to work? Wanted the content to end up in the scrollview so that all tabs are scrollable.
iOS User Interface Guidelines say that the UITabBar has to be at the bottom of the ViewController. You should either create your own GUI for this kind of View or use the "old-fashioned" way. I would not try to hack around the UITabBar as your app may be rejacted by Apple.
I'm trying to add UIScrollView with paging as a header to my table, but unfortunately it is not displayed correctly.
The htableHaderView is resized to the size of my imagesScrollView, but only half of it is displayed the rest area is blank.
- (void)viewDidLoad
{
[super viewDidLoad];
ImagesViewController *imagesScrollView = [[ImagesViewController alloc] initWithNibName:#"ImagesViewController" bundle:nil];
tableView.tableHeaderView = imagesScrollView.view;
imagesScrollView = nil;
}
Thanks for helping
I tried the following code:
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UITableViewController
#end
ViewController.m
#import "ViewController.h"
#import "ImagesViewController.h"
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
ImagesViewController *imageVC = [[ImagesViewController alloc] initWithNibName:#"ImagesViewController" bundle:nil];
[[self tableView] setTableHeaderView:[imageVC view]];
imageVC = nil;
}
#end
ImagesViewController.h
#import <UIKit/UIKit.h>
#interface ImagesViewController : UIViewController
#property (strong, nonatomic) IBOutlet UIScrollView *ScrollView;
#property (strong, nonatomic) IBOutlet UIView *ViewInScrollView;
#end
ImagesViewController.m
#import "ImagesViewController.h"
#implementation ImagesViewController
#synthesize ScrollView;
#synthesize ViewInScrollView;
- (void)viewDidLoad {
[super viewDidLoad];
[[self ViewInScrollView] setFrame:CGRectMake(0, 0, 768 * 2, 400)];
[[self ViewInScrollView] setBackgroundColor:[UIColor orangeColor]];
[[self ScrollView] setContentSize:[[self ViewInScrollView] frame].size];
}
#end
ImagesViewController's xib is a view, 768 wide by 200 tall (I made an iPad-based UITableView single-view application). Inside its view is a UIScrollView, set to take up the entire [view frame] area. Then I put a UIView inside of it.
My testing gives me a header that is an orange rectangle, and I can scroll it around as you would expect. This leads me to believe that maybe you need to check the shocks/struts of your imagesScrollView in Interface Builder. Make sure all of the margins and widths are fixed/flexible as you need for it to display properly.