UIButton embeded in UIVIew no responsible - ios

I have a problem
i created 6 UIButtons put them in a UIView1
then put the UIView1 into another UIView2
then return UIView2 as UITableView.tableHeaderView
now the problem is when i touch the buttons
no responsiblity
here is some information
1. UIButtons UIView1 UIView2 fremes are these
2017-06-04 16:26:40.014 LOLHelper[8590:223132] BUT frame is :8.000000 8.000000 70.500000 18.000000
2017-06-04 16:26:40.014 LOLHelper[8590:223132] BUT frame is :86.500000 8.000000 71.000000 18.000000
2017-06-04 16:26:40.014 LOLHelper[8590:223132] BUT frame is :165.500000 8.000000 70.500000 18.000000
2017-06-04 16:26:40.015 LOLHelper[8590:223132] BUT frame is :244.000000 8.000000 70.500000 18.000000
2017-06-04 16:26:40.015 LOLHelper[8590:223132] BUT frame is :322.500000 8.000000 71.000000 18.000000
2017-06-04 16:26:40.015 LOLHelper[8590:223132] BUT frame is :401.500000 8.000000 70.500000 18.000000
2017-06-04 16:26:40.015 LOLHelper[8590:223132] SubView frame is: :-3.000000 0.000000 480.000000 20.000000
2017-06-04 16:26:40.015 LOLHelper[8590:223132] headerView frame is: :0.000000 0.000000 320.000000 20.000000
2.i turn on the userInteractionEnabled of UIButtons UIView1 UIView2 , u can see in the code :
#import "TableViewDataSource.h"
#implementation TableViewDataSource
#synthesize tableView;
#synthesize tableCell;
#synthesize LHfetchedResultsController;
#synthesize numberOfRows;
#synthesize dataTemp;
#synthesize paused;
#synthesize type;
#synthesize imgAche;
#synthesize cellHeight;
#synthesize subHeaderViewFrame;
-(id)initWithTableView:(UITableView *) tableView
{
self = [super init];
if (self) {
self.tableView = tableView;
self.tableView.dataSource = self;
self.tableView.delegate = self;
self.tableView.tableHeaderView = [self setHeaderView];
}
return self;
}
-(UIView *)setHeaderView
{
CGSize screenSize = [UIScreen mainScreen].bounds.size;
UIView * container = [[UIView alloc] init];
container.frame = CGRectMake(0, 0, screenSize.width, 20);
container.userInteractionEnabled = YES;
UIView * headerView = [[UIView alloc] init];
headerView.frame = CGRectMake(0, 0, screenSize.width*1.5, 20);
headerView.tag = 01;
headerView.userInteractionEnabled = YES;
[container addSubview:headerView];
for (int i = 1; i < 7; i++) {
UIButton * button = [[UIButton alloc] init];
button.tag = i+10;
button.titleLabel.font = [UIFont boldSystemFontOfSize:12];
[button setTitle:[NSString stringWithFormat:#"but0%d",i] forState:UIControlStateNormal];
[button setTitle:[NSString stringWithFormat:#"but0%d s",i] forState:UIControlStateSelected];
[button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
button.translatesAutoresizingMaskIntoConstraints = NO;
[button setTitleColor:[UIColor brownColor] forState:UIControlStateSelected];
button.enabled = YES;
button.userInteractionEnabled = YES;
[headerView addSubview:button];
}
UIButton *button01 = [headerView viewWithTag:11];
UIButton *button02 = [headerView viewWithTag:12];
UIButton *button03 = [headerView viewWithTag:13];
UIButton *button04 = [headerView viewWithTag:14];
UIButton *button05 = [headerView viewWithTag:15];
UIButton *button06 = [headerView viewWithTag:16];
NSDictionary * views = NSDictionaryOfVariableBindings(button01,button02,button03,button04,button05,button06);
NSString * vflV1 = #"V:|-1-[button01]-1-|";
NSString * vflV2 = #"V:|-1-[button02]-1-|";
NSString * vflV3 = #"V:|-1-[button03]-1-|";
NSString * vflV4 = #"V:|-1-[button04]-1-|";
NSString * vflV5 = #"V:|-1-[button05]-1-|";
NSString * vflV6 = #"V:|-1-[button06]-1-|";
NSString * vflH1 = #"H:|-[button01]-[button02(==button01)]-[button03(==button01)]-[button04(==button01)]-[button05(==button01)]-[button06(==button01)]-|";
NSArray * constraintsV1 = [NSLayoutConstraint constraintsWithVisualFormat:vflV1 options:0 metrics:NULL views:views];
NSArray * constraintsV2 = [NSLayoutConstraint constraintsWithVisualFormat:vflV2 options:0 metrics:NULL views:views];
NSArray * constraintsV3 = [NSLayoutConstraint constraintsWithVisualFormat:vflV3 options:0 metrics:NULL views:views];
NSArray * constraintsV4 = [NSLayoutConstraint constraintsWithVisualFormat:vflV4 options:0 metrics:NULL views:views];
NSArray * constraintsV5 = [NSLayoutConstraint constraintsWithVisualFormat:vflV5 options:0 metrics:NULL views:views];
NSArray * constraintsV6 = [NSLayoutConstraint constraintsWithVisualFormat:vflV6 options:0 metrics:NULL views:views];
NSArray * constraintsH1 = [NSLayoutConstraint constraintsWithVisualFormat:vflH1 options:0 metrics:NULL views:views];
[headerView addConstraints:constraintsV1];
[headerView addConstraints:constraintsV2];
[headerView addConstraints:constraintsV3];
[headerView addConstraints:constraintsV4];
[headerView addConstraints:constraintsV5];
[headerView addConstraints:constraintsV6];
[headerView addConstraints:constraintsH1];
return container;
}
i have not find the reason
anyone could help me?
i also add some UISwipeGestureRecognizer into UIView2
thank u

Thank u Guys
i got the solution
reason is that
[button addTarget:NULL action:#selector(click:) forControlEvents:UIControlEventTouchUpInside];
i set target NULL, and write click: in the same file, but actually i get the table from the main controller, so when i click button, xcode will find click: in the main controller, then can not find, so no responsibility.
after i set target self or write click: in main controller
it works

Related

Objective-C - is there any way to have UIView property as array?

I need to access the UIView array items (where all UIView will have its own independent activity). But while assigning as #property (assign, nonatomic) UIView *ui_view[MAXIMUM_UIVIEW];, its causing the build to fail.
is there anyway to make it work the way i am trying or some other better way?
ERROR:
CODE:
#import "ViewController.h"
const int MAXIMUM_UIVIEW = 50;
#interface ViewController ()
#property (assign, nonatomic) UIView *ui_view[MAXIMUM_UIVIEW];
#property (assign, nonatomic) NSInteger phone_height;
#property (assign, nonatomic) NSInteger phone_width;
-(void)func_draw_wall:(int)argument_count;
#end
#implementation ViewController
-(void)ui_button_submit:(UIButton*)sender {
int __chronological__;
//UIView *ui_view[MAXIMUM_UIVIEW];
//int phone_height = self.view.frame.size.height;
//int phone_width = self.view.frame.size.width;
int phone_height = self.view.frame.size.height;
int phone_width = self.view.frame.size.width;
self.phone_height = phone_height;
self.phone_width = phone_width;
for (__chronological__ = 0 ; __chronological__ <= 50 ; __chronological__++ ) {
[self func_draw_wall:__chronological__];
}
}
-(void)func_draw_wall:(int)__chronological__ {
self.ui_view[__chronological__] =
[[UIView alloc] initWithFrame:CGRectMake(0, 0, 50,50)];
[self.view addSubview:self.ui_view[__chronological__]];
NSLog(#"Mem Address of localView[%d] = %x\n", __chronological__, self.ui_view);
}
-(void)ui_button {
self.view.backgroundColor = [UIColor blackColor];
UIButton *but = [[UIButton alloc] init];
[but setTitle:#"--- Add ---" forState:UIControlStateNormal];
[but setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
[but addTarget:self action:#selector(ui_button_submit:)
forControlEvents:UIControlEventTouchUpInside];
int startHeight = 167;
int frameHeight = self.view.frame.size.height - startHeight;
[but setFrame:CGRectMake(0, startHeight, 320, frameHeight)];
[but setTranslatesAutoresizingMaskIntoConstraints:false];
[but setImage:[UIImage imageNamed:#"Image"] forState:UIControlStateNormal];
[self.view addSubview:but];
NSDictionary *viewsDict = #{#"button" : but};
[self.view addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:#"V:[button]-0-|"
options:0 metrics:nil views:viewsDict]];
NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:but
attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual
toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0
constant:0];
constraint.active = true;
[self.view addConstraint:constraint];
[self.view layoutIfNeeded];
}
- (void)viewDidLoad {
[super viewDidLoad];
[self ui_button];
}
#end
Make the type NSArray *, not UIView *[]
You should be able to use a generic type parameter, so NSArray<UIView *> *

View not found in container hierarchy crash while adding View constraints programatically

Although the crash message is very clear but I have checked my code and everything seems to be looking fine. My only worry is because I am setting constraints on a view which is being set as accessory view for keyboard, could that be a reason why entire view hierarchy is not set properly.
Here is what I am doing:
Step 1: Create a custom accessory view (a number bar from 0 to 9) and put it on top of regular keyboard.
MyAccessoryView *anAccessoryView = [[MyAccessoryView alloc] initWithFrame:CGRectMake(0, 0, 320, 46.0f)];
anAccessoryView.delegate = self;
self.textField.inputAccessoryView = anAccessoryView;
Step 2: In custom accessory view (subview of UIView), add buttons and related handling. Add them to super view and then call a method after a delay of 1 second to add constraints.
- (id)initWithFrame:(CGRect)iFrame {
if (self = [super initWithFrame:iFrame]) {
[self refresh];
self.autoresizingMask = UIViewAutoresizingFlexibleWidth;
}
[self setExclusiveTouch:YES];
return self;
}
- (void)refresh {
if (!self.layoutController) {
self.layoutController = [[MyAccessoryViewLayoutController alloc] init];
}
self.backgroundColor = [self.layoutController colorForNumericInputAccessory:self];
self.userInteractionEnabled = YES;
NSMutableArray *buttonsArray = [NSMutableArray arrayWithCapacity:10];
// Adding number keys to the accessory view and setting thier properties
for (NSInteger i = 1; i < 11; i++) {
MyAccessoryViewNumericButton *aKeyboardButton = [MyAccessoryViewNumericButton buttonWithType:UIButtonTypeCustom];
aKeyboardButton.tag = i;
aKeyboardButton.frame = CGRectMake(0, 0, 32.0, 44);
[aKeyboardButton setTitle: [NSString stringWithFormat:#"%ld", (long)i % 10] forState:UIControlStateNormal];
NSString *aButtonImageTitle = [self.layoutController buttonNormalStateImageNameForIndex:(i % 10) forNumericInputAccessory:self];
[aKeyboardButton setBackgroundImage:[UIImage imageNamed:aButtonImageTitle] forState:UIControlStateNormal];
aKeyboardButton.backgroundColor = [UIColor clearColor];
[aKeyboardButton setTitleColor:[UIColor blackColor] forState: UIControlStateNormal];
[aKeyboardButton setExclusiveTouch:YES];
aKeyboardButton.titleLabel.font = [self.layoutController fontForButtonTitlesForNumericInputAccessory:self];
if (self.layoutController.interfaceIdiom == UIUserInterfaceIdiomPhone) {
aKeyboardButton.titleLabel.textAlignment = NSTextAlignmentCenter;
} else {
NSString *aButtonHighlightedImageTitle = [self.layoutController buttonHighlightedStateImageNameForIndex:(i % 10) forNumericInputAccessory:self];
[aKeyboardButton setBackgroundImage:[UIImage imageNamed:aButtonHighlightedImageTitle] forState:UIControlStateHighlighted];
}
aKeyboardButton.hidden = NO;
aKeyboardButton.enabled = YES;
aKeyboardButton.tag = i;
[aKeyboardButton addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:aKeyboardButton];
[buttonsArray addObject:aKeyboardButton];
if (self.layoutController.interfaceIdiom == UIUserInterfaceIdiomPhone) {
UIImage *aPressedButtonImage = [UIImage imageNamed:[self.layoutController buttonHighlightedStateImageNameForIndex:(i % 10) forNumericInputAccessory:self]];
CGRect aPressedButtonViewFrame = [self.layoutController frameForPressedButtonViewWithIndex:(i % 10) forNumericInputAccessory:self];
UIView *aPressedButtonView = [[UIView alloc] initWithFrame:aPressedButtonViewFrame];
aPressedButtonView.backgroundColor = [UIColor clearColor];
aPressedButtonView.userInteractionEnabled = YES;
aPressedButtonView.hidden = YES;
UIImageView *aPressedButtonImageView = [[UIImageView alloc] initWithImage:aPressedButtonImage];
aPressedButtonImageView.frame = CGRectMake(0.0, 0.0, aPressedButtonViewFrame.size.width, aPressedButtonViewFrame.size.height);
aPressedButtonImageView.contentMode = UIViewContentModeBottom;
aPressedButtonImageView.backgroundColor = [UIColor clearColor];
CGRect aPressedButtonLabelFrame = [self.layoutController frameForPressedButtonLabelWithIndex:(i % 10) forNumericInputAccessory:self];
UILabel *aPressedButtonLabel = [[UILabel alloc] initWithFrame:aPressedButtonLabelFrame];
aPressedButtonLabel.backgroundColor = [UIColor clearColor];
aPressedButtonLabel.text = [NSString stringWithFormat: #"%ld", (long)i % 10];
aPressedButtonLabel.textAlignment = NSTextAlignmentCenter;
aPressedButtonView.tag = i + 100;
aPressedButtonLabel.font = [UIFont fontWithName: #"Helvetica-Bold" size: 44.0f];
aPressedButtonLabel.shadowColor = [UIColor colorWithRed: 0.95f green: 0.95f blue: 0.95f alpha: 1.0f];
aPressedButtonLabel.shadowOffset = CGSizeMake(0.0f, 0.75f);
if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication]statusBarOrientation])) {
aPressedButtonImageView.frame = CGRectMake(aPressedButtonImageView.frame.origin.x, aPressedButtonImageView.frame.origin.y - 2.0f, aPressedButtonImageView.frame.size.width, aPressedButtonImageView.frame.size.height);
}
[aPressedButtonView addSubview:aPressedButtonImageView];
[aPressedButtonView addSubview:aPressedButtonLabel];
[self addSubview:aPressedButtonView];
}
}
CALayer *aLightGreyBorder = [CALayer layer];
aLightGreyBorder.frame = CGRectMake(self.bounds.origin.x, self.bounds.origin.y + 1.0f, self.bounds.size.width, 1.0f);
UIColor *aColor = [UIColor colorWithRed:178.0f/255.0f green:184.0f/255.0f blue:191.0f/255.0f alpha:1.0f];
aLightGreyBorder.backgroundColor = [aColor CGColor];
[self.layer insertSublayer:aLightGreyBorder atIndex:0];
CALayer *aDarkGreyBorder = [CALayer layer];
aDarkGreyBorder.frame = CGRectMake(self.bounds.origin.x, self.bounds.origin.y, self.bounds.size.width, 1.0f);
UIColor *aSecondColor;
aSecondColor = [UIColor colorWithRed:100.0f/255.0f green:100.0f/255.0f blue:100.0f/255.0f alpha:1.0f];
aDarkGreyBorder.backgroundColor = [aSecondColor CGColor];
[self.layer insertSublayer:aDarkGreyBorder atIndex:0];
if (self.layoutController.interfaceIdiom == UIUserInterfaceIdiomPhone) {
for (UIView *aPressedButtonView in [self subviews]) {
if ([aPressedButtonView isMemberOfClass:[UIView class]]) {
[self bringSubviewToFront:aPressedButtonView];
}
}
}
// Now lets add constaints
[self performSelector:#selector(addConstraintsForButtons:) withObject:buttonsArray afterDelay:1.0];
}
Step 3: Add constraints to all buttons (0 to 9). Here, I am showing only first 2 buttons.
- (void)addConstraintsForButtons:(NSMutableArray *)iButtons {
// First Button
MyAccessoryViewNumericButton *firstButton = (MyAccessoryViewNumericButton *)iButtons[0];
// Left edge constraint for First button
NSLayoutConstraint *leading =[NSLayoutConstraint
constraintWithItem:firstButton
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeTrailing
multiplier:1.0f
constant:4.f];
[self addConstraint:leading];
// Middle in the super view
NSLayoutConstraint *vertical =[NSLayoutConstraint
constraintWithItem:firstButton
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeCenterY
multiplier:1.0f
constant:0];
[self addConstraint:vertical];
// Width-Height Constraint for First button
[self addWHContraintForButton:firstButton];
// Second Button
MyAccessoryViewNumericButton *secondButton = (MyAccessoryViewNumericButton *)iButtons[1];
// Left edge constraint for First button
NSLayoutConstraint *secondLeading =[NSLayoutConstraint
constraintWithItem:secondButton
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:firstButton
attribute:NSLayoutAttributeTrailing
multiplier:1.0f
constant:4.f];
[secondButton addConstraint:secondLeading];
// Middle in the super view
NSLayoutConstraint *secondVertical =[NSLayoutConstraint
constraintWithItem:secondButton
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:firstButton
attribute:NSLayoutAttributeCenterY
multiplier:1.0f
constant:0];
[secondButton addConstraint:secondVertical];
// Width-Height Constraint for Second button
[self addWHContraintForButton:secondButton];
// Add constaints to rest of the buttons...
}
- (void)addWHContraintForButton:(MyAccessoryViewNumericButton *)iButton {
CGFloat buttonWidth = 32.0f;
CGFloat buttonHeight = 44.0f;
// Height Constraint
NSLayoutConstraint *height = [NSLayoutConstraint
constraintWithItem:iButton
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:0
multiplier:0
constant:buttonHeight];
// Width Constraint
NSLayoutConstraint *width = [NSLayoutConstraint
constraintWithItem:iButton
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:0
multiplier:0
constant:buttonWidth];
[iButton addConstraint:height];
[iButton addConstraint:width];
}
But when I run this code, it crashes with following message:
View not found in container hierarchy: <MyAccessoryViewNumericButton: 0x7fb506036f90; baseClass = UIButton; frame = (0 0; 32 44); opaque = NO; tag = 1; layer = <CALayer: 0x7fb506039c70>>
That view's superview: <MyAccessoryView: 0x7fb503ddfb50; frame = (0 0; 320 46); autoresize = W; layer = <CALayer: 0x7fb503dc1fe0>>
This is what I see when debug this (tried by setting constraints in keyboardDidShow: and didMoveToSuperview methods):
(lldb) po [secondButton superview]
<MyAccessoryView: 0x7fcd6d04f6c0; frame = (0 0; 320 46); autoresize = W; layer = <CALayer: 0x7fcd6adf5ed0>>
(lldb) po [[secondButton superview] superview]
<UIInputSetHostView: 0x7fcd6d0346c0; frame = (0 522; 320 262); layer = <CALayer: 0x7fcd6adef270>>
(lldb) po [[[secondButton superview] superview] superview]
<UIInputSetContainerView: 0x7fcd6d014000; frame = (0 0; 320 568); layer = <CALayer: 0x7fcd6add78d0>>
(lldb) po [[[[secondButton superview] superview] superview] superview]
<UITextEffectsWindow: 0x7fcd6d033c30; frame = (0 0; 320 568); opaque = NO; autoresize = W+H; layer = <UIWindowLayer: 0x7fcd6d034250>>
(lldb) po [[[[[secondButton superview] superview] superview] superview] superview]
0x0000000000000000
Although view has a parent. Can someone please advise here.

Layout of custom UITableViewCell using Autolayout programmatically

I have a custom UITableViewCell that works great on iPhone 5s, however since this projected started we now have to update it to support iPhone 6 en iPhone 6 Plus as well.
I've solved most of these upgrade issues using Autolayout in my .xib files. This Cell however does not have a .xib so I Have to do everything programmatically. For clarity I've temporarily drawn a border around my problematic label
This is how it looks on iPhone 5S
This is how it looks on iPhone 6
These tableviews are expandable/collapsable. In the screenshot you see it expanded.
This is the relevant code:
#import "LotsDetailTableViewCell.h"
#import "MSCellAccessory.h"
#interface LotsDetailTableViewCell ()
#property (nonatomic, strong) NSArray *data;
#property (nonatomic, strong) UIView *detailView;
#end
const float LABEL_HEIGHT = 22.0f;
#implementation LotsDetailTableViewCell
- (id)initWithData:(NSArray *)data reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier];
if (self) {
self.data = data;
[self setupDetailView];
self.textLabel.textColor = RGB(39, 143, 191);
self.textLabel.font = [UIFont fontWithName:#"HelveticaNeue-Light" size:16.0];
self.autoresizingMask = UIViewAutoresizingFlexibleHeight;
self.clipsToBounds = true;
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
self.textLabel.frame = CGRectMake(self.textLabel.frame.origin.x,
self.textLabel.frame.origin.y,
self.textLabel.frame.size.width,
43.5f);
self.accessoryView.frame = CGRectMake(self.accessoryView.frame.origin.x, 6, 32, 32);
}
#pragma mark Detail View
- (void)setupDetailView
{
self.detailView = [[UIView alloc] init];
UILabel *previousLabel;
for (NSObject *detail in self.data) {
CGFloat frameY;
NSString *keyText;
NSString *valueText;
if([detail isKindOfClass:[NSString class]]){
keyText = #"";
valueText = (NSString *)detail;
} else if([detail isKindOfClass:[NSDictionary class]]){
keyText = ((NSDictionary *)detail)[#"key"];
valueText = [(NSDictionary *)detail objectForKey:#"value"];
}
if (previousLabel) {
frameY = previousLabel.frame.origin.y+previousLabel.frame.size.height;
} else {
frameY = self.frame.origin.y+44.0f+[self.data indexOfObject:detail]*LABEL_HEIGHT;
}
UILabel *keyLabel = [[UILabel alloc] initWithFrame:
CGRectMake(self.frame.size.width*.05, frameY, self.frame.size.width*.45, [self heightForValueLabel:valueText])
];
UILabel *valueLabel = [[UILabel alloc] initWithFrame:
CGRectMake(self.frame.size.width*.5, frameY, self.frame.size.width*.45, [self heightForValueLabel:valueText])
];
valueLabel.lineBreakMode = NSLineBreakByWordWrapping;
valueLabel.numberOfLines = 0;
keyLabel.lineBreakMode = NSLineBreakByWordWrapping;
keyLabel.numberOfLines = 0;
valueLabel.textAlignment = NSTextAlignmentRight;
keyLabel.font = [UIFont fontWithName:#"HelveticaNeue-Light" size:12.0];
valueLabel.font = [UIFont fontWithName:#"HelveticaNeue-Bold" size:12.0];
keyLabel.textColor = RGB(119, 119, 119);
valueLabel.textColor = RGB(39, 143, 191);
keyLabel.text = keyText;
valueLabel.text = valueText;
valueLabel.layer.borderColor = [RGB(178, 178, 178) CGColor];
valueLabel.layer.borderWidth = 1.0f;
[self.detailView addSubview:keyLabel];
[self.detailView addSubview:valueLabel];
previousLabel = valueLabel;
}
[self addSubview:self.detailView];
}
- (CGFloat)heightForValueLabel:(NSString *)text
{
return [[self class] heightForValueLabel:text width:self.frame.size.width*.5];
}
+ (CGFloat)heightForValueLabel:(NSString *)text width:(CGFloat)width
{
CGSize constrainedSize = CGSizeMake(width, CGFLOAT_MAX);
NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
[UIFont fontWithName:#"HelveticaNeue-Bold" size:12.0], NSFontAttributeName,
nil];
NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:text attributes:attributesDictionary];
CGRect requiredHeight = [string boundingRectWithSize:constrainedSize options:NSStringDrawingUsesLineFragmentOrigin context:nil];
return requiredHeight.size.height+5.0;
}
+ (CGFloat)heightForData:(NSArray*)data width:(CGFloat)width
{
CGFloat height = 0.0;
for (NSObject *detail in data) {
NSString *valueText;
if([detail isKindOfClass:[NSString class]]){
valueText = (NSString *)detail;
} else if([detail isKindOfClass:[NSDictionary class]]){
valueText = ((NSDictionary *)detail)[#"value"];
}
height = height + [self heightForValueLabel:valueText width:width];
}
return height;
}
#end
Most of the relevant drawing is performed in the setupDetailView method.
What I want: I want the label to be aligned to the right hand side of the tableviewcell to make best use of the available space.
What I tried: I've tried adding a NSLayoutConstraint programmatically in the setupDetailView using the following co
NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:valueLabel attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeRight multiplier:1.0 constant:1.0];
[valueLabel addConstraint:constraint];
[self needsUpdateConstraints];
but this has lead to run-time crashes.
If my problem can be easily solved without Autolayout I'm not opposed to that.
Edit: If I try to add the constraint, this is how it blows up:
2015-03-25 14:19:04.047 App[35277:10763464] The view hierarchy is not prepared for the constraint: <NSLayoutConstraint:0x7faf5049a630 UILabel:0x7faf50499a50'8050'.trailing == LotsDetailTableViewCell:0x7faf50494840'LotDetailInfoCell'.right + 1>
When added to a view, the constraint's items must be descendants of that view (or the view itself). This will crash if the constraint needs to be resolved before the view hierarchy is assembled. Break on -[UIView _viewHierarchyUnpreparedForConstraint:] to debug.
2015-03-25 14:19:04.048 App[35277:10763464] View hierarchy unprepared for constraint.
Constraint: <NSLayoutConstraint:0x7faf5049a630 UILabel:0x7faf50499a50'8050'.trailing == LotsDetailTableViewCell:0x7faf50494840'LotDetailInfoCell'.right + 1>
Container hierarchy:
<LotsDetailTableViewCell: 0x7faf50494840; baseClass = UITableViewCell; frame = (0 0; 320 44); layer = <CALayer: 0x7faf50494c50>>
| <UITableViewCellContentView: 0x7faf5049c070; frame = (0 0; 320 44); gestureRecognizers = <NSArray: 0x7faf504a2530>; layer = <CALayer: 0x7faf50455b60>>
View not found in container hierarchy: <UILabel: 0x7faf50499a50; frame = (156 44; 144 19.304); text = '8050'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7faf50499870>>
That view's superview: NO SUPERVIEW
2015-03-25 14:19:04.058 App[35277:10763464] *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to install constraint on view. Does the constraint reference something from outside the subtree of the view? That's illegal. constraint:<NSLayoutConstraint:0x7faf5049a630 UILabel:0x7faf50499a50'8050'.trailing == LotsDetailTableViewCell:0x7faf50494840'LotDetailInfoCell'.right + 1> view:<LotsDetailTableViewCell: 0x7faf50494840; baseClass = UITableViewCell; frame = (0 0; 320 44); layer = <CALayer: 0x7faf50494c50>>'
Give leftConstarint to your label, after adding it as subView.
[_label setTranslatesAutoresizingMaskIntoConstraints:NO];
NSLayoutConstraint *leftConstraint = [NSLayoutConstraint constraintWithItem:_label
attribute:NSLayoutAttributeLeft
relatedBy:NSLayoutRelationEqual
toItem:[_label superview]
attribute:NSLayoutAttributeLeft
multiplier:1.0
constant:10];
[_label addConstraint:leftConstraint];
[_label superview] must be your [self view]. //Might be.
Hope, it helps. :)
When adding constraints between subview and superview, you have to add them to the superview:
NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:valueLabel attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeRight multiplier:1.0 constant:1.0];
[self addConstraint:constraint];
[self needsUpdateConstraints];

UILabel/Content not appearing in UIScrollView

been trying to figure this out for a while. I'm tapping on the CNPPopupController and I'm trying to add a UIScrollView into the UIView.
In the scroll view I will be adding the content, I have tried so far but the content does not seem to be appearing in the UIScrollView. I am not sure what I'm doing wrongly, can anyone please guide me?
//The content view that will house labels and a UIScrollView
self.contentView = [[UIView alloc] init];
[self.contentView setTranslatesAutoresizingMaskIntoConstraints:NO];
self.contentView.clipsToBounds = YES;
self.contentView.backgroundColor = self.theme.backgroundColor;
self.contentView.layer.cornerRadius = self.theme.popupStyle == CNPPopupStyleCentered ? self.theme.cornerRadius : 0.0f;
[self.maskView addSubview:self.contentView];//The UI ScrollView
self.scrollView = [[UIScrollView alloc] init];
//self.scrollView.backgroundColor= self.theme.backgroundColor;
self.scrollView.frame = CGRectMake(50, 50, 200, 100);
self.scrollView.layer.cornerRadius = self.theme.popupStyle == CNPPopupStyleCentered ? self.theme.cornerRadius : 0.0f;
self.scrollView.clipsToBounds = YES; // default is NO, we want to restrict drawing within our scrollview
self.scrollView.scrollEnabled = YES;
if (self.popupTitle) {
UILabel *title = [self multilineLabelWithAttributedString:self.popupTitle];
[self.contentView addSubview:title];
}
//Adding items in the UISCrollView
if (self.contents) {
for (NSObject *content in self.contents) {
if ([content isKindOfClass:[NSAttributedString class]]) {
UILabel *label = [self multilineLabelWithAttributedString:(NSAttributedString *)content];
[label sizeToFit];
CGSize scrollViewContentSize = CGSizeMake(self.contentView.frame.size.width, self.contentView.frame.size.height+500);
[self.scrollView setContentSize:scrollViewContentSize];
[self.scrollView addSubview:label];
}
else if ([content isKindOfClass:[UIImage class]]) {
UIImageView *imageView = [self centeredImageViewForImage:(UIImage *)content];
[imageView sizeToFit];
CGSize scrollViewContentSize = CGSizeMake(self.contentView.frame.size.width, self.contentView.frame.size.height+500);
[self.scrollView setContentSize:scrollViewContentSize];
[self.scrollView addSubview:imageView];
[self.scrollView addConstraint:[NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationLessThanOrEqual toItem:imageView attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0]];
}
}
[self.contentView addSubview:self.scrollView];
}

getting adjustsFontSizeToFitWidth to work with constraints for snug content

This is a little view control I've written to test out the issue I'm having with constraints and adjustsFontSizeToFitWidth. Its a little thing that add's and remove's words from a label to see how various content sizes in label_title effect the layout. The desired layout is snug around the label_title (with the label_count taking up the rest of the room). Unfortunately its not quite snug yet.
Here are 3 view states I've screen captured to illustrate the lack of snugness on the blue title which I'm trying to fix.
Following that is the full source of a view controller that will run this view.
#import "MainViewController.h"
#interface MainViewController ()
// stuff to test our problem with
#property(nonatomic,strong) UIButton * addButton;
#property(nonatomic,strong) UIButton * removeButton;
// our problem
#property(nonatomic,strong) UIView * view_labels;
#property(nonatomic,strong) UILabel * label_title;
#property(nonatomic,strong) UILabel * label_count;
#end
#implementation MainViewController
// synthesize for the views constraint mapping
#synthesize label_title;
#synthesize label_count;
- (void)viewDidLoad
{
[super viewDidLoad];
[self.view setBackgroundColor:[UIColor grayColor]];
self.addButton = [self buttonWithTitle:#"Add Word"
selector:#selector(addButtonPressed) color:[UIColor greenColor]];
self.removeButton = [self buttonWithTitle:#"Remove Word"
selector:#selector(removeButtonPressed) color:[UIColor redColor]];
// view containing our troublesome labels
self.view_labels = [[UIView alloc] init];
[self.view addSubview:self.view_labels];
//[self.view_labels setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.view_labels setBackgroundColor:[UIColor lightGrayColor]];
// label row 1
self.label_title = [self labelWithText:#"word" defaultFontSize:30.0 bgcolor:[UIColor blueColor]];
[self.view_labels addSubview:self.label_title];
// label row 2
self.label_count = [self labelWithText:#"77" defaultFontSize:40.0 bgcolor:[UIColor purpleColor]];
[self.view_labels addSubview:self.label_count];
NSDictionary *views = NSDictionaryOfVariableBindings(label_title, label_count);
NSDictionary *metrics = #{#"pad":#2};
[self.view addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:#"V:|-(==pad)-[label_title(<=44)]-(==pad)-[label_count]-(==pad)-|"
options:0
metrics:metrics
views:views]];
[self.view addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:#"|-(==pad)-[label_title]-(==pad)-|"
options:0
metrics:metrics
views:views]];
[self.view addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:#"|-(==pad)-[label_count]-(==pad)-|"
options:0
metrics:metrics
views:views]];
}
#pragma mark - boiler plate stuff
-(UILabel*) labelWithText:(NSString*) text defaultFontSize:(float) fontSize bgcolor:(UIColor*) color
{
UILabel * label = [[UILabel alloc] init];
[label setTranslatesAutoresizingMaskIntoConstraints:NO];
[label setTextAlignment:NSTextAlignmentCenter];
[label setTextColor:[UIColor whiteColor]];
[label setAdjustsFontSizeToFitWidth:YES];
[label setNumberOfLines:0];
[label setMinimumScaleFactor:0.6];
[label setFont:[UIFont boldSystemFontOfSize:fontSize]];
[label setBackgroundColor:color];
[label setText:text];
return label;
}
-(UIButton*) buttonWithTitle:(NSString*) title selector:(SEL) selector color:(UIColor*) color
{
UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
[self.view addSubview:button];
[button setTitle:title forState:UIControlStateNormal];
[button setBackgroundColor:color];
[button addTarget:self action:selector forControlEvents:UIControlEventTouchUpInside];
return button;
}
-(void) viewWillLayoutSubviews{
[super viewWillLayoutSubviews];
float SQUARE_SIZE = 100;
[self.addButton setFrame:CGRectMake(0, self.view.frame.size.height-44.0, self.view.frame.size.width, 44.0)];
[self.removeButton setFrame:CGRectMake(0, self.view.frame.size.height-(44.0*2), self.view.frame.size.width, 44.0)];
[self.view_labels setFrame:CGRectMake(SQUARE_SIZE, SQUARE_SIZE, SQUARE_SIZE, SQUARE_SIZE)];
}
-(void) addButtonPressed
{
NSString * text = self.label_title.text;
if (text == nil){
text = #"";
}
text = [NSString stringWithFormat:#"%#%#",text,#" word"];
text = [text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
[self.label_title setText:text];
}
-(void) removeButtonPressed
{
NSString * text = self.label_title.text;
if (text == nil || [text isEqualToString:#""]){
return;
}
NSArray * array = [text componentsSeparatedByString:#" "];
text = #"";
for (int i = 0; i < [array count]-1; i++){
NSString * token = [array objectAtIndex:i];
text = [NSString stringWithFormat:#"%# %#",text,token];
}
text = [text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
[self.label_title setText:text];
}
#end
If you are trying to fit the text in UILabel replace the your method by the following.
-(UILabel*)labelWithText:(NSString*) text defaultFontSize:(float) fontSize bgcolor:(UIColor*) color
{
#autoreleasepool {
UILabel * label = [[UILabel alloc] initWithFrame:CGRectMake(50, 50,100,100)];
[label setTextAlignment:NSTextAlignmentCenter];
[label setTextColor:[UIColor whiteColor]];
[label setAdjustsFontSizeToFitWidth:YES];
[label setFont:[UIFont boldSystemFontOfSize:fontSize]];
[label setBackgroundColor:color];
[label setText:text];
[label setNumberOfLines:0];
while (fontSize > 0.0)
{
CGSize size = [text sizeWithFont:label.font constrainedToSize:CGSizeMake(label.frame.size.width, label.frame.size.height) lineBreakMode:NSLineBreakByWordWrapping];
if (size.height <= label.frame.size.height)
break;
fontSize -= 1.0;
}
[label setFont:[UIFont boldSystemFontOfSize:fontSize]];
return label;
}
}

Resources