iOS 5 ScrollView Adding SubViews Causes EXC_BAD_ACCESS - ios5

ARC, iOS 5, XCode 4.2
I am trying to implement a paged scroll view with a page control (similar to the Home screen), and I can't seem to get it to work. The relevant code is:
- (void)viewDidLoad
{
[super viewDidLoad];
[scroll setDelegate:self];
[scroll setContentSize:CGSizeMake(2 * [[UIScreen mainScreen] bounds].size.width, [[UIScreen mainScreen] bounds].size.height)];
[scroll setPagingEnabled:YES];
pageControl.currentPage = 0;
pageControl.numberOfPages = 2;
UIView* view = [[self.storyboard instantiateViewControllerWithIdentifier:#"VALID_ID_1"] view];
view.frame = CGRectMake(0, 0, [[UIScreen mainScreen] bounds].size.width, [[UIScreen mainScreen] bounds].size.height);
[scroll addSubview:view];
UIView *aView = [[self.storyboard instantiateViewControllerWithIdentifier:#"VALID_ID_2"] view];
aView.frame = CGRectMake([[UIScreen mainScreen] bounds].size.width, 0, [[UIScreen mainScreen] bounds].size.width, [[UIScreen mainScreen] bounds].size.height);
[scroll addSubview:aView];
}
Calling the instantiateViewControllerWithIdentifier method returns a result.
Things I have tried:
Disabling ARC on this particular file
Using alloc] init] on the view controller
EDIT: I should probably show the declaration:
//MyViewController.h
#property (strong, nonatomic) IBOutlet UIScrollView* scroll;
...
//MyViewController.m
#synthesize scroll;

most likely, scroll is nil. please check..!

Related

iOS - UIView in landscape mode is not rotating

I'm writing an app support for both iPhone & iPad. In iPhone required Portrait mode, iPad required to use Landscape.
In AppDelegate.m
if ([CKAppDelegate isPad]) {
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight];
CGSize size = [self getScreenSize];
navigationController = [[UINavigationController alloc] initWithRootViewController:[[PadMainViewController alloc] initWithFrame:CGRectMake(0, 0, size.width, size.height)]];
} else {
CGSize size = [self getScreenSize];
navigationController = [[UINavigationController alloc] initWithRootViewController:[[MainViewController alloc] initWithFrame:CGRectMake(0, 0, size.width, size.height)]];
}
self.window.rootViewController = navigationController;
...
- (CGSize)getScreenSize
{
CGSize size;
if (UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation) && [[UIScreen mainScreen] bounds].size.height > [[UIScreen mainScreen] bounds].size.width) {
// in Landscape mode, width always higher than height
size.width = [[UIScreen mainScreen] bounds].size.height;
size.height = [[UIScreen mainScreen] bounds].size.width;
} else if (UIInterfaceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation) && [[UIScreen mainScreen] bounds].size.height < [[UIScreen mainScreen] bounds].size.width) {
// in Portrait mode, height always higher than width
size.width = [[UIScreen mainScreen] bounds].size.height;
size.height = [[UIScreen mainScreen] bounds].size.width;
} else {
// otherwise it is normal
size.height = [[UIScreen mainScreen] bounds].size.height;
size.width = [[UIScreen mainScreen] bounds].size.width;
}
return size;
}
In PadMainViewController.m
- (id)initWithFrame:(CGRect)frame
{
UIView *leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width * 0.7, frame.size.height)];
leftView.backgroundColor = [UIColor cyanColor];
UIView *rightView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width * 0.3, frame.size.height)];
rightView.backgroundColor = [UIColor yellowColor];
self.chopInkButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[self.chopInkButton setTitle:#"Tap to ChopInk" forState:UIControlStateNormal];
self.chopInkButton.frame = CGRectMake(50, 200, 250, 44);
[self.chopInkButton addTarget:self action:#selector(chopInkButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
[rightView addSubview:self.chopInkButton];
self.logoImageView.frame = CGRectMake(50, 50, 100, 100);
[self.logoImageView.layer setBorderColor:[[UIColor blackColor] CGColor]];
[self.logoImageView.layer setBorderWidth:2.0f];
[rightView addSubview:self.logoImageView];
[self.view addSubview:leftView];
[self.view addSubview:rightView];
return self;
}
...
- (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)toInterfaceOrientation
{
return (UIInterfaceOrientationIsLandscape(toInterfaceOrientation));
}
The result that I get is
In project summary, I already disabled the portrait mode for iPad
Any idea why the button is not rotating?
Try to use below methods : for iOS 6
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAll;
}
- (BOOL)shouldAutorotate
{
return YES;
}
I solve this by changing
PadMainViewController.m
- (id)initWithFrame:(CGRect)frame
{
...
return self;
}
to
- (id)initWithFrame:(CGRect)frame
{
if ((self = [super init])) {
...
}
return self;
}
By the way, the initWithFrame is self defined function.

