Developing a NavigationBar Based application including one Open GL View : How? - cocoa-touch

My question starts from a problem :
I started a project in Xcode : a Navigation Bar based one (with a TableView).
Then I added a few views, through IB or programmatically... which works perfectly fine.
Then, I decided to write my Own ViewClass, inherited from UIView, called OpenGlView (based on the view provided by Basic OpenGlES project in XCode), and its OpenGlViewController (inherited from UIViewController).
This works fine until I try to push the view Controller into my navBar: then I receive a "EXC__ BAD __ACCESS". I can't understand why it is ok whith any view but the one used for display OpenGL content...
And I actually have no idea how I can manage to develop a NavBar based App including a View displaying OpenGL contents... any idea?
(I also tried to add the OpenGlView as a subView of a basic UIView previously added to the NavigationBar, but I received the same error).
In the RootController :
OpenGlViewController *glvController;
if (glvController == nil)
{
glvController = [[OpenGlViewController alloc] initWithNibName:#"Gl View" bundle:nil];
glvController.title = #"GL View";
}
[self.navigationController pushViewController:glvController animated:YES];
in the OpenGlViewController :
- (void)loadView {
OpenGlView * view;
view = [[OpenGlView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
self.view = view;
[view release];
}

If it's localized to your OpenGL view, the crash may be the result of not properly initializing OpenGL items inside your view. See here for my recommendations on a potentially similar problem.

Related

Setting frame dose not working in OS7

I am trying to set the frame of my superview when presenting a view, the code i used is
navigationController.modalPresentationStyle = UIModalPresentationPageSheet;
navigationController.view.superview.frame = CGRectMake(32, 20, 1024-(32*2), 748);
[[self navigationController] presentModalViewController:navigationController animated:YES];
the code was working fine in OS6. but when come to OS7 its not working.
This method has been deprecated in iOS 7.
- (void)presentModalViewController:(UIViewController *)modalViewController animated:(BOOL)animated NS_DEPRECATED_IOS(2_0, 6_0);
Use the following :
- (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^)(void))completion NS_AVAILABLE_IOS(5_0);
If it was working in iOS 6 it was by chance. You are depending on the private view hierarchy used by iOS when presenting modal view controllers, and you've just found out why this is a bad idea. It can, and does, change without warning or documentation. See also, the view hierarchy of a UITableView between iOS 6 and 7.
If you want to make your own style of presented view controller it is safest to write it yourself from scratch rather than hijack one of the existing ones. Try using the custom style of presentation and writing a transition delegate.
Ok i found a solution.,
BOOL ios7 = [UIDeviceHardware isOS7Device];
if(ios7){
navigationController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
}
Now it works fine. :)

Custom UIView Not Showing Accessibility on Voice Over

I'm trying to get voice over working with an openGL view, specifically from the cocos2d framework.
From the Apple Accessibility guide I followed this section: Make the Contents of Custom Container Views Accessible
I've subclassed the view (CCGLView for cocos2d people), which is a UIView, to implement the informal UIAccessibilityContainer protocol.
UIAccessibilityContainer implementation in my subclassed UIView:
-(NSArray *)accessibilityElements{
return [self.delegate accessibleElements];
}
-(BOOL)isAccessibilityElement{
return NO;
}
-(NSInteger)accessibilityElementCount{
return [self accessibilityElements].count;
}
-(NSInteger)indexOfAccessibilityElement:(id)element{
return [[self accessibilityElements] indexOfObject:element];
}
-(id)accessibilityElementAtIndex:(NSInteger)index{
return [[self accessibilityElements] objectAtIndex:index];
}
This code is getting called and -(NSArray *)acessibilityElements is returning an array of UIAccessibilityElements. However the voice over controls are not showing up when I touch the screen. Any ideas on what I'm missing or doing wrong?
Other Information:
I'm using a storyboard and adding the CCGLView to the UIView in the storyboard. The _director.view is the CCGLView that I subclassed.
// Add the director as a child view controller.
[self addChildViewController:_director];
// Add the director's OpenGL view, and send it to the back of the view hierarchy so we can place UIKit elements on top of it.
[self.view addSubview:_director.view];
[self.view sendSubviewToBack:_director.view];
For a while I suspected that because I added the subview that this was causing it not to show up, but I also tried subclassing the UIView in the storyboard the same way but it was also not working.
Also this is how I am creating each UIAccessibilityElement in the array.
UIAccessibilityElement *elm = [[UIAccessibilityElement alloc] initWithAccessibilityContainer:view];
elm.accessibilityFrame = f;
elm.accessibilityLabel = t.letter;
elm.isAccessibilityElement = YES;
elm.accessibilityHint = #"Button";
elm.accessibilityValue = t.letter;
elm.accessibilityTraits = UIAccessibilityTraitButton;
Found a solution that is working now, in case anyone has this problem. -(id)accessibilityElementAtIndex:(NSInteger)index was returning a properUIAccessibilityElement but it looks like it wasn't getting retained by whatever Accessibility API is using it. I made a strong NSArray property to hold the UIAccessibilityElements and now it is working fine.

GKTurnBasedMatchmakerViewController works on iPad but not on iPhone

We've been having trouble with this issue for a while, and just cannot find the answer to it in the docs or online searches..
Our iOS game is based on OpenGL ES, and we are implementing GameCenter turn based gaming. The following code shows a matchmaking UI for creating a turn based match. This code works fine on my iPad 1 and iPad 3. However, it will not work on my iPhone 4S!
[ UPDATE: ] We were using a UIWindow at the top of the View hierarchy, with a GL View / Layer as a sub view. This obscured the new view when it was presented. I can see this window now by adding a UIView into the main window, and the GL view as a child of it. However, I still cannot interact with this view..
This code is from a .mm file where we mix C++ and Objective-C code.
// Configure the match making view, with our own delegate
GKTurnBasedMatchmakerViewController *mmvc =
[[GKTurnBasedMatchmakerViewController alloc]
initWithMatchRequest:request];
mmvc.showExistingMatches = YES;
// Uses our own delegate.
if(!g_pTurnBasedDelegate)
{
g_pTurnBasedDelegate = [[TurnBasedDelegate alloc] init];
}
mmvc.turnBasedMatchmakerDelegate = g_pTurnBasedDelegate;
// Get the main window's root controller and instruct it to show the match making delegate.
if(g_Env && g_Env->m_pWindow)
{
RefPtr<WindowIOS> pIOSWin = ref_static_cast<WindowIOS>(g_Env->m_pWindow);
UIWindow * pUIWin = (UIWindow *)pIOSWin->GetHandle();
UIViewController * pController = [pUIWin rootViewController];
if(pController)
{
g_pRootViewController = pController;
}
}
if(g_pRootViewController)
{
[g_pRootViewController presentViewController:mmvc animated:YES completion:nil];
}
Came back to this issue after a while. The problem was not with the Game Center controllers, but rather with how we were setting up our main application views. This just happened to work on iPad, but not on iPhone.
For our application, we need to initialize the whole view hierarchy in code instead of using a NIB / Storyboard.
Our old initialization steps were:
UIWindow init and make key.
UIWindow addView (our OpenGL window).
UIWindow addView (a touch responder UIView).
UIWindow rootViewController = [[ViewController alloc] init];
Adding our views directly to UIWindow would impede the functionality of View Controllers and cause undefined behavior on iPhone vs. iPad.
Our new initialization steps (to fix these issues if anyone is having them):
UIWindow init and make key.
UIWindow rootViewController = [[ViewController alloc] init];
rootViewController.view = [[GLAndTouchView alloc] init];
Hopefully, anyone stuck with the same problem will find this useful.

Menu Accessible Throughout My App - How do I code this?

I have an app that's pretty much a large presentation of a companies product.
I have some additional functionality which I need to be accessible throughout my app.
The intended functionality for this toolbar is that it'll sit as a small, subtle tab along the bottom of the screen. When you tap the tab, the menu will expand upward (i.e. animate it's frame.y property), allowing you to tap any of the buttons contained within the menu.
The difficulty I'm having is that the app currently spans over several view controllers, and as I need this accessible throughout, in the interest of not duplicating code it would seem appropriate to make this ViewController also, that I would just load into my other view controllers, but this, by all accounts isn't recommended by Apple.
How can I build this menu functionality without duplicating code? I've tried a few things but cannot get the menu to display on my view.
Below, I'll show what I have at the moment.
Code that will sit on any view controller:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
ToolboxMenu *toolboxMenu = [[ToolboxMenu alloc] init];
[self.view addSubview:toolboxMenu.view];
}
Code that builds the toolbar:
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"Creating View");
self.view = [[UIView alloc] initWithFrame:CGRectMake(0,0,88,209)];
self.view.backgroundColor = [UIColor clearColor];
UIImageView *toolboxImage = [[UIImageView alloc] initWithImage:[[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"popup_toolbox" ofType:#"jpg"]]];
toolboxImage.frame = self.view.frame;
[self.view addSubview:toolboxImage];
}
In the above code, the NSLog fires when the menu is initialised, but I see no menu.
Rather than try to inject this into every view, I would recommend creating a separate UIWindow and float it over the main UIWindow. This is how the keyboard is implemented. Doing it that way will avoid any changes to any of the existing views. You will need to handle device rotation by hand for it, but that shouldn't be too difficult.
IIRC Apple's TabViewController was designed differently in that it's backwards to how you describe above. A TabViewController is the main or master ViewController with siblings being the display ViewControlers. Basically you have one TabViewController that will tab between views.
I would recommend you either redesign your view hierarchy OR extend UIViewController with a class that manages and displays the lower tab menu. Then you can easily init a single class that handles that in each of your views.

"Application tried to present modally an active controller"?

I just came across a crash showing a NSInvalidArgumentException with this message on an app which wasn't doing this before.
Application tried to present modally an active controller
UITabBarController: 0x83d7f00.
I have a UITabBarController which I create in the AppDelegate and give it the array of UIViewControllers.
One of them I want to present modally when tapped on it. I did that by implementing the delegate method
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
If that view controller is of the class of the one I want to present modally, I return NO and do
[tabBarController presentModalViewController:viewController animated:YES];
And now I'm getting that error, which seems to mean that you can't present modally a view controller that is active somewhere else (in the tabbar...)
I should say I'm on XCode 4.2 Developer Preview 7, so this is iOS 5 (I know about the NDA, but I think I'm not giving any forbidden details). I currently don't have an XCode installation to test if this crashes compiling against the iOS4 SDK, but I'm almost entirely sure it doesn't.
I only wanted to ask if anyone has experienced this issue or has any suggestion
Assume you have three view controllers instantiated like so:
UIViewController* vc1 = [[UIViewController alloc] init];
UIViewController* vc2 = [[UIViewController alloc] init];
UIViewController* vc3 = [[UIViewController alloc] init];
You have added them to a tab bar like this:
UITabBarController* tabBarController = [[UITabBarController alloc] init];
[tabBarController setViewControllers:[NSArray arrayWithObjects:vc1, vc2, vc3, nil]];
Now you are trying to do something like this:
[tabBarController presentModalViewController:vc3];
This will give you an error because that Tab Bar Controller has a death grip on the view controller that you gave it. You can either not add it to the array of view controllers on the tab bar, or you can not present it modally.
Apple expects you to treat their UI elements in a certain way. This is probably buried in the Human Interface Guidelines somewhere as a "don't do this because we aren't expecting you to ever want to do this".
I have the same problem. I try to present view controller just after dismissing.
[self dismissModalViewControllerAnimated:YES];
When I try to do it without animation it works perfectly so the problem is that controller is still alive. I think that the best solution is to use dismissViewControllerAnimated:completion: for iOS5
In my case i was trying to present the viewController (i have the reference of the viewController in the TabBarViewController) from different view controllers and it was crashing with the above message.
In that case to avoid presenting you can use
viewController.isBeingPresented
!viewController.isBeingPresented {
// Present your ViewController only if its not present to the user currently.
}
Might help someone.
The same problem error happened to me when I tried to present a child view controller instead of its UINavigationViewController parent
I had same problem.I solve it. You can try This code:
[tabBarController setSelectedIndex:1];
[self dismissModalViewControllerAnimated:YES];
For React Native Developer - Problem might not be in AppDelegate Or main.m if app has been successfully build and is running and will crash after splash or perhaps the error screen
Issue might be due to use of fonts/resources that is not available with xcode and not properly configured.. You can find out the error by commenting certain portion starting from App.js and drilling inside the navigation/screens and commenting the components till you find the component that is generating the error....
In my case the resource of fontFamily was making an issue which was used right after splash in walkthrough screen
<Text style={{fontFamily: Fonts.roboto}}>ABC</Text>
Here font roboto wasnot configured properly. Wasted entire days just debugging the error hope its helps you
In my case, I was presenting the rootViewController of an UINavigationController when I was supposed to present the UINavigationController itself.
Just remove
[tabBarController presentModalViewController:viewController animated:YES];
and keep
[self dismissModalViewControllerAnimated:YES];
Instead of using:
self.present(viewControllerToPresent: UIViewController, animated: Bool, completion: (() -> Void)?)
you can use:
self.navigationController?.pushViewController(viewController: UIViewController, animated: Bool)
This is my way which supporting multiple Windows(from a single APP) on the iPad and nested modal present.
import UIKit
///✅Use this public method
public func SheetViewController(ViewController:UIViewController) {
for i in returnAvailableViewControllers().shuffled() {
if i.presentedViewController == nil && !ViewController.isViewLoaded {i.present(ViewController, animated: true, completion: {})}
}
}
///Returns all possible ViewControllers
private func returnAvailableViewControllers() -> [UIViewController] {
let 场景 = UIApplication.shared.connectedScenes
var 存储VC : [UIViewController] = []
for i in 场景 {
if i.activationState == .foregroundActive {
//⭐️Set up “foregroundActive” to give the user more control
var 视图控制器 = (i.delegate as? UIWindowSceneDelegate)?.window??.rootViewController
if 视图控制器 != nil {
存储VC.append(视图控制器!)
}
var 结束没 = true
while 结束没 {
//🌟Enumerate all child ViewController
视图控制器 = 视图控制器?.presentedViewController
if 视图控制器 != nil {
存储VC.append(视图控制器!)
} else {
结束没.toggle()
}
}
}
}
return 存储VC
}