UIkit elements can't see in overlaySKScene for AR - objective-c

I making some simple AR app with interfaces using overlaySKScene.
In viewDidLoad, I applied overlay scene in main ARSCNView(OverlayScene is my class inherited SKScene).
self.sceneView.overlaySKScene = [[OverlayScene alloc] initWithSize:self.sceneView.bounds.size];
self.sceneView.overlaySKScene.delegate = self;
Then, I added UIkit button in OverlayScene init.
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 200, 100)];
[button setTitle:#"button" forState:UIControlStateNormal];
button.layer.position = CGPointMake(self.view.frame.size.width/2, 200);
[self.view addSubview:button];
But, that button didn't appear on screen.
When I added sprite node in this scene, it worked.
Is there other method for it or bug?
Thank you.

OverlayScene's init isn't really an appropriate place to do that, as self.view will equal nil because when a scene is initialize it has yet to be added to the view hierarchy. A better choice might be the SKScene lifecycle method - (void)didMoveToView:(SKView *)view; like:
- (void)didMoveToView:(SKView *)view {
[super didMoveToView:view];
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 200, 100)];
[button setTitle:#"button" forState:UIControlStateNormal];
button.layer.position = CGPointMake(self.view.frame.size.width/2, 200);
[self.view addSubview:button];
}

Related

Lag / Delay on ModalViewController dismiss after loading an xib view over SKView

