Masonry.unrecognized selector sent to instance - ios

UIView *v2 = ({
UIView *view = [UIView new];
[self.view addSubview:view];
[view mas_makeConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(CGSizeMake(50, 50));
make.left.equalTo(v1.mas_right);
make.top.equalTo(v1.mas_bottom);
}];
view.backgroundColor = [UIColor blueColor];
view.layoutMargins = UIEdgeInsetsMake(-20, -20, -20, -20);
view;
});
UIView *v3 = ({
UIView *view = [UIView new];
[self.view addSubview:view];
[view mas_makeConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(CGSizeMake(50, 50));
make.centerY.equalTo(v2);
make.left.equalTo(v2.mas_rightMargin);
// make.left.equalTo(v2.mas_right);
}];
view.backgroundColor = [UIColor redColor];
view;
});
As you see, I am using the Masonry to create the UI.
This code has the bug.
-[UIView mas_rightMargin]: unrecognized selector sent to instance 0x7fdfa640cf80'
If I change the make.left.equalTo(v2.mas_rightMargin); to make.left.equalTo(v2.mas_right);;, it doesn't crash.

Just set the Pods -> Masonry -> iOS Deployment Target to the target what your project is.
Here is the screenshot, wish to be helpful to you...

Related

Cannot select/edit text in UITextView within UIScrollView

I have setup my UIScrollView with subviews like so using Masonry:
- (void)setupViews {
self.view.backgroundColor = [UIColor Background];
self.scrollView = [UIScrollView new];
self.scrollView.alwaysBounceVertical = YES;
[self.view addSubview:self.scrollView];
[self.scrollView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.view);
}];
self.contentView = [UIView new];
[self.scrollView addSubview:self.contentView];
self.scrollView.backgroundColor = [UIColor clearColor];
[self.contentView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.scrollView);
make.left.and.right.equalTo(self.view);
}];
self.imageButton = [UIButton buttonWithType:UIButtonTypeCustom];
[self.imageButton sd_setImageWithURL:[NSURL URLWithString:self.card.cardImageURL] forState:UIControlStateNormal];
[self.imageButton.imageView setContentMode:UIViewContentModeScaleAspectFill];
[self.contentView addSubview:self.imageButton];
[self.imageButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.and.right.equalTo(self.contentView);
make.height.equalTo(self.imageButton.mas_width).multipliedBy(3/4.0);
}];
self.textField = [UITextField new];
self.textField.backgroundColor = [UIColor whiteColor];
self.textField.font = kFontRegular(14);
self.textField.text = self.card.cardTitle;
[self.contentView addSubview:self.textField];
[self.textField mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.contentView).with.offset(8);
make.top.equalTo(self.imageButton.mas_bottom).with.offset(8);
make.right.equalTo(self.contentView).with.offset(-8);
make.height.equalTo(#(45));
}];
}
but it will not let me interact with the UITextField. what element here is preventing user interaction?
Your contentView's height will be zero. So it will never get some touch events. You should not use this constraint:
make.edges.equalTo(self.scrollView);
It will not get a correct value. Try to set top and height constraints for your contentView.
make.top.equalTo(#0);
make.height.equalTo(#700);

UIView flip animation is not animating

I'm trying to flip between a front view and a back view, like a page of a book. I ran the following test code in a view controller and no animation happened. I only saw the back view (red square) appear statically for 2 seconds. What's wrong?
UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 100.0, 100.0)];
containerView.backgroundColor = [UIColor greenColor];
[self.view addSubview:containerView];
UIView *backView = [[UIView alloc] initWithFrame:containerView.bounds];
backView.backgroundColor = [UIColor redColor];
[containerView addSubview:backView];
UIView *frontView = [[UIView alloc] initWithFrame:containerView.bounds];
frontView.backgroundColor = [UIColor blueColor];
[containerView addSubview:frontView];
[UIView transitionFromView:frontView
toView:backView
duration:2.0
options:UIViewAnimationOptionTransitionFlipFromRight
| UIViewAnimationOptionShowHideTransitionViews
completion:^(BOOL finished) {
[containerView removeFromSuperview];
}];
If you declare your frontView, backView and containerViewas ivars:
#interface yourViewController ()
{
UIView *backView;
UIView *frontView;
UIView *containerView;
}
Then place your view initialization code within viewDidLoad:
UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 100.0, 100.0)];
containerView.backgroundColor = [UIColor greenColor];
[self.view addSubview:containerView];
UIView *backView = [[UIView alloc] initWithFrame:containerView.bounds];
backView.backgroundColor = [UIColor redColor];
[containerView addSubview:backView];
UIView *frontView = [[UIView alloc] initWithFrame:containerView.bounds];
frontView.backgroundColor = [UIColor blueColor];
[containerView addSubview:frontView];
And finally place your animation code within a method:
- (void)flippingViewTransitionAnimation
{
[UIView transitionFromView:frontView
toView:backView
duration:2.0
options:UIViewAnimationOptionTransitionFlipFromRight | UIViewAnimationOptionShowHideTransitionViews
completion:^(BOOL finished) {
[containerView removeFromSuperview];
}];
}
And subsequently call the above method from within viewDidAppear, you should then be able to see the animation run.

