iOS Game Controller framework : How to use "startWirelessControllerDiscoveryWithCompletionHandler" - ios

When game controller be paired from system setting, all is fine.
But I want to discover & pair game controller in my app.
Actually I found that it seems feasible by Apple's docs.
doc link : Discovering and Connecting to Controllers.
I have a game controller which is in pairing...
But I found the log of function "startWirelessControllerDiscoveryWithCompletionHandler" never be shown.
Seems the behavior does not conform.
I call "startWirelessControllerDiscoveryWithCompletionHandler" when app load...
I also call "stopWirelessControllerDiscovery", but still same.
- (void)viewDidLoad {
...
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(gameControllerDidConnect:) name:GCControllerDidConnectNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(gameControllerDidDisconnect:) name:GCControllerDidDisconnectNotification object:nil];
[GCController startWirelessControllerDiscoveryWithCompletionHandler:^{
NSLog(#"Finished finding controllers");
[self completionWirelessControllerDiscovery];
}];
...
}
- (void)completionWirelessControllerDiscovery {
if (isDebug) {
NSLog(#"%s-%d", __FUNCTION__, __LINE__);
}
}
Someone has experiences on this?

My experience has been that it does not work for pairing a controller - I have always had to pair my game controllers directly to the device. I've been developing a wrapper around GCController, so I've tested about 5 different MFi controllers with no luck getting GCController to manage the pairing process.

Related

Listen for application terminate from a library/framework?

Is it possible to listen for the iOS application terminate/going to background mode from a library/framework, which is included into that app?
As I see, dealloc method (for a class which implemented in the library) does not called in case if whole app terminating (correct me if I'm wrong).
UPD.: The question is about libraries/frameworks. I know about applicationWillTerminate method for AppDelegate, but it's for the app itself, not for a library/framework.
Registering for UIApplicationWillTerminateNotification via NotificationCenter will work.
Code:
-(void)addAppTerminationNotifier
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(appWillTerminate) name:UIApplicationWillTerminateNotification object:nil];
}
-(void)appWillTerminate
{
//..... task to done before termination
}

NSNotificationCenter crashes my app

