How to show custom logs from App to Crashlytics dashboard - crashlytics

I am trying to report custom logs from my app to Crashlytics without any crashes. I want to log a particular button action and display it in the Crashlytics dashboard. Is there a way to do this in Crashlytics?

- (void)recordError:(NSError *)error;
- (void)recordError:(NSError *)error withAdditionalUserInfo:(nullable CLS_GENERIC_NSDICTIONARY(NSString *, id) *)userInfo;
Just use the instance of Crashlytics and you can receive your non-fatal issue with the custom error.
Also, you can send additional logs
CLSLog(NSString *format, ...)
And will be helpful to use Answers if you need to see some actions statistic or events.
+ (void)logCustomEventWithName:(NSString *)eventName
customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;

Related

FirebaseStorage Completion block not called. Objective-C

I am trying to simply load in a picture from firebase storage into my IOS app, but my completion block is not being called.
I use a TableViewController initially which loads plenty of pictures just fine. When I click on an item in the tableview it presents a simple view controller modally. I use the same code that successfully loads pictures in the TableViewController. In this modally presented view controller, my FirebaseStorage completion blocks do not execute. When I exit this view controller, the TableViewController can still load load pictures as necessary as I request.
I have enabled logging with -FIRAnalyticsDebugEnabled
and still do not receive any errors in my log.
I have allowed all read and writes temporarily in my rules for FirebaseStorage.
I have seen this question iOS setValue withCompletionBlock not called which states in the comments that a specific version of firebase had some issue with FirebaseDatabase blocking some other completion blocks.
The documentation said "Fixed a race condition where performing a transaction or adding an event observer immediately after connecting to the Firebase Realtime Database service could cause completion blocks for other operations to not be executed." from https://firebase.google.com/support/release-notes/ios#3.6.0
In the above question the asker fixed the problem by upgrading to Firebase 3.7.1, I am using 5.0.1
Here are the versions I am using
Using Firebase (5.0.1)
Using FirebaseAnalytics (5.0.0)
Using FirebaseAuth (5.0.0)
Using FirebaseCore (5.0.1)
Using FirebaseDatabase (5.0.0)
Using FirebaseInstanceID (3.0.0)
Using FirebaseStorage (3.0.0)
Using GTMSessionFetcher (1.1.15)
Using GoogleToolboxForMac (2.1.4)
Using leveldb-library (1.20)
Using nanopb (0.3.8)
Generating Pods project
I have logged all along my code to find that my code is being called, but the completion block is never executed. I am using the proper children ids, so I know that the storage reference does exist. I also know it is not a connection problem because the other pictures load fine just seconds before.
- (void)loadPicture {
NSLog(#"Attempting to load picture");
FIRStorageReference *ref = [[self.storageRef child:self.detailItem.faction] child:[self.detailItem firebaseEntry]];
[ref dataWithMaxSize:1024*1024 completion:^(NSData * _Nullable data, NSError * _Nullable error) {
NSLog(#"Got a result!");
}];
I am completely lost on what steps to take next. Has anyone experienced something similar or have any advice?
I appreciate any feedback that might help! Thanks!
Import this first
#import "UIImageView+FirebaseStorage.h"
and then for load image From reference use this
FIRStorageReference *gsReference = [[self.storageRef child:self.detailItem.faction] child:[self.detailItem firebaseEntry]];
[yourImage sd_setImageWithStorageReference:gsReference placeholderImage:nil];
I have solved the problem by creating a new ViewController to do the same action from scratch. Unfortunately I don't know what the original problem was or how to reproduce it. My original ViewController was about as simple as possible. The problem seemed like a strange glitch/flaw in the API, xcode, or emulator since no errors were present and it fixed itself in the new ViewController using the same exact code.
Everything else I saw online pointed to a issue involving Firebase 3.6.0 and below. Make sure you are using a recent Firebase version and then recreate the same ViewController and your problem will likely be fixed.

Passing data from Siri to other apps in Objective-C?

We are implementing Sirikit for one of our application. We are able to send message using SiriKit intent INSendMessageIntent. Upon “Send” Siri command handling, we need to pass some of the information to other application.
We have figured out [self.extensionContext openURL] to open application from intentViewController. As we observed that, there is configureWithInteraction of IntentViewController which gets called every time Siri processes each user command. Since we need to open application only on “Send” Siri command, we are not able to identify current processing state i.e. “Send”.
OR is there anyway to call openURL from intentHandler?
We are completing IntentResponse as mentioned below.
NSUserActivity *userActivity = [[NSUserActivity alloc] initWithActivityType:#“com.xxxxxx.xxx.myapp”];
INSendMessageIntentResponse *response = [[INSendMessageIntentResponse alloc] initWithCode:INSendMessageIntentResponseCodeSuccess userActivity:userActivity];
NSLog(#"response is %#",response);
completion(response);
We are expecting following function from containing app’s delegate to be called when action gets completed (i.e.INSendMessageIntentResponse is passed to completion handler)
-(BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler
Several years passed ... but anyway, maybe it will help someone.
You can pass parameters with user activity you created.
[userActivity addUserInfoEntries: ]

XPCService not getting launched from app

I am trying a simple sample app on XPCServices, in which I am following below steps:
Step 1: Created a sample project and added target - XPCServices with name - HelperProcess to it. When the target is created XCode automatically generates below files:
HelperProcessProtocol.h
HelperProcess.h
HelperProcess.m
main.m
Step 2: In main.m added a log statement within implementation of ServiceDelegate:
- (BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection {
// This method is where the NSXPCListener configures, accepts, and resumes a new incoming NSXPCConnection.
NSLog(#"Log which is never displayed :(");
// Configure the connection.
// First, set the interface that the exported object implements.
newConnection.exportedInterface = [NSXPCInterface interfaceWithProtocol:#protocol(HelperProcessProtocol)];
// Next, set the object that the connection exports. All messages sent on the connection to this service will be sent to the exported object to handle. The connection retains the exported object.
HelperProcess *exportedObject = [HelperProcess new];
newConnection.exportedObject = exportedObject;
// Resuming the connection allows the system to deliver more incoming messages.
[newConnection resume];
// Returning YES from this method tells the system that you have accepted this connection. If you want to reject the connection for some reason, call -invalidate on the connection and return NO.
return YES;
}
Step 3: In AppDelegate added below code in applicationDidFinishLaunching:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Insert code here to initialize your application
_connectionToService = [[NSXPCConnection alloc] initWithServiceName:#"HelperProcess"];
_connectionToService.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:#protocol(HelperProcessProtocol)];
[_connectionToService resume];
}
Problem is -
When I launch the app, neither the log added in
listener:shouldAcceptNewConnection: is displayed nor the helper
process appears in Activity Monitor :(
Here is the code: XPCShootOut
Note: I am trying this on XCode 6.0
Is there any additional setup which I need to do to make it working? Please suggest.
-- Update --
I tried to refer this sample from apple: AppSandboxLoginItemXPCDemo
When I tried to run it on XCode 6, it displayed error message - 'No signing identity found'. Since I don't have registered mac developer account, in build settings for - iDecide and iDecideHelper I changed 'Code Signing Identity' as 'Don't Code Sign'.
I got a warning for each of the targets:
Code Sign warning: CODE_SIGN_ENTITLEMENTS specified without specifying CODE_SIGN_IDENTITY. It is not possible to add entitlements to a binary without signing it.
This time when I compiled the build, it worked as expected.
Now I tried to follow the steps specified in its ReadMe.txt file, specifically I performed these steps in my sample app:
Step 1: Updated - Main App Target -> Capabilities Tab
Turned on 'App Sandbox'
Turned on 'App Groups'
Added an app group - 'XYZ'
Step 2: Updated - Helper Target -> Capabilities Tab
Turned on 'App Sandbox'
Enabled 'Outgoing Connections (Client)'
Turned on 'App Groups'
Added an app group - 'XYZ'
Step 3: Updated - Helper Target -> General Tab -> Bundle Identifier, added 'XYZ' prefix to it.
On running the app in console it displayed these messages:
10/12/14 6:27:42.159 PM xpcd[554]: (null): Code identity[pid: 11875::Devarshi-Kulshreshtha.XPCShootOut (/Users/devarshi/Library/Developer/Xcode/DerivedData/XPCShootOut-aaedwraccpinnndivoaqkujcmhmj/Build/Products/Debug/XPCShootOut.app)] is not in ACL for container: ~/Library/Containers/Devarshi-Kulshreshtha.XPCShootOut/Data -- allowing access.
10/12/14 6:27:43.712 PM appleeventsd[63]: <rdar://problem/11489077> A sandboxed application with pid 11875, "XPCShootOut" checked in with appleeventsd, but its code signature could not be validated ( either because it was corrupt, or could not be read by appleeventsd ) and so it cannot receive AppleEvents targeted by name, bundle id, or signature. Error=ERROR: #100013 { "NSDescription"="SecCodeCopySigningInformation() returned 100013, -." } (handleMessage()/appleEventsD.cp #2072) client-reqs-q
Neither app performed its intended function nor it displayed the log message added in listener:shouldAcceptNewConnection: delegate.
I am clueless. Kindly suggest if I am missing any thing? Is it possible to get XPC service sample app working without a registered mac developer account?
I don't think you can launch XPC services without having them signed.
Even for testing and debugging the code sign build infrastructure needs to be setup.
I think the Mac developer certificate is free you don't need a paid account for that.

Detecting user canceling SKReceiptRefreshRequest to sign in

When we need to refresh an iOS7 receipt, the appropriate way to do that is to use SKReceiptRefreshRequest. This brings up an Apple dialog for the user to sign in using their Apple ID. It also allows them to Cancel. How can we detect if the user presses Cancel? (Of course, in iOS6, this can be done using catching the cancel event for [[SKPaymentQueue defaultQueue] restoreCompletedTransactions]).
The SKReceiptRefreshRequest object has a delegate with two methods:
- (void)requestDidFinish:(SKRequest *)request;
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error;
In my code the requestDidFinish delegate method is called if the user does or does not press cancel.
The reason this is important to me is that I want to cancel the restore process if the user presses Cancel. If there was simply no receipt present after the refresh request, this might be relatively easy. However, sometimes there is a receipt (with some purchases) present in the app before the SKReceiptRefreshRequest, and so it stays in the app if the user cancels from the sign-in dialog.
I have two ideas for how to do this:
1) Delete the receipt from the bundle prior to the refresh request. The apparent problem with this is that the app can't remove files from the bundle (e.g., see Delete file from bundle after install). I tried. Nope.
2) Check the bytes of the receipt before the refresh request and after; if they differ, then this should indicate the user didn't press Cancel. If they don't differ, I'm not sure that does indicate they pressed Cancel. If the receipt contains purchases, I think that the bytes will differ because a refreshed receipt should have different transaction id's (but the same "original" transaction id's). If the receipt contains no purchases, I'm not sure about that.
Update, 11/9/15; I've just noticed that the delegate response to the user pressing Cancel appears to have changed. Now, didFailWithError is called. The problem of detecting user cancellation remains, however. How can we distinguish between the user pressing Cancel and a genuine error? I've been testing on iOS8.4 and iOS9.2 (beta). I have now reported this lack of distinguishability as a bug to Apple (bug #23476210).
Update, 11/10/15; This issue does not appear with iOS 9.0.2! I just tried this now with all three systems, with the same app binary, in the same approximate interval of time (within 20 minutes for all three systems): (A) iOS9.2 (13C5050d): Issue does occur (didFailWithError is called and can't distinguish between a real error and user pressing cancel), (B) iOS9.0.2, issue does not occur (requestDidFinish is called), and (C) iOS8.4.1, issue does occur. With all three system versions, this is running on real hardware, not the simulator.
iOS 9.2.1, Xcode 7.2.1, ARC enabled
I understand you asked this 2 years ago, but I recently had my run in with this issue and found a solution, and wanted to share here so others can save some time.
1) You may elect to store the receipt into keychain and access a copy of it, this allows you to delete it or refresh it as you see fit.
2) Yeah you can definitely check if it changed, I think the simplest way to do that is to use:
[receipt isEqualToData:(NSData *)(copyReceiptObject)]
My suggestion is as follows:
The key is to expect the error you get from the method:
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error;
that gets called when the user taps cancel after the log in dialogue comes up to sign in to iTunes Store. There are many custom was you could do the refresh request, so the results may vary, but here is the different error you get for my request:
When there is no connection to iTunes:
Error Domain=SSErrorDomain Code=110 "Cannot connect to iTunes Store"
UserInfo={NSLocalizedDescription=Cannot connect to iTunes Store,
NSUnderlyingError=0x13c76d680 {Error Domain=NSURLErrorDomain
Code=-1009 "Cannot connect to iTunes Store"
UserInfo={NSLocalizedDescription=Cannot connect to iTunes Store,
NSErrorFailingURLStringKey=
{ your product ids and corresponding URIs here }
, _kCFStreamErrorCodeKey=8, _kCFStreamErrorDomainKey=12,
NSLocalizedDescription=The Internet connection appears to be offline.}}}
When the user taps cancel:
Error Domain=SSErrorDomain Code=16 "Cannot connect to iTunes Store"
UserInfo={NSLocalizedDescription=Cannot connect to iTunes Store,
NSUnderlyingError=0x13c6ac7b0 {Error Domain=AKAuthenticationError
Code=-7003 "(null)"}}
The easiest I think is to check the error.code, if you want to get more complicated you may choose to parse the full error string to get more details about the error.
In my case, no connection error code is 110 and when the user cancels the log in the error code is 16. Handle the error.

How do I pause my app until a crash report has been submitted?

Background
I'm using UKCrashReporter in my app.
I've installed my own Uncaught
Exception Handler.
I'm setting up the
managedObjectContext of the object
activeItemController in
applicationDidFinishLaunching (1)
The Problem
If the managedObjectContext method throws an exception, the crash reporter dialog box only flashes up before the app crashes and so the user never gets to report the crash.
I want my app to continue only after the crash has been reported, not whilst the window is showing.
What I've tried
If UKCrashReporterCheckForCrash()
were an objective C method, I assume
I could call
performSelectorOnMainThread:waitUntilDone:YES
but it's not.
I've looked at some other Stack
Overflow questions about using
Conditional Locks to pause apps,
but I can't understand how I'd use it
for a C function.
How would I go about doing this in a nice way? Do people have any advice
for me? Any responses would be much
appreciated.
The Code
// In app delegate
-(void)applicationWillFinishLaunching:(NSNotification *)aNotification {
UKCrashReporterCheckForCrash(); // A C function which then creates a window if
// it detects a crash has happened.
}
-(void)applicationDidFinishLaunching:(NSNotification *)aNotification {
[activeItemController setMoContextDisk:[self managedObjectContext]];
[activeItemController setMoContextMemory:[self managedObjectContextMemory]];
}
Update 1
I've been asked for more details on what I'm trying to do, so here goes.
The bug that triggered this thinking was an exception when merging managedObjectModels. My app got caught in a loop printing "Uncaught exception" to the console every few milliseconds.
And when I installed the uncaught exception handler before this exception happened, I'd get the described behaviour - my app would fire up, display the crash report dialog briefly, then continue to load and crash again.
Summary - I want to be able to handle errors that happen on startup.
(1) I'm not using bindings to do this, as I thought bindings would make testing the class more problematic.
I think your problem is with thinking of it as "pausing" your app. Think of it more as a different initial UI state. Your attempts to block the run loop will prevent any interactive window from ... well, being interactive. :-)
Your best bet is to show your main UI (and connect data sources, etc) only if the "am I prompting the user to submit a crash report" method says "no, go ahead and start normally". Otherwise, show your window and, when the user sends or declines to send the report, close the window and ask your app controller to continue the normal startup.
I looked at UKCrashReporterCheckForCrash() and it doesn't appear to create a window of any kind. It merely submits the crash. Could you describe what you're doing with more detail?