UIScrollView paging disabled after rotation

Following is my code for App Tour using UIScrollView with paging enabled using AutoLayout (Masonry) It works fine in Portrait but when I rotate paging gets disabled so it doesn't work in Landscape. Then it doesn't work in Portrait mode either. Can someone help what's wrong here?
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor clearColor];
self.scrollView = [UIScrollView new];
self.scrollView.backgroundColor = [UIColor clearColor];
self.scrollView.scrollEnabled = YES;
self.scrollView.pagingEnabled = YES;
self.scrollView.delegate = self;
self.scrollView.showsHorizontalScrollIndicator = NO;
[self.view addSubview:self.scrollView];
[self.scrollView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.view);
}];
UIImageView *esImageview1 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"CommonResources.bundle/page1"]];
esImageview1.contentMode = UIViewContentModeScaleAspectFit;
esImageview1.backgroundColor = [UIColor clearColor];
esImageview1.userInteractionEnabled = YES;
[self.scrollView addSubview:esImageview1];
[esImageview1 mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.bottom.equalTo(self.scrollView);
make.width.height.equalTo(self.view);
}];
UIImageView *esImageview2 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"CommonResources.bundle/page2"]];
esImageview2.contentMode = UIViewContentModeScaleAspectFit;
esImageview2.backgroundColor = [UIColor clearColor];
esImageview2.userInteractionEnabled = YES;
[self.scrollView addSubview:esImageview2];
[esImageview2 mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(esImageview1.mas_right);
make.top.bottom.equalTo(self.scrollView);
make.width.height.equalTo(self.view);
}];
UIImageView *esImageview3 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"CommonResources.bundle/page3"]];
esImageview3.contentMode = UIViewContentModeScaleAspectFit;
esImageview3.backgroundColor = [UIColor clearColor];
esImageview3.userInteractionEnabled = YES;
[self.scrollView addSubview:esImageview3];
[esImageview3 mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(esImageview2.mas_right);
make.top.bottom.equalTo(self.scrollView);
make.width.height.equalTo(self.view);
}];
self.pageControl = [UIPageControl new];
self.pageControl.numberOfPages = 3;
self.pageControl.currentPage = 0;
self.pageControl.backgroundColor = [UIColor clearColor];
[self.view addSubview:self.pageControl];
[self.pageControl mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.equalTo(self.view);
make.height.equalTo(#40);
make.top.equalTo(self.view).with.offset(40);
}];
UILabel *titleLabel = [UILabel new];
titleLabel.text = #"App Tour";
titleLabel.backgroundColor = [UIColor clearColor];
titleLabel.textColor = [UIColor whiteColor];
titleLabel.font = [UIFont fontWithName:#"Helvetica-Light" size:16];
titleLabel.textAlignment = NSTextAlignmentCenter;
[self.view addSubview:titleLabel];
[titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.equalTo(self.view);
make.height.equalTo(#40);
make.top.equalTo(self.view).with.offset(20);
}];
UIButton *doneButton = [UIButton new];
[doneButton.titleLabel setFont:[UIFont fontWithName:#"Helvetica-Light" size:16]];
[doneButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[doneButton setTitleColor:[UIColor grayColor] forState:UIControlStateHighlighted];
[doneButton setTitle:#"Done" forState:UIControlStateNormal];
[doneButton addTarget:self action:#selector(doneButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
doneButton.backgroundColor = [UIColor clearColor];
[self.view addSubview:doneButton];
[doneButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(self.view);
make.height.equalTo(#40);
make.width.equalTo(#70);
make.top.equalTo(self.view).with.offset(20);
}];
}
- (void)doneButtonPressed:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
self.scrollView.contentSize = CGSizeMake(self.view.frame.size.width*self.pageControl.numberOfPages, self.view.frame.size.height);
}
- (void)scrollViewDidScroll:(UIScrollView *)sender {
CGFloat pageWidth = self.scrollView.frame.size.width;
int page = floor((self.scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
self.pageControl.currentPage = page;
}
I'm guessing its getting covered up by another view or something similar to that. Try subclassing the UIScrollView and implementing the following method to check if its responding to your touches at all.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(#"OMG TOUCHES WORK, NOW WHAT?");
}
You can easily check if it was getting covered up by forcing it to be in front. Call this line of code in the callback for rotation in the UIViewController containing the UIScrollView. It should fix the problem. You may have to subclass the UIView for the controller and put this method in the didLayoutSubviews method instead, not quite sure, depends on your implementation.
[self.view bringSubViewToFront:self.scrollView];
Also check the frame and bounds before and after rotation and see if anything is out of place looking
I just wanted to reset Scrollview's contentsize in didRotateFromInterfaceOrientation delegate. Not sure why though because when I rotate, videDidLayoutSubview already gets called where I am already reseting content size.
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
self.scrollView.contentSize = CGSizeMake(self.view.frame.size.width*self.pageControl.numberOfPages, self.view.frame.size.height);
}

How to add subview with flip animation?

If you create a brand new single view app and put this code behind a button:
UIView *blah = [[UIView alloc] initWithFrame:CGRectMake(0,0,100,100)];
blah.backgroundColor = [UIColor grayColor];
[UIView transitionWithView:blah duration:1
options:UIViewAnimationOptionTransitionFlipFromRight
animations:^{
[self.view addSubview:blah];
}
completion:^(BOOL finished){
}];
The subview is added immediately with no animation. If you add the subview first then try to animate it... you get the same problem.
UIView *blah = [[UIView alloc] initWithFrame:CGRectMake(0,0,100,100)];
[self.view addSubview:blah];
[UIView transitionWithView:blah duration:1
options:UIViewAnimationOptionTransitionFlipFromRight
animations:^{
blah.backgroundColor = [UIColor grayColor];
}
completion:^(BOOL finished){
}];
How on Earth do you animate a flip for a subview while or immediately after adding it?
You generally need to have the container that constrains the animation to be in place already:
- (void)viewDidLoad
{
[super viewDidLoad];
CGRect frame = CGRectMake(0, 0, 100, 100);
_container = [[UIView alloc] initWithFrame:frame];
_container.backgroundColor = [UIColor lightGrayColor];
[self.view addSubview:_container];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
UIView *subview = [[UIView alloc] initWithFrame:_container.bounds];
subview.backgroundColor = [UIColor darkGrayColor];
[UIView transitionWithView:_container
duration:1.0
options:UIViewAnimationOptionTransitionFlipFromRight
animations:^{
[_container addSubview:subview];
}
completion:NULL];
}
This is worth a try:
UIView *blah = [[UIView alloc] initWithFrame:CGRectMake(0,0,100,100)];
blah.backgroundColor = [UIColor grayColor];
[self.view addSubview:blah];
blah.alpha = 0.0; //Or with blah.hidden = TRUE and then FALSE inside the animation block
[UIView transitionWithView:blah
duration:1
options:UIViewAnimationOptionTransitionFlipFromRight
animations:^{
blah.alpha = 1.0;
}
completion:^(BOOL finished){
}];

Removing subviews when bar button is tapped

I am trying to trigger adding two subviews when a Bar Button is tapped. But adding the subviews works just fine, but when I try removing the subviews, it doesn't work.
Here is the code I am implementing
-(IBAction)showPopover:(id)sender{
UIView *popoverView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 100)];
UIView *popoverViewBackground = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 1000)];
popoverView.alpha = 0.0;
popoverView.layer.cornerRadius = 2;
popoverView.layer.borderWidth = 0.1f;
popoverView.layer.backgroundColor = [UIColor whiteColor].CGColor;
popoverView.layer.masksToBounds = YES;
popoverViewBackground.layer.backgroundColor= [UIColor blackColor].CGColor;
if (popoverCount == 0) {
[self.view addSubview:popoverViewBackground];
[self.view addSubview:popoverView];
popoverCount = 1;
}else if (popoverCount ==1){
[popoverView removeFromSuperview];
[popoverViewBackground removeFromSuperview];
popoverCount = 0;
}
[popoverViewBackground setAlpha:0.5];
[popoverView setAlpha:1.0];
}
Problem is that you are creating new view every time you click the button so old view not removing put your code like thi, then it will work fine.I have tested it.
in .h file
#interface secondViewController : UIViewController
{
int popoverCount;
UIView *popoverView ;
UIView *popoverViewBackground;
}
in .m file
- (void)viewDidLoad
{
[super viewDidLoad];
popoverView = [[UIView alloc] initWithFrame:CGRectMake(0, -100, 320, 100)];
popoverViewBackground = [[UIView alloc] initWithFrame:CGRectMake(0, -100, 320, 100)];
popoverView.alpha = 0.0;
popoverView.layer.cornerRadius = 2;
popoverView.layer.borderWidth = 0.1f;
popoverView.layer.backgroundColor = [UIColor whiteColor].CGColor;
popoverView.layer.masksToBounds = YES;
popoverViewBackground.layer.backgroundColor= [UIColor blackColor].CGColor;
}
-(IBAction)showPopover:(id)sender {
if (popoverCount == 0) {
[self.view addSubview:popoverViewBackground];
[self.view addSubview:popoverView];
[UIView animateWithDuration:0.5
animations:^{
popoverView.frame = CGRectMake(0,0,320,100);
}
completion:^(BOOL finished){
;
}];
[UIView animateWithDuration:0.5
animations:^{
popoverViewBackground.frame = CGRectMake(0,0,320,100);
}
completion:^(BOOL finished){
;
}];
popoverCount = 1;
}else if (popoverCount ==1){
[UIView animateWithDuration:0.5
animations:^{
popoverView.frame = CGRectMake(0,-100,320,100);
}
completion:^(BOOL finished){
[popoverView removeFromSuperview];
}];
[UIView animateWithDuration:0.5
animations:^{
popoverViewBackground.frame = CGRectMake(0,-100,320,100);
}
completion:^(BOOL finished){
[popoverViewBackground removeFromSuperview];
}];
popoverCount = 0;
}
[popoverViewBackground setAlpha:0.5];
[popoverView setAlpha:1.0];
}
UIView *popoverView;
UIView *popoverViewBackground;
Declare popoverView and popoverViewBackground in .h file and allocate and initializes of these subview in when popoverCount is zero.
-(IBAction)showPopover:(id)sender{
if (popoverCount == 0) {
popoverView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 100)];
popoverViewBackground = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 1000)];
popoverView.alpha = 0.0;
popoverView.layer.cornerRadius = 2;
popoverView.layer.borderWidth = 0.1f;
popoverView.layer.backgroundColor = [UIColor whiteColor].CGColor;
popoverView.layer.masksToBounds = YES;
popoverViewBackground.layer.backgroundColor= [UIColor blackColor].CGColor;
[self.view addSubview:popoverViewBackground];
[self.view addSubview:popoverView];
popoverCount = 1;
}else if (popoverCount ==1){
[popoverView removeFromSuperview];
[popoverViewBackground removeFromSuperview];
popoverCount = 0;
}
[popoverViewBackground setAlpha:0.5];
[popoverView setAlpha:1.0];
}
At least 2 issues in your code:
Every time the method is involved, you are creating new instances of these sub-views
You are removing the newly created instances. That is, previous instances that were added still exist.
You should
save these sub-views in instance variables, so that you can refer to them and remove them correctly.
move the creation code inside the first if-block, so that you are not creating too many sub-views.
It is happening because you are applying addSubview and removeFromSuperview on different object.
When First time showPopover is called it create two object of UIView
with name popoverView and popoverViewBackground.
and add this to self.view.
Till now every thing fine but when this method call second time
New object of popoverView and popoverViewBackground created again and
You are trying to remove that new created object from self.view which is not there.
How to solve this:
There are two way to solve this:
1) Create this object in .h file so you can access it from anywhere.
2) create object in such way that it created only when method call first time.
Give this UIView tag and when you remove find this tag in UIView.subview
Way 1 is easy way 2 require some code but you can make it efficient in turm of memory.
All the best

Resources