I have the following MasterViewController:
- (id) init{
self = [super init];
if(self){
//self.title = #"Main Menu";
//self.clearsSelectionOnViewWillAppear = NO;
self.contentSizeForViewInPopover = CGSizeMake(320.0, 600.0);
UIImageView* imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"view-1_0000s_0000_Muskoka-Logo1"]];
self.navigationItem.titleView = imageView;
self.tableView.backgroundColor = [UIColor clearColor];
self.tableView.opaque = NO;
self.tableView.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"view-1_0002s_0003s_0001_Bottom-panel"]];
self.tableView.scrollEnabled = NO;
}
return self;
}
It crashes when I try to set the background colour of the tableviewcontroller because the tableview inside the master is null. The image there is not null of course.
My only guess is that [super init] is not working properly?
A view controller's views and subviews do not exist until they have been loaded, which will occur during loadView (where the view hierarchy is built either in code or from a xib) All of those customisations should be in viewDidLoad. I'm surprised it's crashing, though, messages to nil don't cause crashes.
Related
I have a view controller animating in from the left edge of screen, and this view controller has a UITableView subview.
On every device and orientation except for one (iPhone X in landscape), this table view shows properly.
On the iPhone X in landscape, the table view is in the correct place but its cells do not populate until you scroll the tableView. Once you scroll, the table view is as if it had been there the whole time but with invisible cells.
This constraint causes the cells to not load:
[tableView.leftAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.leftAnchor].active = YES;
And when replacing this constraint with the following, the problem is solved as well:
[tableView.leftAnchor constraintEqualToAnchor:self.view.leftAnchor].active = YES;
I've made the background of the UITableView red to show that it is correctly placed, but no rows are showing even though they load in the portrait orientation.
I've also tried leaving it as:
[tableView.leftAnchor constraintEqualToAnchor:self.view.leftAnchor].active = YES;
but doing:
[tableView setContentInsetAdjustmentBehavior:UIScrollViewContentInsetAdjustmentNever];
which solves the problem for header cells:
but not content cells:
This code causes the same issue:
[tableView setInsetsContentViewsToSafeArea:YES];
I am setting up my regular cells like this :
-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if([reuseIdentifier isEqual: #"LayerCell"]) {
_titleLabel = [[UILabel alloc] init];
_imgView = [[UIImageView alloc] init];
_toggleView = [[UIImageView alloc] init];
[_imgView setTranslatesAutoresizingMaskIntoConstraints:NO];
[self addSubview:_imgView];
[_imgView.heightAnchor constraintEqualToAnchor:self.heightAnchor multiplier:0.8].active = YES;
[_imgView.widthAnchor constraintEqualToAnchor:self.heightAnchor multiplier:0.8].active = YES;
[_imgView.centerYAnchor constraintEqualToAnchor:self.centerYAnchor].active = YES;
[_imgView.leftAnchor constraintEqualToAnchor:self.leftAnchor constant:8].active = YES;
[_imgView setContentMode:UIViewContentModeScaleAspectFit];
[self addSubview:_toggleView];
[_toggleView setTranslatesAutoresizingMaskIntoConstraints:NO];
[_toggleView.heightAnchor constraintEqualToAnchor:_imgView.heightAnchor].active = YES;
[_toggleView.widthAnchor constraintEqualToAnchor:_imgView.widthAnchor].active = YES;
[_toggleView.centerYAnchor constraintEqualToAnchor:_imgView.centerYAnchor].active = YES;
[_toggleView.rightAnchor constraintEqualToAnchor:self.rightAnchor constant:-10].active = YES;
[_toggleView setContentMode:UIViewContentModeScaleAspectFit];
[self addSubview:_titleLabel];
[_titleLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
[_titleLabel.heightAnchor constraintEqualToConstant:20].active = YES;
[_titleLabel.centerYAnchor constraintEqualToAnchor:_imgView.centerYAnchor].active = YES;
[_titleLabel.rightAnchor constraintEqualToAnchor:_toggleView.leftAnchor constant:-10].active = YES;
[_titleLabel.leftAnchor constraintEqualToAnchor:_imgView.rightAnchor constant:10].active = YES;
[self layoutIfNeeded];
}
return self;
}
I'm trying to add an imageView in the ScrollView but I always get the ScrollView empty. Please where would be my issue? While I have added the delegate method <UIScrollViewDelegate> also made the connection in the storyboard.
My code:
- (void) viewDidLoad {
[super viewDidLoad];
[self slider];
}
-(void) slider {
_scrlView = [[UIScrollView alloc]init];
_scrlView.backgroundColor = [UIColor blackColor];
_scrlView.pagingEnabled = YES;
_scrlView.delegate = self;
_scrlView.showsHorizontalScrollIndicator = false;
_scrlView.layer.cornerRadius = 2;
_scrlView.contentSize = CGSizeMake(_scrlView.frame.size.width * 3, _scrlView.frame.size.height);
_img1 = [[UIImageView alloc] initWithFrame:CGRectMake((_scrlView.frame.size.width*0),0,_scrlView.frame.size.width,_scrlView.frame.size.height)];
_img2 = [[UIImageView alloc] initWithFrame:CGRectMake((_scrlView.frame.size.width*1),0,_scrlView.frame.size.width,_scrlView.frame.size.height)];
_img3 = [[UIImageView alloc] initWithFrame:CGRectMake((_scrlView.frame.size.width*2),0,_scrlView.frame.size.width,_scrlView.frame.size.height)];
_img1 = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"1234.jpg"]];
_img2 = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"1234.jpg"]];
_img3 = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"1234.jpg"]];
[_scrlView addSubview:_img1];
[_scrlView addSubview:_img2];
[_scrlView addSubview:_img3];
}
First, you don't add the scrollView to any view, so it won't be presented on screen.
Second, this:
_scrlView = [[UIScrollView alloc]init];
creates a scrollView with CGRectZero which is the same like writing:
_scrlView = [[UIScrollView alloc] initWithFrame:CGRectMake(0,0,0,0)];
This means the contentSize is also CGRectZero.
Edit: If you don't want to override the creation of the scrollView (because you have already set it in Interface Builder), remove the line _scrlView = [[UIScrollView alloc]init];.
But if you are using Auto Layout in the storyboard you should call [self slider] in viewDidLayoutSubviews.
You need to set frame first, for getting its width and height,
- (void)viewDidLoad {
[super viewDidLoad];
[self slider];
}
-(void)slider{
_scrlView = [[UIScrollView alloc] initWithFrame:CGRectMake(YOUR_X, YOUR_X, YOUR_WIDTH, YOUR_HIEGHT)];
// do this if you have not added Scrollview in storyboard, if Added, then no need to invoke, init by line [[UIScrollView alloc] init] ;
...
...
[self.view addSubview:_scrlView];
}
I would suggest one more thing, to call your slider method from viewDidAppear method of UIView
Enjoy Coding !!
You need to allocate the ScrollView if have not used a storyboard. Also in that case, specify a frame:
_scrlView = [[UIScrollView alloc] initWithFrame:CGRectMake(0,0,self.view.frame.size.width,self.view.frame.size.height)];
You are reallocating the imageviews, try to set image after allocating it once.
Another thing : Dont init scrollview again.
- (void)viewDidLoad {
[super viewDidLoad];
[self slider];
}
-(void)slider{
_scrlView.backgroundColor = [UIColor blackColor];
_scrlView.pagingEnabled = YES;
_scrlView.delegate = self;
_scrlView.showsHorizontalScrollIndicator = false;
_scrlView.layer.cornerRadius = 2;
_scrlView.contentSize = CGSizeMake(_scrlView.frame.size.width * 3, _scrlView.frame.size.height);
_img1 = [[UIImageView alloc] initWithFrame:CGRectMake((_scrlView.frame.size.width*0),0,_scrlView.frame.size.width,_scrlView.frame.size.height)];
_img2 = [[UIImageView alloc] initWithFrame:CGRectMake((_scrlView.frame.size.width*1),0,_scrlView.frame.size.width,_scrlView.frame.size.height)];
_img3 = [[UIImageView alloc] initWithFrame:CGRectMake((_scrlView.frame.size.width*2),0,_scrlView.frame.size.width,_scrlView.frame.size.height)];
[_img1 setImage:[UIImage imageNamed:#"1234.jpg"]];
[_img2 setImage:[UIImage imageNamed:#"1234.jpg"]];
[_img3 setImage:[UIImage imageNamed:#"1234.jpg"]];
[_scrlView addSubview:_img1];
[_scrlView addSubview:_img2];
[_scrlView addSubview:_img3];
}
My reply would be
if you are not using Storyboard or Interface builder , also autolayout is unchecked, set the frame of uiscrollview after its allocation and use alloc init only one time for one image. Add image on scrollview and scrollview on superview
if you are not using Storyboard or Interface builder and autolayout is checked, then put proper constraints on scrollview and imageviews. Read this
https://developer.apple.com/library/ios/technotes/tn2154/_index.html
I have a UITableView with custom UITableViewCells. The content of the cell is kept in a separate class extending UIView (i have 3 kind of contents which i switch by hiding and showing views, i took this approach because of the way i wanted to make the transition between cells).
So let's assume i have one of the views visible and added to the contentView of the cell. This view contains some text and some rectangles made of UIViews. Everything good till now, but the weird thing is when i touch the cell, the rectangles simply disappears, the text stays the same. Do you know what might be the problem? I tried to add the view to the backgroundView as well, it's doing the same.
- (id) initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.active = NO;
state = -1;
// Touch is not working if the view has no bounds
self.backgroundView = [[UIView alloc] init];
self.backgroundColor = [UIColor clearColor];
self.selectedBackgroundView = [[UIView alloc] init];
self.selectedBackgroundView.backgroundColor = [UIColor clearColor];
self.clipsToBounds = YES;
self.contentView.clipsToBounds = YES;
// Add empty view
emptyView = [[View1 alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height) andRadius:CELL_DOT_RADIUS];
emptyView.userInteractionEnabled = NO;
[self.backgroundView addSubview:emptyView];
The view:
- (id) initWithFrame:(CGRect)frame andRadius:(int)r {
self = [super initWithFrame:frame]; radius = r;
if (self) {
int outerlineWeight = 1;
timelineView = [[UIView alloc] initWithFrame:CGRectMake(frame.size.width/4, frame.size.height/2, 1, 1)];
[self addSubview:timelineView];
dotView = [[UIView alloc] initWithFrame:CGRectMake(frame.size.width/4-radius, frame.size.height/2-radius, radius*2, radius*2)];
dotView.layer.cornerRadius = radius;
dotView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
[self addSubview:dotView];
UIView *n = [[UIView alloc] initWithFrame:CGRectMake(160, 0, 50, 20)];
n.backgroundColor = [UIColor redColor];
[self addSubview:n];
middleText = [[UILabel alloc] initWithFrame:dotView.frame];
middleText.font = [UIFont systemFontOfSize:12];
middleText.textColor = [UIColor grayColor];
middleText.backgroundColor = [UIColor clearColor];
middleText.textAlignment = NSTextAlignmentCenter;
[self addSubview:middleText];
This are the sources so you can try for yourself if you want. As you can see the orange rectangle disappears but the text not. For what i need to do nothing should disappear, in the best case i want to change their colours. http://ge.tt/6wRBObD1/v/0?c
You are adding it to background view. When selected the selected background view will display not background view. In your custom cell try
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
if (selected) {
[self.backgroundView addSubview:emptyView];
}
else{
[self.selectedBackgroundView addSubview:emptyView];
}
// Configure the view for the selected state
}
Or add empty view to contentview
one thing for frame settings u need to override "layoutsubviews" method ...
in custom cell
init all the views in initialisation method i,e ur - (id) initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier method and add it to cell
in - (void)layoutSubviews just set the frame for ur views in the cell,
use tag property to access the views in the layoutsubviews, if it is not the property
- (id) initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.active = NO;
state = -1;
// Touch is not working if the view has no bounds
self.backgroundView = [[UIView alloc] init];
self.backgroundColor = [UIColor clearColor];
self.selectedBackgroundView = [[UIView alloc] init];
self.selectedBackgroundView.backgroundColor = [UIColor clearColor];
self.clipsToBounds = YES;
self.contentView.clipsToBounds = YES;
// Add empty view
//emptyView = [[View1 alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height) andRadius:CELL_DOT_RADIUS];//dont set the frame heare do it layoutsubviews
emptyView = [[View1 alloc] init];
emptyView.userInteractionEnabled = NO;
emptyView.tag = 100;
[self.backgroundView addSubview:emptyView];
- (void)layoutSubviews
{
[super layoutSubviews];
UIView *emptyView = [self viewWithTag:100];//your background view heare u can get the frame values for ur cell
emptyView.frame = self.bounds;//better do it for other views in cell also
//test it by setting some background color
}
Hope this helps u ...:)
Ok, so like i've said in my last comment the backgroundColor of any subview is the problem, in the selected state is cleared. For cells created in interface builder the problem does not occurs, my cells are created programatically.
I fixed this by drawing with CoreGraphics in drawRect method.
As with a UICollectionView a UITableView has a background view that is build before AutoLayout. If you use autoLayout you should make sure the backgroundView has a frame. Otherwise is will disappear.
In your cell subclass you can do:
-(void)setBackgroundView:(UIView *)backgroundView
{
super.backgroundView = backgroundView;
self.backgroundView.translatesAutoresizingMaskIntoConstraints = NO;
[self.backgroundView autoPinEdgesToSuperviewEdgesWithInsets:UIEdgeInsetsZero];
}
In swift you need to declare viewcontroller object globally that would result in Strong, in case if you declare locally it results in keep disappearing the cells.
var refineViewController : RefineViewController?
then you can access that controller using below code that would not result in disappearing cells.
func showRefineView(isFindHomeTab isFindHomeTab : Bool){
refineViewController = RefineViewController(nibName: String(BaseGroupedTableVC),bundle : nil)
refineViewController!.refineSearchDelegate = self
refineViewController!.view.frame = CGRectMake(0, -490, self.view.frame.size.width, self.view.frame.size.height)
UIView.animateWithDuration(0.3, delay: 0.0, options: .CurveEaseOut, animations:
{
self.refineViewController!.view.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)
self.refineViewController!.isFindHomeTab = isFindHomeTab
}, completion: nil)
self.view.addSubview(refineViewController!.view)
}
I have a UITableView which has some custom styling. This table view appears in two places in the app, one of which is inside a UIPopoverController. However when the tableview is inside the popover it takes on the default tableview styling as stated in the UI Transition Guide under "Popover".
The problem I have is that there appears to be nowhere to change this behaviour. Regardless of where I try and modify properties of the tableview the view inside the popover doesn't change.
Anyone dealt with this issue before or have any ideas?
Here is the init method of LibraryProductView where I create the table view:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.sectionOrdering = [NSArray arrayWithObjects:
[NSNumber numberWithInt:LIBRARY_PRODUCT_SECTION_DESCRIPTION],
[NSNumber numberWithInt:LIBRARY_PRODUCT_SECTION_DOCUMENTS],
[NSNumber numberWithInt:LIBRARY_PRODUCT_SECTION_ACTIVE_INGREDIENTS],
[NSNumber numberWithInt:LIBRARY_PRODUCT_SECTION_RELATED_PRODUCTS],
[NSNumber numberWithInt:LIBRARY_PRODUCT_SECTION_RELATED_DOCUMENTS], nil];
self.backgroundColor = [UIColor whiteColor];
self.tableView = [[UITableView alloc] initWithFrame:CGRectInset(self.bounds, 10, 0) style:UITableViewStyleGrouped];
self.tableView.backgroundColor = [UIColor whiteColor];
self.tableView.dataSource = self;
self.tableView.delegate = self;
self.tableView.separatorColor = [UIColor clearColor];
self.tableView.showsVerticalScrollIndicator = NO;
[self addSubview:self.tableView];
}
return self;
}
Here is where the containing view (LibraryProductView) is added to the popover:
- (IBAction)didTouchInformationButton:(id)sender
{
if (_infoPopover != nil && _infoPopover.isPopoverVisible)
{
[_infoPopover dismissPopoverAnimated:YES];
return;
}
CGSize preferredSize = CGSizeMake(600.0f, 500.0f);
LibraryProductViewController* productController = [[[LibraryProductViewController alloc] initWithPreferredSize:preferredSize] autorelease];
productController.filterByMyCompany = NO;
productController.product = _activityInput.product;
UINavigationController* nav = [[[UINavigationController alloc] initWithRootViewController:productController] autorelease];
nav.title = _activityInput.product.name;
RELEASE(_infoPopover);
_infoPopover = [[UIPopoverController alloc] initWithContentViewController:nav];
_infoPopover.popoverContentSize = CGSizeMake(preferredSize.width, preferredSize.height + 46);
[_infoPopover presentPopoverFromRect:_infoButton.frame inView:_infoButton permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES];
}
The LibraryProductView is created within viewDidLoad method of LibraryProductViewController.
- (void)viewDidLoad
{
[super viewDidLoad];
self.libraryProductView = [[LibraryProductView alloc] initWithFrame:(usingPreferredSize ? CGRectMake(0.0, 0.0, preferredSize.width, preferredSize.height) : self.view.bounds)];
self.libraryProductView.dataSource = self;
self.libraryProductView.delegate = self;
[self.view addSubview:self.libraryProductView];
}
To set properties for the TableView you might do so in
- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
[tableView setBackgroundColor:[UIColor redcolor]];
[tableView setSeparatorColor: [UIColor blueColor]];
return 1;
}
This, of course, assumes you have set UITableViewDataSource in your .h file
I've used UITapGestureRecognizer tons of times, but in this case I'm getting EXC_BAD_ACCESS when a tap occurs. I think it has to do with the fact that I'm adding it to an Alert-type overlay view. And for some reason the overlay view isn't getting retained even though it's on-screen.
I'm creating the view like this:
HelperView *testHelper = [HelperView helperWithBodyText:#"test text"];
[testHelper presentAtPoint:screenCenter];
The convenience method in HelperView.m looks like this:
+ (id)helperWithBodyText:(NSString*)text
{
return [[self alloc] initWithFrame:CGRectZero bodyText:text];
}
And the rest of the code looks like this:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.container = [[AGWindowView alloc] initAndAddToKeyWindow];
self.container.supportedInterfaceOrientations = UIInterfaceOrientationMaskLandscapeRight;
self.overlay = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
self.overlay.backgroundColor = [UIColor redColor];
self.overlay.alpha = 0.6;
[self.container addSubviewAndFillBounds:self.overlay]; //this fills the screen with a transparent red color, for testing
UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(dismissMe:)];
[self.overlay addGestureRecognizer:tap]; //I want to dismiss the whole view if the overlay is tapped
self.content = [[UIView alloc] initWithFrame:CGRectZero];
}
return self;
}
- (id)initWithFrame:(CGRect)frame bodyText:(NSString*)bodyText
{
self = [self initWithFrame:frame];
if (self) {
//TEST frame
self.content.frame = CGRectMake(0, 0, 217, 134);
// Initialization code
UIImage *bgImage = [[UIImage imageNamed:#"helper-bg"]
resizableImageWithCapInsets:UIEdgeInsetsMake(30, 28, 20, 20)];
UIImageView *bgImgView = [[UIImageView alloc] initWithImage:bgImage];
bgImgView.bounds = self.content.frame;
[self.content addSubview:bgImgView];
}
return self;
}
- (void)presentAtPoint:(CGPoint)loc
{
CGPoint newPoint = [self.container convertPoint:loc toView:self.container];
self.content.center = newPoint;
[self.container addSubview:self.content];
}
- (void)dismissMe:(UITapGestureRecognizer*)recognizer
{
//this never happens - I get EXC_BAD_ACCESS when I tap the overlay
}
HelperView is not the view getting displayed and it's not getting retained, but you're using as the target for the gesture recognizer. The AGWindowView property "container" is getting displayed and retained by its superview. Your code needs refactoring since you have this view HelperView that doesn't ever display anything itself, but if you want it to work like this you need to retain HelperView so it doesn't automatically get released. You can do this by assigning it to a strong instance variable.