ViewController's UILayoutAnchor messed up when added to UINavigationController - ios

I'm playing around with UILayoutAnchor and it works perfectly with my ViewController. But when I add the ViewController to a NavigationController, I didn't get the result I'm expecting. Here's the code:
UIButton *topContainer = [UIButton buttonWithType:UIButtonTypeCustom];
[topContainer setBackgroundColor:[UIColor redColor]];
[self.view addSubview:topContainer];
//Setup anchor
topContainer.translatesAutoresizingMaskIntoConstraints = false;
[topContainer.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor].active = true;
[topContainer.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor].active = true;
[topContainer.heightAnchor constraintEqualToConstant:40].active = true;
[topContainer.topAnchor constraintEqualToAnchor:self.topLayoutGuide.bottomAnchor constant:0].active = true;
the result of the above code:
Now when I make the same ViewController as a root of NavigationController (via storyboard where I also hide intentionally) the same code gives the below result.
The first I've noticed is the background that went from gray to black. The interaction on the viewcontroller also is not working anymore. I've check the inspector of the navigationcontroller and its "user interaction enabled" is checked. And the topContainer(redbar) didn't extend to the edge of the screen.
I've tried using the viewcontrollers readableContentGuide but it extends all the way to the edge. See below code along with the result.
[topContainer.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor].active = true;
[topContainer.leadingAnchor constraintEqualToAnchor:self.view.readableContentGuide.leadingAnchor].active = true;
I also tried showing the NavigationController and a clean build but it still gives the same result. Where did I messed up?

Teddy bear programming really works. The problem is somewhere in my code there is this line.
self.view.translatesAutoresizingMaskIntoConstraints = false;
I got the result I want by just commenting/removing it out. I'm leaving this here just in case someone encounter it.

Related

UIButton titleLabel not displaying center aligned.