How can I set my UIView's frame from CGRectMake?

I am new to iOS development, but have had an extensive crash course recently (BNR guid to iOS Programming). I am working on modally adding views to an app. I currently do not have a View Controller, so my AppDelegate's application:didFinishLaunchingWithOptions method looks as follows:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
MyUIView *map = [[MapSurface alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
//this one does not work: MyUIView *map = [[MapSurface alloc] initWithFrame:CGRectMake(0, 0, 256, 256)];
[map setBackgroundColor:[UIColor grayColor]];
[[self window] addSubview:map];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
After the view loads, I make a call to add a subview, but I cannot set the frame size using CGRectMake. It doesn't show up on screen. The only thing I have found to work is using the screen size, but this is not what I want. Here is the code for adding this subview:
UIImage *image = [[UIImage alloc] initWithCGImage:img];//img is a CGImageRef
UIImageView *view = [[UIImageView alloc] initWithImage:image];
CGRect b = CGRectMake(0, 0, 256, 256);
//[view setFrame:b];//nothing shows on screen
//[view setBounds:b];//nothing shows on screen
//[view setBounds:[[UIScreen mainScreen] bounds]];//shows the tan area in the graphic below
[view setFrame:[[UIScreen mainScreen] bounds]];//fills the screen
[map addSubView:view];
CGImageRelease(img);
I was setting the bounds attribute, when I should have been setting frame. Making this change fixed the issue.

Cannot add custom view controller to UIScrollVIew

I'm trying to make an application that uses a UIScrollView to page between an indeterminate number of dynamically generated custom view controllers. Unfortunately, when I try the code shown below, all I get is a blank screen. Additionally, the nslog statement that I put right after the subview is supposedly added to the UIScrollView always says that the UIScrollView has zero subviews. I'm totally baffled by this problem and would greatly appreciate any help.
- (void)loadView
{
[super loadView];
scrollView.pagingEnabled = YES;
viewControllers = [[NSMutableArray alloc] init];
CGRect screenBounds = [[UIScreen mainScreen] bounds];
CGFloat screenScale = [[UIScreen mainScreen] scale];
CGFloat width = screenBounds.size.width * screenScale;
CGFloat height = screenBounds.size.height * screenScale;
scrollView.contentSize = CGSizeMake(width * [routes count], height);
for( int i = 0; i < [arrayWithDataForViewControllers count]; i++)
{
ViewController *controller = [[ViewController alloc] init];
controller.view.frame = CGRectMake(width*i, 20, width, height);
[scrollView addSubview:controller.view];
NSLog(#"SUBVIEWS %d", [[scrollView subviews] count]);
[viewControllers addObject:controller];
}
}
Check your ViewController's view outside of the scrollview - chances are that it's view property is nil.

How to zoom particular part of UIScrollView?

HI,
I develop an application in which I want to implement the splash screen, on that splash screen I want to bind the scrollView and UIImage. My code as follow,
-(void)splashAnimation{
window = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, 320, 420)];
//scrollView = [[UIScrollView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
scrollView = [[UIScrollView alloc] initWithFrame:[window bounds]];
scrollView.pagingEnabled = NO;
scrollView.bounces = NO;
UIImage *image = [UIImage imageNamed:#"splash.png"];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
imageView.userInteractionEnabled = NO;
[scrollView addSubview:imageView];
[scrollView setDelegate:self];
//[scrollView release];
}
- (void)applicationDidFinishLaunching:(UIApplication *)application {
[self splashAnimation];
[self initControllers];
[window addSubview:[mainTabBarController view]];
[window makeKeyAndVisible];
}
On my given code the one blank window comes up and stay on.
I want to on that blank screen bind my splash.png.
****The Above problem is solved****
My current code is
scrollView.pagingEnabled = NO;
scrollView.bounces = NO;
UIImage *image = [UIImage imageNamed:#"splash.png"];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
imageView.userInteractionEnabled = NO;
[scrollView addSubview:imageView];
scrollView.maximumZoomScale = 4.0f;
scrollView.minimumZoomScale = 1.0f;
CGRect rect = CGRectMake(119, 42, 208, 166);
[scrollView zoomToRect:rect animated:YES];
[scrollView setDelegate:self];
[window addSubview:scrollView];
[window makeKeyAndVisible];
I want to zoom the particular part of scrollView.
RajB - for your zooming of the scrollView do this:
CGRect zoomRect = CGRectMake(119, 42, 208, 166);
[scrollView zoomToRect:zoomRect animated:YES];
Hope this helps!
You create a UIScrollView but never add it to the view hierarchy, therefore it will never get displayed. Call [window addSubview:scrollView], and then don't forget to release it.
If you are using a MainWindow.xib in your project, your window is created for you, you do not need to create your own.
Use [[UIScreen mainScreen] instead of CGRect(0, 0, 320, 420) <- I also believe you meant "480"
After setting up your splash animation, you call [window addSubview:[mainTabBarController view]]. Even after adding your scrollview as previously mentioned, this will then become the topmost and therefore visible view.
Delay the [window addSubview:[mainTabBarController view]] until after your splash animation completes.

Why does this code from iPhone Developer's Cookbook work?

I've been trying out some of the view code from Erica Sadun's book "The iPhone Developer's Cookbook" and found some code I don't understand. Here's the code for a loadView method:
- (void)loadView
{
// Create the main view
UIView *contentView = [[UIView alloc] initWithFrame:
[[UIScreen mainScreen] applicationFrame]];
contentView.backgroundColor = [UIColor whiteColor];
self.view = contentView;
[contentView release];
// Get the view bounds as our starting point
CGRect apprect = [contentView bounds];
// Add each inset subview
UIView *subview = [[UIView alloc]
initWithFrame:CGRectInset(apprect, 32.0f, 32.0f)];
subview.backgroundColor = [UIColor lightGrayColor];
[contentView addSubview:subview];
[subview release];
}
My question is why does she release contentView, but then use it again in [contentView addSubview:subview]? Has self.view = contentView retained contentView?
If you look in the documentation for UIViewController, you'll see that the view property is declared as:
#property(nonatomic, retain) UIView *view;
This means that when you use the setView: method (or use .view on the left hand side of the =), then whatever value you pass in will be retained. So, if you go through the code and look at retain counts, you'll get this:
- (void)loadView {
// Create the main view
UIView *contentView = [[UIView alloc] initWithFrame:
[[UIScreen mainScreen] applicationFrame]]; //retain count +1
contentView.backgroundColor = [UIColor whiteColor]; //retain count +1
self.view = contentView; //retain count +2
[contentView release]; //retain count +1
// Get the view bounds as our starting point
CGRect apprect = [contentView bounds];
// Add each inset subview
UIView *subview = [[UIView alloc]
initWithFrame:CGRectInset(apprect, 32.0f, 32.0f)];
subview.backgroundColor = [UIColor lightGrayColor];
[contentView addSubview:subview];
[subview release];
}
I'd say that the really interesting thing is that after releasing contentView, we can still send messages to it, because the object living at the end of contentView's pointer still exists (since it was retained by calling setView:).
If u declare ur property like so
#property(nonatomic,retain) ...
TheN yes the property is retained when assigned. that is probably what's going on