MKAnnotationView leftCalloutAccessoryView Autolayout - ios

I am trying to add a custom view as the leftCalloutAccessoryView in my custom MKAnnotationView. All of the examples I have found use either an image, or some type of view where the frame is specified on init. I want to use autolayout for the view.
This is the code I have in my init method for myMKAnnotationView. I am just trying to use simple width and height constraints:
UIView* contentView = [[UIView alloc] init];
contentView.backgroundColor = [UIColor redColor];
contentView.translatesAutoresizingMaskIntoConstraints = NO;
NSLayoutConstraint* height = [NSLayoutConstraint constraintWithItem:contentView
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1
constant:32];
NSLayoutConstraint* width = [NSLayoutConstraint constraintWithItem:contentView
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1
constant:50];
[contentView addConstraints:#[height,width]];
self.leftCalloutAccessoryView = contentView;
I can never get the view to show up with constraints. If I remove the constraints and init the view with a frame it will show up. What do I need to do to get constraints working with the leftCalloutAccessoryView?
Also, if I change leftCalloutAccessoryView to detailCalloutAccessoryView, which was added in iOS 9, and it shows up correctly.

Related

XIB gave a constraint to launch the WKWebView, but there is an error A multiplier of 0 or a nil..... How can I fix this?

an error occurred while trying to run webview on xib using PageViewController.
Thread 1: "NSLayoutConstraint for <WKWebView: 0x14d0a8e00; frame = (0 0; 0 0); layer = <CALayer: 0x28109b600>>: A multiplier of 0 or a nil second item together with a location for the first attribute creates an illegal constraint of a location equal to a constant. Location attributes must be specified in pairs."
I made a view in xib (Not a ..cell. This is a view.) and made a wkwebview with code using that view, but I am having a hard time because of these errors. Is there a solution?
Below is the code I wrote.
CGRect rect = [[UIScreen mainScreen]bounds];
//CGRect rect = CGRectMake(0.0, 0.0, self.safeAreaContainerView.layer.frame.size.width, self.safeAreaContainerView.layer.frame.size.height); //I only received width and height as 0 and annotated it.
self.wkwebview = [[WKWebView alloc] initWithFrame:rect];
self.wkwebview.UIDelegate = self;
self.wkwebview.navigationDelegate = self;
self.wkwebview.translatesAutoresizingMaskIntoConstraints = NO;
[self.wkwebview sizeToFit];
self.wkwebview.scrollView.scrollEnabled= YES;
[self.safeAreaContainerView addSubview:self.wkwebview];
[self.safeAreaContainerView sendSubviewToBack:self.wkwebview];
//WKWebView Layout Setting
NSLayoutConstraint *firstViewConstraintTop = [NSLayoutConstraint constraintWithItem:self.wkwebview attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.safeAreaContainerView attribute:NSLayoutAttributeTop multiplier:1 constant:0];
NSLayoutConstraint *firstViewConstraintBottom = [NSLayoutConstraint constraintWithItem:self.safeAreaContainerView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.wkwebview attribute:NSLayoutAttributeBottom multiplier:1 constant:0];
NSLayoutConstraint *firstViewConstraintLeadingSpace = [NSLayoutConstraint constraintWithItem:self.wkwebview attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.safeAreaContainerView attribute:NSLayoutAttributeLeading multiplier:1 constant:0];
NSLayoutConstraint *firstViewConstraintTrailingSpace = [NSLayoutConstraint constraintWithItem:self.safeAreaContainerView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.wkwebview attribute:NSLayoutAttributeTrailing multiplier:1 constant:0];
[self.safeAreaContainerView addConstraints:[NSArray arrayWithObjects: firstViewConstraintTop, firstViewConstraintBottom, firstViewConstraintLeadingSpace, firstViewConstraintTrailingSpace, nil]];
Does it not work in View when coding the WKWebView to the XIB?
Is it only available on TableViewCell or CollectionViewCell?
I do something similar and use the code I posted here to embed the webview into its container view.
How to: Constrain subview to safeArea Obj-c
Apart from using that I do preciously little on the webview itself, basically the following
webView = [[WKWebView alloc] initWithFrame:GCRectZero];
webView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
and nothing else.
HIH

Why I will get this wrong when I add some constraints in subView?

LogoView is top_bg's subview. top_bg is window's subView. I try to add constraints with LogoView. Why I will get these wrong?
CGRect screenFrame = [[UIScreen mainScreen] bounds];
UIImageView *logoView = [[UIImageView alloc]init];//logo
UIImage *logoImage = [UIImage imageNamed:#"top_ico.png"];
[logoView setImage:logoImage];//below add constraint
// logoView.frame = CGRectMake(150.0f,0.0f, 304.74f, 60.0f);
[logoView setTranslatesAutoresizingMaskIntoConstraints:NO];
NSLayoutConstraint *logoConstraint_0 = [NSLayoutConstraint constraintWithItem:logoView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:top_bg attribute:NSLayoutAttributeTop multiplier:1.0f constant:0.0f];
NSLayoutConstraint *logoConstraint_1 = [NSLayoutConstraint constraintWithItem:logoView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:top_bg attribute:NSLayoutAttributeLeft multiplier:1.0f constant:screenFrame.size.width/2.0f];
NSLayoutConstraint *logoConstraint_2 = [NSLayoutConstraint constraintWithItem:logoView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0f constant:304.74f];
NSLayoutConstraint *logoConstraint_3 = [NSLayoutConstraint constraintWithItem:logoView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0f constant:60.0f];
NSArray *LogoConstraints = [NSArray arrayWithObjects:logoConstraint_0,logoConstraint_1,logoConstraint_2,logoConstraint_3,nil];
[top_bg addConstraints:LogoConstraints];
[top_bg addSubview:logoView];
Below is the error when I run it.
2018-03-09 10:43:54.114041+0800 MainUI[1855:81910] [LayoutConstraints] The view hierarchy is not prepared for the constraint: <NSLayoutConstraint:0x60000009b080 UIImageView:0x7f9196429a20.top == UIImageView:0x7f9196615d70.top (inactive)>
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(UIConstraintBasedLayout) _viewHierarchyUnpreparedForConstraint:] to debug.
I got the answer !,like this code below
-(instancetype) initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if(self){
self.top_bg = [[UIImageView alloc]init];
self.logoView=[[UIImageView alloc]init];
[self.top_bg addSubview:self.logoView];
}
return self;
}
I must be confirm View's hierarchy before I add some constraints ! I can't add constrains then addSubViews.
You need to change the code sequence i.e. first add logoView as subview and then add its constraints.
First add Subview
[top_bg addSubview:logoView];
And the apply constraints
NSArray *LogoConstraints = [NSArray arrayWithObjects:logoConstraint_0,logoConstraint_1,logoConstraint_2,logoConstraint_3,nil];
[top_bg addConstraints:LogoConstraints];