I've added a NSNotificationCenter observer that calls 2 selectors with the same name on two different view controllers.
It works, but when I run the app sometimes it crashes with this error message:
Thread 1: EXC_BAD_ACCESS (code=1, address=0x18)
or
Thread 1: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
Anyone has an idea why it crashes? Thank you!
.
My code:
fetchFromParse:
-(void)sendAllStores
{
[[NSNotificationCenter defaultCenter]postNotificationName:#"getStoresArrays" object:nil userInfo:self.storesDict];
}
firstVC.m:
- (void)viewDidLoad {
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(getStoresArrays:) name:#"getStoresArrays" object:nil];
}
-(void)getStoresArrays:(NSNotification*)notification
{
NSLog(#“Working”);
}
secondVC.m:
-(void)prepareArrays
{
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(getStoresArrays:) name:#"getStoresArrays" object:nil];
}
-(void)getStoresArrays:(NSNotification*)notification
{
NSLog(#“Working”);
}
AppDelegate.m:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.secVC=[[secondVC alloc] init];
[self.secVC prepareArrays];
fetchFromParse *fetchFromParseObj=[[fetchFromParse alloc] init];
[fetchFromParseObj getStoresFromParse];
Return YES;
}
Notification Crashes
Typically you might see a crash of this nature if you attempt to close a view controller without removing the observer. So that part of the answer provided by Mr. Patil, is absolutely required. Your use-case will vary about where and how you remove the observer. If you remove it too soon you might end up crashing if you try to reference any related objects.
So you might want to remove the self.storesDict object or at least verify that it is not nil before using it.
Debugging
Here's a quick tutorial on debugging with Xcode. It's for an older version but it should get you up to speed quickly. You can also review Apple docs for more on collecting crash logs.
Logs
You should go to the reports navigator and copy a bit more of your log so that we can determine a more precise cause of the issue. You can add a breakpoint right before the faulty code and then step through the issue. Copy the debug console if nothing else.
Getting the crash log
You can open Xcode go the Window menu select Devices. Select your attached device (iPhone/iPad) and click the View Device Logs button. From the list select your app name/crash date. Copy the data to the question.
More Information
The more information you provide on crashes the more likely we can help you. I suspect that the answer is you are either trying to access something that is nil or not releasing the observer at the right time. It might not be appropriate to release the observer when your view disappears but you have not provided enough information to make that obvious.
How do the different view controllers work together? Are you certain that the Notifications is causing the crash?? Put a breakpoint at the post notification and in each selector and then debug the app until it crashes. You will need to identify the conditions that precede the crash. I'll refine this answer if you let me know when you update the question.
First thing I would do is do a global search and make sure no other classes are listening to that notification. Then I would make sure that in the classes that you have added an observer for that notification you do the following:
-(void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
Add this
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
//Has to be unregistered always, otherwise nav controllers down the line will call this method
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
hope it helps.
Are you sure that 'addObserver', 'postNotification' and 'removeObserver' are always called on the main thread?
Please doublecheck with:
if ([NSThread isMainThread])

How to reset the app after the midnight

I am working on Pedometer application via using CMPedometer Class. It works fine and I cross-checked the value via built in app- HealthKit. However, when I wake up this morning and I was still seeing the yesterday value.
Then I killed the app and reopened it again, then it showed me today value.
My question is how to handle this issue?
you can use applicationWillEnterForeground Delegate in your ViewController or Model ...
( if you want handle in specific VC or model you must register it ) or you can use this Delegate from your appDelegate
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(updateData) name:UIApplicationDidBecomeActiveNotification object:[UIApplication sharedApplication]]; // Dont forgot about removeObserve
-(void)updateData{
[[CMPedometer sharedInstance]update]; // update your data
// now you should update Your UI
[self.tableView reloadData];}

iOS Google Analytics memory growing out of control FAST

I've used Google Analytics on several iOS apps. No problems. This time, problem.
I do the basic setup using version 3.0. Add library/header, include required frameworks, and stuff the boiler plate code into the AppDelegate.m. So far so good, everything works as expected. I take my first UIViewController and change it to extend GAITrackedViewController and it hits the fan. The app freezes up on the first screen and memory usage starts going up about 4Meg per second. So I change the UIViewController back and all is good. I try making the screen name call manually in viewDidLoad.
// Analytics
id tracker = [[GAI sharedInstance] defaultTracker];
[tracker set:kGAIScreenName value:#"Initial"];
[tracker send:[[GAIDictionaryBuilder createAppView] build]];
Same thing happens. My view controller has a couple custom container views and it the root view controller on a generic UINavigationViewController. I figure it's probably the custom containers confusing it about which is the active view controller and what screen name to use (but I'm not seeing any sign of this in the logging).
Has anyone run into this problem and been able to nail down exactly what's causing it and how to work around it?
João's answer is correct, but I'd like to explain it more.
From Google's Getting Started document
If your app uses the CoreData framework: responding to a notification,
e.g. NSManagedObjectContextDidSaveNotification, from the Google
Analytics CoreData object may result in an exception. Instead, Apple
recommends filtering CoreData notifications by specifying the managed
object context as a parameter to your listener.
What that means is...
// This code will cause a problem because it gets triggered on ANY NSManagedObjectContextDidSaveNotification.
// (both your managed object contact and the one used by Google Analytics)
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(managedObjectContextDidSave:)
name:NSManagedObjectContextDidSaveNotification
object:nil];
// This code is safe and will only be trigger from the notification generated by your Managed Object Context.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(managedObjectContextDidSave:)
name:NSManagedObjectContextDidSaveNotification
object:myManagedObjectContext];
Now I read the docs and I had done this properly, but I was still having the problem. Turns out I didn't update my code for when I removed the notification.
// Not Safe
[[NSNotificationCenter defaultCenter] removeObserver:self
name:NSManagedObjectContextDidSaveNotification
object:nil];
// Safe
[[NSNotificationCenter defaultCenter] removeObserver:self
name:NSManagedObjectContextDidSaveNotification
object:myManagedObjectContext];
The moral of the story is, pay attention to your notification listeners. It takes a couple seconds to specify a listener for a specific object and it can take a long time to debug an issue because you accidentally listening to events you don't want to or remove listening to events.
Solution 1: Use a specific moc on object parameter when observing NSManagedObjectContextDidSaveNotification, this will allow you to observe only saves on the given moc.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(managedObjectContextDidSave:)
name:NSManagedObjectContextDidSaveNotification
object:managedObjectContext];
Solution 2: If you are using the Core Data technique of merging mocs created on background threads, you cannot easily solve in the suggested way, so the alternative is to change your method that handles notification in order to avoid merging when the persistentStoreCoordinator of the saved moc doesn't match the persistentStoreCoordinator of your main moc.
- (void)managedObjectContextDidSave:(NSNotification *)notification {
if ([NSThread isMainThread]) {
NSManagedObjectContext *savedMoc = notification.object;
// Merge only saves of mocs that are not my managedObjectContext
if (savedMoc == self.managedObjectContext) {
return;
}
// Merge only saves of mocs that share the same persistentStoreCoordinator of my managedObjectContext (i.e.: ignore the save of Google Analytics moc)
if (savedMoc.persistentStoreCoordinator != self.managedObjectContext.persistentStoreCoordinator) {
return;
}
[self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
}
else {
[self performSelectorOnMainThread:#selector(handleBackgroundContextSaveNotification:) withObject:notification waitUntilDone:YES];
}
}
I was having the exact same problem.
I've managed to find the solution in my case: I was registering to NSManagedObjectContextDidSaveNotification without specifying the context:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(managedObjectContextDidSave:)
name:NSManagedObjectContextDidSaveNotification
object:nil];
Removing this listener solved my out of memory problems.
Cheers
Im working on XMPP Framwork and as soon i fixed GA crash. This one failed https://github.com/robbiehanson/XMPPFramework/blob/master/Extensions/CoreDataStorage/XMPPCoreDataStorage.m
ANy easy way to solve this issue.
https://github.com/robbiehanson/XMPPFramework/issues/577

Updating UI from IOS library

Could somebody give me guidance/starting point on how I would update a UI Text Label in an IOS app from a library.
I have temperature data being received from a BT module in a library connected to my app. I want to send that Integer data to my app and update the UI Text label.
NOTE: I have full access to the library.
Any help is appreciated
I think what you are asking for is a way to provide feedback to an application from your Cocoa static library.
I would suggest that you have a look at the NSNotificationCenter class. For example, say that you have a class BTThermometer that, upon the reception of a new measurement calls:
[[NSNotificationCenter defaultCenter] postNotificationName:#"com.my.BTThermometer.NewValue" object:self];
Then, in you application, you could do something like:
[[NSNotificationCenter defaultCenter] addObserverForName:#"com.my.BTThermometer.NewValue" object:self queue:nil usingBlock:^(NSNotification* n) {
dispatch_async(dispatch_get_main_queue(), ^{
someLabel.text = ((BTThermometer*)n.object).temperatureValue;
}
}];
This is a standard mechanism in iOS to decouple your application from the internal workings of your library. The only coupling is the name itself, and of course it is usually a good idea to use a constant (e.g. #define kMyTemperatureEvent #"com.my.BTThermometer.NewValue) so that the compiler catches any typos.

Resources