Imagine this scenario (some code below):
I have an SKView on a viewcontroller.
I load an xib view (external .xib file) over skview (xib view is a like small menu view that does not cover screen in full).
Then, I show a view controller modally from SKView's controller
When I dismiss this modal view controller, there is a lag on every second dismissal (so, i show it modally, dismiss, it is fine, then i repeat, there is delay, then repeat, works fine, then do again, there is delay ... and so on)
If I do not use SKView (if i just used UIView), that delay does not happen. It only happens when I use SKView.
What may be causing that? Here is simplified code that produces this problem:
#implementation NOZTestController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
// button that loads xib view onto the current skview
UIButton *showxib = [[UIButton alloc] initWithFrame:CGRectMake(20, 80, 280, 30)];
[showxib setTitle:#"Add xib view here" forState:UIControlStateNormal];
[showxib addTarget:self action:#selector(showxibTapped) forControlEvents:UIControlEventTouchUpInside];
// button that loads a view controller programmatically
UIButton *showmodal = [[UIButton alloc] initWithFrame:CGRectMake(20, 120, 280, 30)];
[showmodal setTitle:#"Show modal" forState:UIControlStateNormal];
[showmodal addTarget:self action:#selector(showmodalTapped) forControlEvents:UIControlEventTouchUpInside];
self.view = [[SKView alloc] initWithFrame:self.view.frame];
SKView *v = (SKView *)self.view;
//UIView *v = self.view;
[v addSubview:showxib];
[v addSubview:showmodal];
}
- (void)showxibTapped
{
// displays the xib view
[NOZPlayAgainView presentOnView:self.view inRect:CGRectMake(20, 200, 280, 160) withDelegate:self];
}
- (void)showmodalTapped
{
// displays the modal window
UIViewController *vc = [[UIViewController alloc] init];
UIButton *dismiss = [[UIButton alloc] initWithFrame:CGRectMake(40, 40, 240, 40)];
[dismiss setTitle:#"Dismiss" forState:UIControlStateNormal];
[dismiss addTarget:self action:#selector(dismissModal) forControlEvents:UIControlEventTouchUpInside];
[vc.view addSubview:dismiss];
[self presentViewController:vc animated:YES completion:nil];
}
- (void)dismissModal
{
[self.presentedViewController dismissViewControllerAnimated:YES completion:nil];
}
#end
It is caused by autolayout constraints on the xib view. To arrive to that conclusion, I created a simple view with a subview and added it to SKView. The problem I reported above happened only when I used auto layout constraints to place the subview. I don't know why this is happening but that is the reason for it.

my UITableViewCell setting button

I'm having trouble adding button to my UITableViewCell, the cell has two UILabels and two UIImageViews, sometimes the UIImageView will contain an image and sometimes a button:
In my UITableViewCell subclass I have:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if ( self ) {
// Initialization code
firstLock = [[UILabel alloc]init];
[firstLock setBackgroundColor:[UIColor clearColor]];
firstLock.textAlignment = UITextAlignmentLeft;
firstLock.font = [UIFont fontWithName:#"Arial-BoldMT" size:17];
secondLock= [[UILabel alloc]init];
[secondLock setBackgroundColor:[UIColor clearColor]];
secondLock.textAlignment = UITextAlignmentRight;
secondLock.font = [UIFont fontWithName:#"Arial-BoldMT" size:17];
firstLockImage = [[UIImageView alloc]init];
secondLockImage = [[UIImageView alloc] init];
[self.contentView addSubview:firstLock];
[self.contentView addSubview:secondLock];
[self.contentView addSubview:firstLockImage];
[self.contentView addSubview:secondLockImage];
}
return self;
}
When one of the UIImageViews is just an image no problem, but it crashes when I add a UIButton (imaged) as a subview.
In the UITableViewDataSource implementation:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UIImage *btnImage = [UIImage imageNamed:#"bike_ok.png"];
UIButton *button =[UIButton alloc];
[button setImage:btnImage forState:UIControlStateNormal];
[cell.secondLockImage addSubview:button];
Adding a button as a subview of the image view crashes:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Requesting the window of a view (<UIButton: 0x7bac7d0; frame = (0 0; 0 0); transform = [0, 0, 0, 0, 0, 0]; alpha = 0; opaque = NO; userInteractionEnabled = NO; layer = (null)>) with a nil layer. This view probably hasn't received initWithFrame: or initWithCoder:.'
*** First throw call stack:
What am I missing?
Thanks!
Just add! its important this line
[firstLockImage setUserInteractionEnabled:YES];
[secondLockImage setUserInteractionEnabled:YES];
Because the UIImageView has NO as default and the button doesn't work without it!
If you read the crash error it is quite easy to see where your issue is. You have not initialized your button.
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0,0,0,0)];
or you can use initWithCoder.
Hope this helps
Sam
Read the exception text - it says:
This view probably hasn't received initWithFrame: or initWithCoder:
Just a few lines up in your question, you are sending messages to a UIButton instance that you have only alloc'd and not sent any init... message to. That is your error.
Furthermore, you shouldn't directly call the alloc/init pair on UIButton as it's a class cluster and you should usually use +[UIButton buttonWithType:] to get a button instance.
EDIT I'm not 100% sure about that, actually. But you don't really know exactly what you'll get if you do initWithFrame: so I'd still go with buttonWithType: to get a custom button, which is what you want. END EDIT
So, change that line to:
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
Hope this helps!
change UIButton *button =[UIButton alloc]; (alloc w/o init?) to
UIButton *button =[UIButton buttonWithType:UIButtonTypeCustom];
//set frame
[button setFrame:(CGRect){x,y,w,h}];
+buttonWithType handles the alloc/init for your UIButton object

Why is my UIButton not displaying on my view?

I have a iOS5 project using storyboard and with ARC on.
I have a view in storyboard with the class thisViewController and in there I got a smaller subview which I dragged in and gave it the class thisView.
thisView has a custom drawRect function, that works and draws what I want nicely.
But I also want to add buttons dynamically, so I'll add them in the initWithFrame method of thisView like so:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
NSLog(#"This is called <3");
UIButton *btn= [UIButton buttonWithType:UIButtonTypeRoundedRect];
btn.frame = CGRectMake(0, 0, 50, 50);
btn.backgroundColor = [UIColor redColor];
[btn setTitle:#"Play" forState:UIControlStateNormal];
[btn addTarget:self action:#selector(buttonClick) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:btn];
[self bringSubviewToFront:btn]; // last thing I tried, didn't work, thought z-index was to low or something
}
return self;
}
The function is being called since the NSLog displays, but the button is nowhere to be found
--EDIT--
Extra information:
ThisView.h
#interface RadarView : UIView <CLLocationManagerDelegate>{
CLLocation *currentLocation;
}
Dont add the SubView in the init method.
Add the SubView in the - (void)layoutSubviews.
- (void)layoutSubviews {
[super layoutSubviews];
if (![self viewWithTag:12345]) {
UIButton *btn= [UIButton buttonWithType:UIButtonTypeRoundedRect];
btn.frame = CGRectMake(0, 0, 50, 50);
btn.tag = 12345;
btn.backgroundColor = [UIColor redColor];
[btn setTitle:#"Play" forState:UIControlStateNormal];
[btn addTarget:self action:#selector(buttonClick) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:btn];
}
}
I found what the problem was thanks to some comments and the chat
There was an init in the radarviewcontroller, which triggered initwithframe, which made the NSLog display, and the initwithcoder wasn't used so I didn't see anything, that was the problem and got stuff mixed up. Thanks for commenting and helpin!

Create UIView programmatically without Interface Builder

I try to create a view without IB and make it separated with its controller. The view is MediaPlayerView contains two buttons and the controller is MediaPlayerViewController. I called the view in controller and adding a Movie Player view in it. The buttons is showing but the movie view just dark screen. What's wrong with my code?
Here is my code:
MediaPlayerView.m
-(id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// Initialization code
UIButton *audioFileButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
UIButton *shortSoundButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[audioFileButton setFrame:CGRectMake(0, 40, 150, 40)];
[shortSoundButton setFrame:CGRectMake(0, 100, 200, 40)];
[audioFileButton setTitle:#"Play Audio File" forState:UIControlStateNormal];
[shortSoundButton setTitle:#"Play Short Sound" forState:UIControlStateNormal];
_viewController = [[MediaPlayerViewController alloc] init];
[audioFileButton addTarget:[self viewController]
action:#selector(playAudioFile:)
forControlEvents:UIControlEventTouchUpInside];
[shortSoundButton addTarget:[self viewController]
action:#selector(playShortSound:)
forControlEvents:UIControlEventTouchUpInside];
[self addSubview:audioFileButton];
[self addSubview:shortSoundButton];
}
return self;
}
In MediaPlayerViewController.m, here is my loadView and viewDidLoad:
loadView:
MediaPlayerView *mPlayer = [[MediaPlayerView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[mPlayer setBackgroundColor:[UIColor clearColor]];
[self setView:mPlayer];
[mPlayer release];
viewDidLoad:
[super viewDidLoad];
float halfHeight = [[self view] bounds].size.height / 2.0;
float width = [[self view] bounds].size.width;
[[[self moviePlayer] view] setFrame:CGRectMake(0, halfHeight, width, halfHeight)];
[[self view] addSubview:[[self moviePlayer] view]];
Forgive for my bad writing, cause I am a newbie either in here, Objective-C or english.

Button not clickable after adding as a subview to a UIView

I have created a class called UICustomButton, which is a subclass of UIView. I added a UIButton to UIView as a subview as shown in my code below:
-(id)initWithButtonType:(NSString *)type
{
self = [super init];
if (self)
{
self.customButton = [self setupButtonWithTitle:type andFrame:frame];
[self addSubview:self.customButton];
self.customButton addTarget:self action:#selector(buttonPressed) forControlEvents:UIControlEventTouchUpInside];
}
return self;
}
The problem I am facing is that although the button appears, they are not clickable. Is there something wrong with the way I am adding the buttons to the UIView?
EDIT: To add on, I am using this custom button class instance to a cell:
UICustomButton *customButton = [[UICustomButton alloc]initWithFrame:someFrame];
[cell.contentView addSubView:customButton];
check the frame of your UICustomButton object, and if self.customButton is out of its superView.
Make sure that the frame of the subview is within the frame of its superview. I encountered the issue twice and both times the frame of the subview was incorrect.
You should check if all properties userInteractionEnabled are on:
Check that property for UITableView where your cells with this view are displayed
Check that property for UITableViewCell where you add this view as subview
Check that property for UICustomButton
Check that property for customButton in -(id)initWithButtonType:(NSString *)type
My button was not working because i had two views in each other. The first view, as you can see, has a width and heigth of 0 pixels. I've made this view the same size as view2 and then my button was clickable.
UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(325, 346, 0, 0)];
view1.alpha = 0.90;
UIView *view2 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 450, 150)];
[view2.layer setCornerRadius:10.0f];
view2.backgroundColor = [UIColor whiteColor];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btn addTarget:self action:#selector(addClosedToCollection) forControlEvents:UIControlEventTouchUpInside];
[btn setFrame:CGRectMake(30, 30, 300, 32)];
[btn setTitle:#"i'm a button" forState:UIControlStateNormal];
[view2 addSubview:btn];
[view1 addSubview:view2];
i hope i've helped somebody out :)
Your outer view probably has a height of 0. Add constraints that makes it the same height as (or higher than) the subviews, or create it with a frame that is large enough.
try putting this after the if statement:
self.isTouchEnabled = YES;