Autolayout for UITextview inside custom UITableviewcell

I have a UITextView inside a custom UITextviewCell. I want the cell to grow in size according to the content of UITextview. I have pinned top, bottom, right, left of textview to the content view of cell. When I pre-populate textview with text, it is working fine as expected. Its not working when I enter text with keyboard. Inside my custom cell.
UITextView * textView = [[UITextView alloc]init];
[textView setTranslatesAutoresizingMaskIntoConstraints:NO];
[textView setBackgroundColor:[UIColor redColor]];
[textView setScrollEnabled:NO];
[textView setDelegate:self];
[self.contentView addSubview:textView];
NSLayoutConstraint *xConstrain = [NSLayoutConstraint constraintWithItem:textView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0];
NSLayoutConstraint *yConstrain = [NSLayoutConstraint constraintWithItem:textView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTop multiplier:1.0 constant:0];
NSLayoutConstraint *rightConstrain = [NSLayoutConstraint constraintWithItem:textView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeRight multiplier:1.0 constant:0];
NSLayoutConstraint *bottomConstrain = [NSLayoutConstraint constraintWithItem:textView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0];
[self.contentView addConstraint:xConstrain];
[self.contentView addConstraint:yConstrain];
[self.contentView addConstraint:rightConstrain];
[self.contentView addConstraint:bottomConstrain];
In my tableview controller added following line
-(void)viewdidload
{
self.tableView.rowHeight = UITableViewAutomaticDimension;
self.tableView.estimatedRowHeight = 100.0f ;
}
There are a couple thing you can do here, one that comes to mind:
• As you are entering text, keep track of the height of the UITextView, as in keep an 'old height' variable and a 'new height' variable. To get the 'new height' you could use the sizeThatFits method of the UITextView with height set to for example 1000 (large enough that it won't constrain your result).
• The moment the new height is different than the old height, either smaller or larger, you reload the cell that houses the UITextView you are working on. You can event set the [cell setNeedsLayout], followed by [cell layoutIfNeeded] to make sure it resizes.
I'd imagine this should work, please let me know if it doesn't.

iOS 8: UITableViewCell.contentView doesn't resize subviews in it

I put an CustomView in UITableViewCell.contentView, setting the autoresize mask of the custom view as W+H.
But when running, the CustomView gets a larger height than the ContentView, the ContentView is 60pt in height(which is the same as setting in UITableViewDelegate), but the CustomView inside contentView is 76pt in height.
By Xcode6's view debugging, I see some strange constraints on my custom view, they are:
self.height = superview.height + 16
self.midY = superview.midY + 8
Where are these constraints come from and how to modify them? I've never set anything with a value 8 or 16.
UPDATE:
I've made a test project, which is simply a tableview in storyboard with a CustomView loaded from a nib file, and this test project replicated the problem, when running, the CustomView which is a subview of TableViewCell.contentView becomes larger in height than the TableViewCell.contentView.
The test project is here:
https://drive.google.com/file/d/0B5y_NrRbhGlSb1dlbVZNb19vNjQ/view?usp=sharing
At last I understand, auto layout can only form relations in the same xib or storyboard, my CustomView is in a separated xib and is loaded at runtime, so the super view and CustomView don't have any auto layout constraints between them.
If I set translatesAutoresizingMaskIntoConstraints to YES, then there goes the problem, I still don't know why using W+H as auto resizing mask makes CustomView taller than its super view(cell.contentView), but I found a way around:
I manually add constraints between superview and CustomView, and turn off customView. translatesAutoresizingMaskIntoConstraints, there the code goes:
customView.translatesAutoresizingMaskIntoConstraints = NO;
NSLayoutConstraint *top = [NSLayoutConstraint constraintWithItem:customView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:cell.contentView attribute:NSLayoutAttributeTop multiplier:1 constant:0];
NSLayoutConstraint *bottom = [NSLayoutConstraint constraintWithItem:customView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:cell.contentView attribute:NSLayoutAttributeBottom multiplier:1 constant:0];
NSLayoutConstraint *left = [NSLayoutConstraint constraintWithItem:customView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:cell.contentView attribute:NSLayoutAttributeLeft multiplier:1 constant:0];
NSLayoutConstraint *right = [NSLayoutConstraint constraintWithItem:customView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:cell.contentView attribute:NSLayoutAttributeRight multiplier:1 constant:0];
[cell.contentView addConstraints:#[top, bottom, left, right]];

Autolayout crash when applying transform: Assertion failure in -[layoutSublayersOfLayer:]

I have a custom view that display a UILabel in the bottom right corner. The view is setup in a method called from both initWithCoder: and initWithFrame: like this:
MCLabel* likesLabel = [[MCLabel alloc] init];
likesLabel.mc_textPadding = UIEdgeInsetsMake(0, 10, 0, 10);
likesLabel.font = [UIFont fontWithName:#"FontAwesome" size:12.f];
[likesLabel setText:#"test"];
likesLabel.numberOfLines = 2;
likesLabel.backgroundColor = [UIColor colorWithWhite:1 alpha:.8];
likesLabel.textColor = UIColor.blackColor;
likesLabel.translatesAutoresizingMaskIntoConstraints = NO;
likesLabel.textAlignment = NSTextAlignmentCenter;
likesLabel.mc_verticalTextAlignment = MCVerticalTextAlignmentTop;
[self addSubview:likesLabel];
self.likesLabel = likesLabel;
NSLayoutConstraint* widthConstraint = [NSLayoutConstraint constraintWithItem:likesLabel attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeWidth multiplier:1 constant:1];
NSLayoutConstraint* heightConstraint = [NSLayoutConstraint constraintWithItem:likesLabel attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:likesLabel attribute:NSLayoutAttributeWidth multiplier:2/5.f constant:1];
NSLayoutConstraint* horizontalPosition = [NSLayoutConstraint constraintWithItem:likesLabel attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeRight multiplier:1 constant:1];
NSLayoutConstraint* verticalPosition = [NSLayoutConstraint constraintWithItem:likesLabel attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1 constant:1];
[likesLabel addConstraints:#[heightConstraint]];
[self addConstraints:#[widthConstraint, horizontalPosition, verticalPosition]];
Now if I leave everything like this I do not have any kind of problem but, as soon as I apply a transform to this label (that is a subclass of UILabel that simply add vertical alignment and edge insets if that matters) the app crashes with the error in console:
*** Assertion failure in -[MCView layoutSublayersOfLayer:], /SourceCache/UIKit/UIKit-2935.138/UIView.m:8794
Auto Layout still required after executing -layoutSubviews
The assertion hints that probably the subclass didn't call [super layoutSubviews] when overriding the methods but I did.
Since is clear that the problem here is the autolayout setup I'm afraid that I'm overlooking at something and maybe the layout is ambiguous hence the crash.
One more note: the same code does not crash on iOS 8 if I move the transform in the - (void)didMoveToSuperview method.
Anyone that can helps here?
I had this issue in iOS7 (but not iOS8) from putting constraint adjustments in viewWillLayoutSubviews. Moving constraint adjustment to viewWillAppear fixed it for me.
In iOS7 you need to do this on viewDidAppear. It will also work for iOS8. If you dont want to see the delayed element change on screen, hide your super view on viewDidLoad and unhide it on viewDidAppear, right after you apply your changes.

Resources