iOS 11.2 custom navigation bar infinite loop - ios

Since the release of IOS 11.2 my app is encountering an infinite loop when pushing a view controller whose navigation controller has a custom navigation bar height. Did someone find the solution for this problem? Thanks.
-(void)layoutSubviews{
[super layoutSubviews];
float height = 42.5;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
height = 48;
}
imageView.frame = CGRectMake(0, 0, [[UIScreen mainScreen]bounds].size.width, height);
if(UI_USER_INTERFACE_IDIOM() ==UIUserInterfaceIdiomPad){
if(#available(iOS 11.0,*)){
self.frame =CGRectMake(0, 20,[[UIScreen mainScreen]bounds].size.width, 55); // this line provoke the infinite loop
for(UIView *aView in self.subviews){
if([NSStringFromClass([aView class]) isEqualToString: #"_UINavigationBarContentView"]){
aView.frame = CGRectMake(0, 10, aView.frame.size.width, aView.frame.size.height);
}
if([NSStringFromClass([aView class]) isEqualToString: #"_UIBarBackground"]){
aView.frame = CGRectMake(0, 0, aView.frame.size.width, self.frame.size.height );
}
}
}
}
}

I also had the same problem.
I solved by removing this
frame.size.height = customHeight
from layoutSubviews and then adding this
override var frame: CGRect {
get {
return CGRect(x: 0, y: 0, width: super.frame.width, height: customHeight)
}
set (value) {
super.frame = value
}
}
to my UINavigationBar subclass.
I left all other code in layoutSubviews as it was before. (nb)

Related

Margin between 2 Cells

Hi i'm trying to add a top and bottom margin to all my PackageCells.
like
what ive tried
%hook PackageCell
-(void)didMoveToWindow {
self.layer.cornerRadius = 15.0f;
self.layer.masksToBounds = true;
%orig;
}
-(CGRect)frame {
CGRect r = %orig;
return CGRectMake(40, 0, r.size.width, r.origin.height+20);
}
-(void)setFrame:(CGRect)frame {
CGRect r = frame;
%orig(CGRectMake(40, 0, r.size.width, r.origin.height+20));
}
%end
All cells get stacked on top of eachother and look weird.
You should set the backgroundColor of the cell to [UIColor clear]
And Change the frames of the contentView instead and make that view round
self.contentView.layer.cornerRadius = 15.0f;
And update the frame for this
self.contentView.frame = CGRectMake(40, 0, self.frame.size.width, self.frame.origin.height+20);

Change height of inputAccessoryView issue

When I change the height of inputAccessoryView in iOS 8, the inputAccessoryView not go to the right origin, but covers the keyboard.
Here are some code snippets:
in table view controller
- (UIView *)inputAccessoryView {
if (!_commentInputView) {
_commentInputView = [[CommentInputView alloc] initWithFrame:CGRectMake(0, 0, [self width], 41)];
[_commentInputView setPlaceholder:NSLocalizedString(#"Comment", nil) andButtonTitle:NSLocalizedString(#"Send", nil)];
[_commentInputView setBackgroundColor:[UIColor whiteColor]];
_commentInputView.hidden = YES;
_commentInputView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;
}
return _commentInputView;
}
in CommentInputView
#when the textview change height
- (void)growingTextView:(HPGrowingTextView *)growingTextView willChangeHeight:(float)height {
if (height > _textView_height) {
[self setHeight:(CGRectGetHeight(self.frame) + height - _textView_height)];
[self reloadInputViews];
}
}
in UIView Category from ios-helpers
- (void)setHeight: (CGFloat)heigth {
CGRect frame = self.frame;
frame.size.height = heigth;
self.frame = frame;
}
Finally, i found the answer. In ios8, apple add a NSContentSizeLayoutConstraints to inputAccessoryView and set a constant with 44. You can't remove this constaint, because ios8 use it to calculate the height of inputAccessoryView. So, the only solution is to change value of this constant.
Example
in ViewDidAppear
- (void)viewDidAppear:(BOOL)animated {
if ([self.inputAccessoryView constraints].count > 0) {
NSLayoutConstraint *constraint = [[self.inputAccessoryView constraints] objectAtIndex:0];
constraint.constant = CommentInputViewBeginHeight;
}
}
change inputAccessoryView height when the textview height changed
- (void)growingTextView:(HPGrowingTextView *)growingTextView willChangeHeight:(float)height {
NSLayoutConstraint *constraint = [[self constraints] objectAtIndex:0];
float new_height = height + _textView_vertical_gap*2;
[UIView animateWithDuration:0.2 animations:^{
constraint.constant = new_height;
} completion:^(BOOL finished) {
[self setHeight:new_height];
[self reloadInputViews];
}];
}
That is.
One way you can update the constraint mentioned in Yijun's answer when changing the height of the inputAccessoryView is by overwriting setFrame: on your inputAccessoryView. This doesn't rely on the height constraint being the first in the array.
- (void)setFrame:(CGRect)frame {
[super setFrame:frame];
for (NSLayoutConstraint *constraint in self.constraints) {
if (constraint.firstAttribute == NSLayoutAttributeHeight) {
constraint.constant = frame.size.height;
break;
}
}
}
The first answer didn't totally solve my problem but gave me a huge hint.
Apple did add a private constraint to the accessory view, but you cannot find it in the constraint list of the accessory view. You have to search for it from its superview. It killed my a few hours.
After reading the answer above, which is a great find, I was concerned that relying on the constraint you need to change being [0] or firstObject is an implementation detail that's likely to change under us in the future.
After doing a bit of debugging, I found that the Apple-added constraints on the accessory input view seem to have a priority of 76. This is a crazy low value and not one of the listed enums in the documentation for priority.
Given this low priority value it seems like a cleaner solution to simply conditionally add/remove another constraint with a high priority level, say UILayoutPriorityDefaultHigh when you want to resize the view?
For Xcode 11.2 and swift 5 this function will update inputAccessoryView constraints even in animation block
func updateInputContainerConstraints() {
if let accessoryView = inputAccessoryView,
let constraint = accessoryView.superview?.constraints.first(where: { $0.identifier == "accessoryHeight" }) {
constraint.isActive = false
accessoryView.layoutIfNeeded()
constraint.constant = accessoryView.bounds.height
constraint.isActive = true
accessoryView.superview?.addConstraint(constraint)
accessoryView.superview?.superview?.layoutIfNeeded()
}
}
Try this:
_vwForSendChat is the input accessory view
_txtViewChatMessage is the textview inside input accessory view
-(void)textViewDidChange:(UITextView *)textView {
CGFloat fixedWidth = textView.frame.size.width;
CGSize newSize = [textView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)];
CGRect newFrame = textView.frame;
newFrame.size = CGSizeMake(fmaxf(newSize.width, fixedWidth), newSize.height);
if (newFrame.size.height < 40) {
_vwForSendChat.frame = CGRectMake(0, 0, self.view.frame.size.width, 40);
} else {
if (newFrame.size.height > 200) {
_vwForSendChat.frame = CGRectMake(0, 0, self.view.frame.size.width, 200);
} else {
_vwForSendChat.frame = CGRectMake(0, 0, self.view.frame.size.width, newFrame.size.height);
}
}
[self.txtViewChatMessage reloadInputViews];
}

Resizing start behaving inaccurate after starting loop of scrolling

i got images scrollview and i am trying to change the size of views while scrolling, it works correct first time but when i started loop of scrolling means setting contentoff 0, 0, then it will start behaving inaccurate, means it started shuffeling views, up and down, it is working fine while scrolling upwards. if anyone get the problem please guide me where i am doing wrong? or suggest me any tutorial. HERE IS MY CODE.
- (void)viewDidLoad{
if (IS_IPHONE5)
scroller.contentSize=CGSizeMake(320, ((count*142)+710));
else
scroller.contentSize=CGSizeMake(320, ((count*130)+530));
makecopy= tableArray.count+4;
for(int i=0;i<=makecopy;i++)
{
if(i==0)
yValue=0;
else
yValue=130;
UIView* view1;
//=[[UIView alloc]initWithFrame:CGRectMake(0, (i*130)+yValue, 320, 260)];
if (IS_IPHONE5) {
if (i!=0/*&&i!=count*/){
yValue=142;
view1=[[UIView alloc]initWithFrame:CGRectMake(0, (i*142)+yValue, 320, 284)];
}
else{
yValue=0;
view1=[[UIView alloc]initWithFrame:CGRectMake(0, (i*142)+yValue, 320, 284)];
}
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if ([[UIScreen mainScreen] bounds].size.height == 568)
{
if (normalScroll)
{
for(int i=0;i<count;i++)
{
// NSLog(#">:%i %i:<",(i*142),((i+1)*142));
if (scroller.contentOffset.y>=(i*142)&&scroller.contentOffset.y<((i+1)*142)){
[self doscrollingwiththView:[scroller viewWithTag:i+1] view2:[scroller viewWithTag:i+2] view3:[scroller viewWithTag:i+3] view4:[scroller viewWithTag:i+4]];
}
}
changeMe = true;
if (!isUp && scrollView.contentOffset.y>(count*142)) {
[scrollView setContentOffset:CGPointMake(0, 0)];
changeMe = false;
}
if (isUp && scrollView.contentOffset.y<= -1) {
[scrollView setContentOffset:CGPointMake(0, (count*142)-10)];
changeMe = false;
}
}
-(void)doscrollingwiththView:(UIView*)view1 view2:(UIView*)view2 view3:(UIView*)view3 view4:(UIView*)view4
{
// NSLog(#"view1 : %# view1 : %# view1 : %# view1 : %# ",view1,view2,view3,view4);
offsetY=offsetY1+ scroller.contentOffset.y;
int view1Y=0;
int view2Y=0;
//int view3Y;
//int view4Y;
if (IS_IPHONE5)
{
view2Y=284;
}
else
{
view2Y=260;
//view3Y=390;
//view4Y=520;
}
for(int i=0;i<makecopy;i++)
{
if (IS_IPHONE5) {
// NSLog(#"the value is: %i the contentoffset is:%f",(142*i),scroller.contentOffset.y);
if(scroller.contentOffset.y>=(142*i)&&scroller.contentOffset.y<(142*(i+1)))
{
view1Y=(142*i);
view2Y=284+(142*i);
}
}
else
{
if (scroller.contentOffset.y>=(130*i)&&scroller.contentOffset.y<(130*(i+1)))
{
view1Y=(130*i);
view2Y=260+(130*i);
}
}
}
if (IS_IPHONE5) {
view1.frame=CGRectMake(0, view1Y-(offsetY%142), 320, 284);
view2.frame=CGRectMake(0, view2Y-(offsetY%142), 320, 284);
view3.frame=CGRectMake(0, 426+view1Y, 320, 284);
view4.frame=CGRectMake(0, 568+view1Y, 320, 284);
NSLog(#"the content offset is: %d",offsetY);
}
else
{
view1.frame=CGRectMake(0, view1Y-(offsetY%130), 320, 260);
view2.frame=CGRectMake(0, view2Y-(offsetY%130), 320, 260);
view3.frame=CGRectMake(0, 390+view1Y, 320, 260);
view4.frame=CGRectMake(0, 520+view1Y, 320, 260);
}
}
what i understood by your code is, you are shifting the images while scrolling and resizing it to when it reaches some specific point as you r doing its top i think, then my friend you r making 4 view and i think there are 3 views at a time shown in screen, what you hav to do is make 5 view instead of making 4 views, and revolve these view and let me know after it, i hope it will work in your case.

Rounding corners of UIModalPresentationFormSheet

forgive me if this is an obvious question i am relatively new.
I have a modal view which i set up with a custom size and rounded corners:
- (void)viewWillLayoutSubviews{
[super viewWillLayoutSubviews];
self.view.superview.bounds = CGRectMake(0, 0, 600, 450);
self.view.layer.cornerRadius = 60.0;
}
However i find that when i round the view corners, i get this greyish colour appear on the edges of it (as if theres something else behind it) : (see picture).
How do i remove these greyish edges so it shows the background content like normal? I've tried adding
self.view.layer.masksToBounds = YES;
however this still gives the same effect as above.
Thanks,
- (void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
self.view.superview.bounds = CGRectMake(0, 0, 600, 450);
self.view.superview.layer.cornerRadius = 60.0;
self.view.superview.layer.masksToBounds = YES;
}
I think you should set corner radius of the superView.
use like this
- (void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
self.view.superview.bounds = CGRectMake(0, 0, 600, 450);
self.view.layer.cornerRadius = 60.0;
self.view.layer.masksToBounds = YES; //add this line
}
Use this, it will remove the shadow
self.view.layer.masksToBounds = YES;
It turns out you need to round the superview and mask the superview;
[self.view superview].layer.cornerRadius = 30.0f;
[self.view superview].layer.masksToBounds = YES;
So in the end its looked like this :)
- (void)viewWillLayoutSubviews{
//setup custom size modal view
[super viewWillLayoutSubviews];
self.view.superview.bounds = CGRectMake(0, 0, 600, 450);
[self.view superview].layer.cornerRadius = 30.0f;
[self.view superview].layer.masksToBounds = YES;
}
Thanks for your help Shan

UIScrollView in different versions - iOS

I'm working on a UIScrollView in iPad. The Scroll view scrolls smoothly in iOS 5.0 ,but the animation of scrolling is not smoother in Versions below 5.0.
Is there any specific customization be done to handle this?Should I add some more functionality to run UIScrollView in iOS 4.x?
-- I am facing this problem when adding custom UIView into the UIScrollView.
Working Code :
{
timeLineScrollView.frame = CGRectMake(0, 0, 500, 500);
float posX = 0;
for(int i = 0;i < 10;i++)
{
UIView *samView = [[UIView alloc]initWithFrame:CGRectMake(posX, 10, 500, 300)];
posX = posX + 500;
[timeLineScrollView addSubview:samView];
}
timeLineScrollView.contentSize = CGSizeMake(500*10, timeLineScrollView.frame.size.height);
}
Not Working Code :
{
timeLineScrollView.frame = CGRectMake(0, 0, 500, 500);
float posX = 0;
for(int i = 0;i < 10;i++)
{
CustomView *samView = [[CustomView alloc]initWithFrame:CGRectMake(posX, 10, 500, 300)];
posX = posX + 500;
[timeLineScrollView addSubview:samView];
}
timeLineScrollView.contentSize = CGSizeMake(500*10, timeLineScrollView.frame.size.height);
}
The Custom View :
- (id)initWithFrame:(CGRect)frame withEvent:(VisitHistoryEvent*)eventDetails
{
self = [super initWithFrame:frame];
if (self) {
complaint = [[UILabel alloc]init];
}
return self;
}
-(void)layoutSubviews
{
complaint.frame = CGRectMake(0, 0, 100, 20);
[self addSubview:complaint];
}
Just a hunch... If you tried to create one UIView as a subview for the UIScrollView (with a width of 3000 to match your content) and added your UILabels to that view rather than directly to the UIScrollView, perhaps then iOS will be able to cache it and give you better perf.

Resources