ios 10 - UITabBarController UITabBarItem - items slow to render - uitabbarcontroller

Upon login the initial display of my UI worked fine in iOS 9 with the UITabBarController showing all icons appropriately but in iOS 10 there is a noticeable delay of up to 5 - 10 seconds without any error in the log.
I've posted a bug to Apple ID- 29127274
The fix is below...
-J

Here is the code that cause the problem:
#implementation MyTabBarController
//...
- (void)viewDidLoad
{
[super viewDidLoad];
//the code below was causing the delay ... this worked find in iOS9
//tried legacy #define style
//[self setSelectedIndex:int(SelectedLandingToTab)];
//tried extern style .... both fail
//[self setSelectedIndex:SELECTEDLANDINGTAB];
}
//...
#end
If you comment out the setSelectedIndex then the UITabBar shows properly without delay.
-J

Related

Is open OpenGL completely broken after iOS 12.4?

I have an open source MS-DOS emulator for iOS here:
https://github.com/MattAndrzejczuk/MSDOS-for-iOS
This app runs well when using my older iOS devices such as the old iPhone 5S. but right after iOS 13.0 was released, the app delegate has trouble rendering SDL due to NOT calling UIKit methods on the main thread, but I'm not quite sure if this crash is due to OpenGL being completely deprecated, or, if maybe the newer SceneDelegate and AppDelegate changes which seemed to have been overhauled in iOS 13 are the cause of this issue. Just for some context, I've noticed that I cannot create a new Xcode project with a basic hello world label and build it directly for iOS 12 devices without doing this:
#import <UIKit/UIKit.h>
#interface AppDelegate : UIResponder <UIApplicationDelegate>
// ADD THIS TO DEFAULT APPDELEGATE.H:
#property (strong, nonatomic) UIWindow *window;
#end
This solution below, only somewhat fixed the problem:
Sources/dospad/Shared/DosEmuThread.m
#import "DosEmuThread.h"
extern int SDL_main(int argc, char *argv[]);
#implementation DosEmuThread
#synthesize started;
- (void)start
{
if (started) {
NSLog(#"DosEmuThread %p already started", self);
return;
}
NSLog(#"Start dosbox in new thread");
started = YES;
[NSThread detachNewThreadSelector:#selector(run) toTarget:self withObject:nil];
}
- (void) run {
#autoreleasepool {
/// UNCOMMENTING THIS SOMEWHAT FIXES THE ISSUE:
//dispatch_async(dispatch_get_main_queue(), ^{
char *argv[1] = {"dosbox"};
SDL_main(1, argv);
self.started = NO;
//});
}
}
#end
This fixes the app, in that I can reach the DOS prompt, but once I try to open something like this:
C:\ cd WAR2A
C:\ WAR2.EXE
I just get stuck at a blank screen, so obviously the quick fix of putting the dos thread on the main thread will break once SDL tries to run a full screen EXE app.
I'd really like to have the ability to emulate an x86 machine to run classic DOS games and even support Windows 95 for iOS, if there are alternative git repos out there that can do something similar, please let me know.

Upgrade Xcode8 with Swift3.0?

Recently, I have upgraded my Xcode to version8, some strange errors are appear in my console like below:
Painter Z index: 1023 is too large (max 255)
Painter Z index: 1023 is too large (max 255)
Painter Z index: 1023 is too large (max 255)
Painter Z index: 1023 is too large (max 255)
Painter Z index: 1023 is too large (max 255)
ERROR /BuildRoot/Library/Caches/com.apple.xbs/Sources/VectorKit_Sim/VectorKit-1228.30.7.17.9/GeoGL/GeoGL/GLCoreContext.cpp 1763: InfoLog SolidRibbonShader:
ERROR /BuildRoot/Library/Caches/com.apple.xbs/Sources/VectorKit_Sim/VectorKit-1228.30.7.17.9/GeoGL/GeoGL/GLCoreContext.cpp 1764: WARNING: Output of vertex shader 'v_gradient' not read by fragment shader
Any expert know how to deal with it?
Thank you in advanced.
The freezing problem happens only when run from Xcode 8.0 and only on iOS 10, whether in debug or release mode. MKMapView though seems fine when the app is distributed via App Store or 3rd party ad hoc distribution systems. The warnings you are seeing may or may not be related to the problem, I don't know.
What I've found is that the offending code is in MKMapView's destructor, and it doesn't matter what you do with the map view object or how you configure it, i.e. merely calling
#ViewController.h
#property(nonatomic,strong)MKMapView *mapView;
#end
anywhere in your code will freeze the app. The main thread hangs on a semaphore and it's not clear why
NOTE: this is a really sh*tty workaround but at least it will help you to debug your app without freezing. Retaining these objects means your memory usage will grow by about 45-50MB every time you create a view controller with a map.
So, let's say if you have a property mapView, then you can do this in your view controller's dealloc:
#ViewController.m
#interface ViewController ()
{
}
#end
#implementation ViewController
//the freezing problem happens only when run from Xcode 8.0
- (void)dealloc
{
#if DEBUG
// Xcode8/iOS10 MKMapView bug workaround
static NSMutableArray* unusedObjects;
if (!unusedObjects)
unusedObjects = [NSMutableArray new];
[unusedObjects addObject:mapView];
#endif
}
#end

Cocos2d crash when using dictation (microphone button) with CCTextField

I get a permanent crash when tapping on microphone button during the input in CCTextField. There's no crash on iPhone 4s iOS8, but the game is crashed on iPhone 5s iOS9 and iPhone 6+ iOS9. This issue seems to be the same as described here http://discuss.cocos2d-x.org/t/engine-crash-on-ios7/9129/10 and there's a solution for cocos2d-x there. Can someone provide a solution for cocos2d-objc ?
Okay, here's the workaround for cocos2d-objc:
- (void) update:(CCTime)delta{
CCGLView *ccglView = (CCGLView *)[[CCDirector sharedDirector] view];
[EAGLContext setCurrentContext:ccglView.context];
}

interval update debug of uknown interval

I've got the basic engine of a game put together rather nicely, my issue at the moment is that while running it from my computer onto my iPhone, I'm getting a strange debug message:
CCScheduler#scheduleSelector. Selector already scheduled. Updating interval from: 0.0000 to 0.0000
This debug message is being displayed every frame or nearly every frame
Now, I don't have any scheduled updates that are on interval 0, so this makes me think that it must be the generic scheduleUpdate command. I did a search entire project to see if any class had multiple scheduleUpdates and none do so now I am confused. Any thoughts?
I generally get this message when I schedule something that's already scheduled. See if there's anything like this in your code:
[self schedule:#selector(gameLogic:) interval:1.0];
- (void) gameLogic : (ccTime)dt
{
[self doLogic];
[self schedule:#selector(updateTimers:) interval:1.0];
[self schedule:#selector(gameLogic:) interval:1.0];
}
By repeatedly scheduling something inside a timed event, you'll get a warning that you've called the timer a second time.

WebView not showing in NSWindow

I am developing a C++ app and I need to display a NSWindow with a WebKit WebView inside it. I've coded up the Objective-C class which will manage creating and displaying the window but the WebView contained inside it does not display. Here is my code. Any idea on what is wrong and how I can fix it?
I'm compiling the below code with
$g++ -x objective-c++ -framework Cocoa -framework WebKit Foo.m main.m -o test
Foo.h
#import <Cocoa/Cocoa.h>
#import <WebKit/WebKit.h>
#interface Foo :NSObject {
NSWindow *window;
WebView *view;
}
- (void)displayWindow;
#end
Foo.m
#import "Foo.h"
#implementation Foo
- (id)init {
self = [super init];
// Window Container
window = [[NSWindow alloc] initWithContentRect:NSMakeRect(500.0f,500.0f,250.0f,250.0f)
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreNonretained
defer:NO];
// WebView
view = [[WebView alloc] initWithFrame:NSMakeRect(0, 0, 250.0f, 250.0f)
frameName:#"Frame"
groupName:nil];
[[view mainFrame] loadHTMLString:#"<html><head></head><body><h1>Hello</h1></body></html>"
baseURL:nil];
return self;
}
- (void)displayWindow {
NSLog(#"In Display window");
[window setContentView:view];
[window setLevel:NSStatusWindowLevel];
[window orderFrontRegardless];
sleep(5); // leave it up for 5 seconds
}
- (void)dealloc {
[window release];
[super dealloc];
}
#end
main.m
#import "Foo.h"
int main() {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[NSApplication sharedApplication];
Foo *foo = [[Foo alloc] init];
[foo displayWindow];
[foo release];
[pool release];
return 0;
}
You need to run the run loop. If you just order the window in and then exit, that's exactly what will happen: The window will appear, and then (five seconds later) your program will exit. You can run the run loop by telling the application (which you create but don't otherwise use) to run.
On the main thread of a Cocoa app, sleep is always the wrong answer. The same goes for its Cocoa cousins, +[NSThread sleepUntilDate:] and +[NSThread sleepForTimeInterval:]. The run loop will let you tell it to run for a fixed amount of time, but that won't get the application running; you do need to send the application the run message, which provides no opportunity to exit after a fixed interval.
The solution there is to first create an NSTimer object whose target is the application and whose selector is #selector(terminate:). Create it scheduled and non-repeating, with the interval set to five seconds. (Creating it scheduled means you don't need to schedule it separately—it is already ready to go from the moment you create it.) Then, send the application the run message. Five seconds later, the run loop will fire the timer, which will tell the application to terminate itself. This is assuming that you actually have a good reason to make your application quit after five seconds.
As noted by Yuji, every window in modern Cocoa should use NSBackingStoreBuffered.
And don't forget to release what you have created; you currently are forgetting that in the case of the view. See the Memory Management Programming Guide for Cocoa.
Once you have this working, I suggest moving toward a more typical architecture for this application:
Create a subclass of NSObject, and make an instance of that class your application's delegate.
Put the window and its WebView into a nib, and have the app delegate create a window controller to load and own the contents of that nib.
The app delegate should also be responsible for loading the page into the WebView and for setting up the self-termination timer.
Finally, create a nib to hold your application's main menu (the contents of the menu bar) and the application delegate. Interface Builder has a template for the first part; you create the app delegate object by dragging a blank Object in from the Library, setting its class on the ⌘6 Inspector, and dragging the connection from the application to the object. Then, you can reduce main to the single line that Xcode's project templates put in it: return NSApplicationMain(argc, argv);.
Doing all this will help your understanding of Cocoa, as well as your maintenance of the application—cramming everything into main will not scale.
You should also read the Cocoa Fundamentals Guide, if you haven't already.
Don't make it sleep. It stops the execution of the main thread, in which the GUI is dealt with. Instead, you need to run the run loop. Also, Cocoa needs to set itself up. So, call [[NSApplication sharedApplication] run] to set it up correctly and run the event loop.
Also, don't use backing mode other than buffered mode. Other modes are remnants from the time immemorial, and only NSBackingStoreBuffered should be used. As discussed in this Apple document, the non-retained mode is a remnant to support Classic Blue Box (OS 9 virtualizer), and newer classes like WebKit just can't operate within it.
So, what you need to do is practically:
change NSBackingStoreNonretained to NSBackingStoreBuffered.
Remove the line
sleep(5);
add a line
[[NSApplication sharedApplication] run];
after
[foo displayWindow];
Also, in order for an app to receive events from the window server correctly, you need to pack it into an app bundle. Compile it into a binary called foo, and create the following structure:
foo.app/
foo.app/Contents/
foo.app/Contents/MacOS/
foo.app/Contents/MacOS/foo <--- this is the executable
Then you can double-click foo.app from the Finder, or just call ./foo from the command line.