I have a button in my ios project which displays edit profile if the user is the current user and follow if the user is not the current user.
I am setting the titleLabel text programmatically dependant on the above condition. I am also programatically setting the button text to align center.
The problem I'm having is it works perfectly for the edit profile button which appears as it should center aligned but when showing the follow button the word follow is slightly off center to the left and I can't figure out where I'm going wrong.
Here is my code:
if([userID isEqualToString:credentialID]){
self.followEditBtn.layer.cornerRadius = 2;
self.followEditBtn.layer.borderColor = UIColorFromRGB(0xA6B9C1).CGColor;
self.followEditBtn.layer.borderWidth = 1.0f;
self.followEditBtn.layer.backgroundColor = UIColorFromRGB(0xF8FBFC).CGColor;
self.followEditBtn.titleLabel.textColor = UIColorFromRGB(0xA1B1C3);
self.followEditBtn.titleLabel.text = #"Edit Profile";
self.followEditBtn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
} else {
self.followEditBtn.layer.cornerRadius = 2;
self.followEditBtn.layer.borderColor = UIColorFromRGB(0x19A548).CGColor;
self.followEditBtn.layer.borderWidth = 1.0f;
self.followEditBtn.layer.backgroundColor = [UIColor whiteColor].CGColor;
self.followEditBtn.titleLabel.textColor = UIColorFromRGB(0x19A548);
self.followEditBtn.titleLabel.text = #"Follow";
self.followEditBtn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
}
And some images of the buttons as you can see the follow text is slightly off center to the left yet the edit profile button is correctly aligned:
I couldn't reproduce your problem (iOS 6.1 to 7.1). Although I had to make a small change in order to make it work, since it wasn't showing any text.
Instead of using:
self.followEditBtn.titleLabel.text = #"Edit Profile";
you should use:
[self.followEditBtn setTitle:#"Follow" forState:UIControlStateNormal];
I'm assuming you're using a UIButtonTypeCustom type UIButton, and having a fixed frame size.
I'd like you to tell me where are you putting this code, and how is this button being initialized.

Moving Particle View to Front of Screen?

I currently have a particle view connected to storyboard. The problem that I'm facing is that I'm displaying an alert at the same time I show this view, and the alert is always shown in front of the particle view. Is there a way where I can always place the particle view in front? I'm using a third party alert library titled SIAlertView, so I'm assuming it may be possible.
I've logged the zPosition of the alertView and it's always 0, so I set the zPosition of my particle view's layer to 10, but it is still shown beneath the alert view.
Here's the storyboard hierarchy:
I do not know about SIAlertView but normal UIAlertView is shown via separate window. If you want to overlap it you can not do it by changing zpozition, you have to also use a separate window:
// do not forget to keep strong reference for it somewhere!
UIWindow *notificationWindow;
//your frame here!
notificationWindow = [[UIWindow alloc] initWithFrame: some_cgrect];
notificationWindow.backgroundColor = [UIColor clearColor]; // your color if needed
notificationWindow.userInteractionEnabled = NO; // if needed
// IMPORTANT PART!
notificationWindow.windowLevel = UIWindowLevelAlert + 1;
notificationWindow.rootViewController = [UIViewController new];
notificationWindow.hidden = NO; // This is also important!
UPDATE:
To overlap also a status bar use
notificationWindow.windowLevel = UIWindowLevelStatusBar;
to dismiss UIWindow just invalidate strong pointer to it. Something like:
self.strongPointerToYourWindow = nil;

Strange appearance of the status bar after upgrading to ECSlidingViewController 2

It seems that one particular aspect of iOS programming is to diagnose these weird, seemingly trivial yet frustratingly obscure small problems.
So today, I was happily woking on my recent iOS project, and I decided to upgrade my project to the latest version ECSlidingViewController, what harm could it do right? Just update a few deprecated methods that's all.
So I did all of that. Everything works fine, beautiful. However, I noticed that the status bar is behaving strangely! It is not appearing when I display one of my underLeftViewController, and it is in a weird shade when I push segue that particular underLeftViewController into one of its subsequent VC. What?? How could this be happening? Anyway, a picture is worth a thousand words:
So here is it acting nice and normal:
Now it disappears!!!:
Now it has a weird shade!!!:
And here is a picture of the app with the sliding view controller slided out:
I must have done something crazy to my status bar somewhere, then I thought.
So I looked into my implementation file for the VC where statusbar is acting crazy. It is in fact a subclass of UINavigationController, and its viewDidLoad is empty except with the [super viewDidLoad] line. So nothing suspicious here.
The run test page is in fact the rootViewController for the navVC, so I looked into it. I put all of my view setup code in its viewDidLoad, and this is what it looks like:
- (void)viewDidLoad
{
[super viewDidLoad];
// remove advanced button
self.navigationItem.rightBarButtonItem = nil;
self.navigationController.view.layer.shadowOffset = CGSizeMake(1, 0);
// setupGaugeView
[self setupGauge];
// add run test button
[self setupRunTestButton];
// setup notification container
CGRect notificationContainerFrame;
if ([WRGlobalHelper currentDeviceVersion] >= 7) {
CGFloat statusBarHeight = [WRGlobalHelper statusBarHeight];
notificationContainerFrame = CGRectMake(0, [[self.navigationController navigationBar] bounds].size.height+statusBarHeight, self.view.bounds.size.width, 1);
for (UIView *subview in self.view.subviews) {
CGRect newFrame = subview.frame;
newFrame.origin.y += [WRGlobalHelper statusBarHeight];
subview.frame = newFrame;
}
} else {
notificationContainerFrame = CGRectMake(0, [[self.navigationController navigationBar] bounds].size.height, self.view.bounds.size.width, 1);
}
self.notificationContainerView = [[UIView alloc] initWithFrame:notificationContainerFrame];
self.notificationContainerView.clipsToBounds = NO;
self.notificationContainerView.layer.backgroundColor = [UIColor clearColor].CGColor;
[self.view addSubview:self.notificationContainerView];
// some other unrelated stuff omitted....
}
And the `viewDidLoad's for the VCs where the status bar is acting normal or bizarre but with shade is all quite plain as well, they look like
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self.view addGestureRecognizer:self.slidingViewController.panGesture];
}
Mind blown and I give up at this point. I've spent nearly 2 hours on this single issue already, and my brain hurts at the thought of the disappearing status bar. The almighty and omniscient SO, please help me! Thank you very much!
The status bar is not disappering, the text is just changing its color based on its assigned Style.
This answer will help

Stuck with UIActionSheetPicker , iOS

This is going to be a very targeted question , as its for people that have actually used the UIActionSheetPicker before.
I used it in my iphone applications and everything worked great , but now that i tried to implement it on my ipad i experienced some problems.
The main problem is that on ipad the picker appears as a "bubble" or "info window" if you prefer , which points at the spot where it was called , like a button a text field etc.
Below is an example of it :
You can see that the "info window" is pointing at the animals button.
In my application i have 4 different buttons. 2 are in the top side of the screen and 2 at the bottom.
Those who are at the bottom , call the picker very well and the picker appears on top of the buttons pointing down on them.
However , the ones on the top of the screen (almost like the one in the image) when they call the picker the picker appears much lower on the screen and doesnt point at them as it should ...
I mean i expected to appear just under the buttons pointing at them (like in the image), but they are almost in the center of the screen pointing nowhere..
Any ideas? Has someone experienced this before?
EDIT
In the beginning , i was calling the ActionSheetPicker inside the buttons action like this:
- (IBAction)selectTopic:(UIControl *)sender {
[ActionSheetStringPicker showPickerWithTitle:NSLocalizedString(#"CHOOSE_TOPIC", nil) rows:self.topics initialSelection:self.selectedIndex target:self successAction:#selector(topicWasSelected:element:) cancelAction:#selector(actionPickerCancelled:) origin:sender];
//when user picks a new topic we clean the titleField to make sure selected title of previous topic doesnt mix up with new topic
titleField.text = #"";
}
Now i am trying to call it like this:
- (IBAction)selectTopic:(UIControl *)sender {
ActionSheetStringPicker *thePicker = [[ActionSheetStringPicker alloc] initWithTitle:NSLocalizedString(#"CHOOSE_TOPIC", nil) rows:self.topics initialSelection:self.selectedIndex target:self successAction:#selector(topicWasSelected:element:) cancelAction:#selector(actionPickerCancelled:) origin:sender];
thePicker.presentFromRect = topicField.frame;
[thePicker showActionSheetPicker];
//when user picks a new topic we clean the titleField to make sure selected title of previous topic doesnt mix up with new topic
titleField.text = #"";
}
Where topicField is my TextField.
Sadly the result is the same. Even now that i am specifying where i want the arrow to point , the picker is called 300 pixels down.
The strange thing is though that even with another other button that is a bit lower than the previous the picker is again exactly 300 pixels down.
EDIT2
After noticing that the picker shows 300 pixels down , i decided to manually make it show 300pixels up , to point exactly on my button.
I used the following code :
- (IBAction)selectTopic:(UIControl *)sender {
//[ActionSheetStringPicker showPickerWithTitle:NSLocalizedString(#"CHOOSE_TOPIC", nil) rows:self.topics initialSelection:self.selectedIndex target:self successAction:#selector(topicWasSelected:element:) cancelAction:#selector(actionPickerCancelled:) origin:sender];
ActionSheetStringPicker *thePicker = [[ActionSheetStringPicker alloc] initWithTitle:NSLocalizedString(#"CHOOSE_TOPIC", nil) rows:self.topics initialSelection:self.selectedIndex target:self successAction:#selector(topicWasSelected:element:) cancelAction:#selector(actionPickerCancelled:) origin:sender];
CGRect pickerFrame = topicField.frame;
pickerFrame.size.height -= 300;
thePicker.presentFromRect = pickerFrame;
[thePicker showActionSheetPicker];
//when user picks a new topic we clean the titleField to make sure selected title of previous topic doesnt mix up with new topic
titleField.text = #"";
}
Amazingly the button once again appears in the same position 300pixels down. I start to believe that this one may not be the property to alter the position of the picker.
Any ideas ?
Setting the presentFromRect in your calling code won't make a difference since it will be reset based on the sender within the ActionSheetPicker code, instead you are going to need to modify the source code of the library.
The following (unmerged) commit on github should resolve the issue On iPad, set the popover to point properly at its container.
Basically within the AbstractActionSheetPicker.m file modify the - (void)presentPickerForView:(UIView *)aView method like the following
- (void)presentPickerForView:(UIView *)aView {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
self.presentFromRect = CGRectMake(0, 0, self.containerView.frame.size.width, self.containerView.frame.size.height);
[self configureAndPresentPopoverForView:aView];
}
else {
self.presentFromRect = aView.frame;
[self configureAndPresentActionSheetForView:aView];
}
}
After a brief look at the code, I would say that you want to make sure that the presentFromRect on the ActionPicker object is in the coordinates of the container that you are passing in on the init. For instance if I had one big view that contained a button:
This is untested:
UIView* someBigView = ... // get the big view
UIButton* someButton = ... // get the button that the big view contains
ActionSheetDatePicker* thePicker = [[ActionSheetDatePicker alloc] initWithTitle:#"Some Title"
datePickerMode:UIDatePickerModeDate
selectedDate:[NSDate date]
target:self
action:#selector(someMethod:)
origin:someBigView];
//the arrow should be pointing at the button
thePicker.presentFromRect = someButton.frame;
[thePicker showActionSheetPicker];
In my opinion, this library has a pretty big flaw in the fact that it takes an origin parameter that can be a button item or a container. It requires that you look at the source to understand it, instead of being (somewhat) obvious from the interface.

Memory management problem (release UIVIewCotroller)

I develop the game for iPad (composing image from puzzles). In my menu i choose level difficult (simple, medium or hard). After selecting the main playing field will be shown.
Here's place, where i create the main playing field:
- (void)simpleDiffButtonClicked:(id)sender
{
UIButton *button = sender;
if (simpleDiffButton == button) {
UIView *mySuperView = self.view.superview;
mainGame = [[MainGame alloc] initWithMode:1 andImage:nil]; //mainGame variable is declared in header file like: MainGame *mainGame;
mainGame.view.frame = CGRectMake(0, 0, 1024, 768);
[mySuperView addSubview: mainGame.view];
}
}
After this playing field is appears (there are a lot of sublayers adding to self.view.layer) and i can interact with it. When i want to quit from it, i click button "back". (here i want to release my viewcontroller)
- (void)backToMenuButtonClicked:(id)sender
{
UIButton *button = sender;
if (nextImageClick == YES) {
return;
}
if (backToMenuButton == button) {
self.view.layer.sublayers = nil; //here's an exception
[self.view removeFromSuperview];
}
}
After clicking "back" button everything is ok. And i can choose difficultly level again. A choose a level, and after it clicking "back" button again and at this place application crashes (EXC_BAD_ACCESS).
As i understand "self.view.layer.sublayers = nil" causes the exception.
Without it everything is ok. But memory is leaking. And after several minutes of playing app was crashes (memory warning 2).
I cannot solve the problem for about a week. I don't understand what to do to release my viewcontroller (or i need to release all sublayers in controller?).
Please, someone help me.
Thanks in advance.
Try to turn on NSZombieEnabled and check out Debugger and Console when it crush, it can give some more info about the problem.
P.S. NSZombieEnabled : http://www.cocoadev.com/index.pl?NSZombieEnabled (you may want to try useing .gdbinit).
P.P.S:
Btw, there might be some other problem in the line where "mainGame = [[MainGame alloc] initW...". -- where [mainGame release] is called? (it should be called as many as simpleDiffButtonClicked which allocs new instance of MainGame to mainGame variable (every time))

Resources