I am unable to view analytics debug view after I install the app through TestFlight into my test phone.
I have passed in argument -FIRDebugEnabled, and have tried -FIRAnalyticsDebugEnabled but no luck.
-FIRDebugEnabled
-FIRAnalyticsDebugEnabled
If I directly installed the app into my test phone through Xcode, the debug view will be available. But if it's installed through TestFlight, the debug view cannot be seen.
This can be done by injecting special flags into Firebase's local storages. -FIRDebugEnabled command line argument is being checked by both: FirebaseCore and FirebaseAnalytics frameworks. While the former is saving the flag into shared UserDefaults, the latter is using APMUserDefaults private class, which can be accessed in runtime:
if let APMUserDefaults = NSClassFromString("APMUserDefaults") as AnyObject?,
let userDefaults = APMUserDefaults.perform(#selector(getter: UserDefaults.standard))?.takeUnretainedValue() {
_ = userDefaults.perform(#selector(NSMutableDictionary.setObject(_:forKey:)),
with: true,
with: "/google/measurement/debug_mode")
}
UserDefaults.standard.set(true, forKey: "/google/firebase/debug_mode")
Add following code at the first line of application:didFinishLaunchingWithOptions: method of AppDelegate file
CommandLine.arguments.append(contentsOf: ["-FIRDebugEnabled", "-FIRAnalyticsDebugEnabled"])
Add the following code before FirebaseApp.configure():
var newArguments = ProcessInfo.processInfo.arguments
newArguments.append("-FIRDebugEnabled")
ProcessInfo.processInfo.setValue(newArguments, forKey: "arguments")
Then, go to your target's build settings and update Release's Optimization level to No Optimization [-Onone].
After that, upload to TestFlight. This method works for me!
Related
I am very new to app development. I was trying to configure my GoogleSignInButton Callback function.
I get the error:
No active configuration. Make sure GIDClientID is set in Info.plist.
However, my Info.plist defines GIDClientID along with the value generated as advised here
OS: Version 13.0 Beta
Xcode: Version 14.1 beta 3
In order to resolve this issues, you don't need to add anything into the info.plist. you need to setup GIDSignIn.sharedInstance.configuration = config
https://github.com/WesCSK/SwiftUI-Firebase-Authenticate-Using-Google-Sign-In/blob/starting/README.md#updated-steps-for-v700-of-google-signin
guard let clientID = FirebaseApp.app()?.options.clientID else { return }
// Create Google Sign In configuration object.
let config = GIDConfiguration(clientID: clientID)
GIDSignIn.sharedInstance.configuration = config
....
Google documentation at Firebase Login methods is worse than....
So, if you are using 8.6.0 you can use GIDSignIn.sharedInstance.signIn(withPresenting: presentingVC), but add ClientID in Info.plist like here:
enter image description here
Regarding the main issue, from your picture I see that you put the URLSchema at GIDClientID, they are a little bit different.
Eg. GIDclientID: xxxx-xxxxxx.apps.googleusercontent.com
URLSchema: com.googleusercontent.apps.xxxx-xxxxxx.
Try like that.
I get my clientId using this line of debug in my code
guard let clientID = FirebaseApp.app()?.options.clientID
Same error. I'm newbie too, it helped for me to reinstall packages (GoogleSignIn and FirebaseAuth) with older versions (6.0.0 and 8.6.0) so GIDSignIn.sharedInstance.signIn(with: config, presenting: self) is available. This is a temporary solution till we find working way.
Don't add new property named "GIDClientID" into the Info.plist of target project, use CLIENT_ID which is defined in GoogleService-Info.plist instead.
Find more details here:
https://stackoverflow.com/a/74897652/19683708
This changes in google sign is new. Also GIDSignIn.sharedInstance.signIn(with: config, presenting: self) is not available anymore. GIDSignIn.sharedInstance.signIn(withPresenting: presentingVC) replaced it. But I got same error. Hope to someone find an answer
Some details:
I am not enrolled into Mac Developer program, hence the code is not signed.
I am not sandboxing the app.
It's a status bar only app, no dock or menu will appear.
Here's what I did:
Added a new project for helper app on top my existing main app project.
In main app settings:
Added ServiceManagement.framework framework to my main app.
Set Strip Debug Symbols During Copy to NO
In Build Phases tab, under Copy Files, added Contents/Library/LoginItems as Subpath. And added my Helper App.app
For helper app settings:
Set Application is background only to YES
Under Build Settings, set Skip Install to YES
Hocus Pocus.app is my main app and Hocus Pocus Helper.app is helper app.
In AppDelegate of helper app, my code is:
func applicationDidFinishLaunching(aNotification: NSNotification) {
NSWorkspace.sharedWorkspace().launchApplication("Hocus Pocus.app")
NSApplication.sharedApplication().terminate(self)
}
In AppDelegate of main app:
...
override init() {
self.mainBundle = NSBundle.mainBundle()
let path = mainBundle.bundlePath.stringByAppendingPathComponent(
"Contents/Library/LoginItems/Hocus Pocus Helper.app")
self.helperBundle = NSBundle(path: path)!
super.init()
}
...
...
func makeThisAppStartAtLogin(state: Int) {
let result = SMLoginItemSetEnabled(helperBundle.bundleIdentifier!, Boolean(state))
if result != 0 {
println("success")
}
else {
println("failed")
}
}
It's not working when I call makeThisAppStartAtLogin(1), why?
Apple documentation mentions:
The Boolean enabled state of the helper application. This value is effective only for the currently logged in user. If true, the helper application will be started immediately (and upon subsequent logins) and kept running. If false, the helper application will no longer be kept running.
When I call makeThisAppStartAtLogin(_:), it should start helper app immediately. But it doesn't seem to be doing that.
The if block prints success.
In Helper App code, I also sent the path to launchApplication(_:) instead of app name, it did not make any difference.
I have ran this app from default debug directory and also under /Applications
I have also tried following, it didn't make any difference:
...
let launchDaemon: CFStringRef = "avi.Hocus-Pocus-Helper"
if SMLoginItemSetEnabled(launchDaemon, Boolean(state)) {
...
I have checked that helper app is copied to main app at correct path.
When I launch the helper app manually, either from debug folder or from main app's Contents, it does launches main app and kill itself, as it should.
Here's the full repository, if you are interested. Check loginitems branch.
I have3 Estimote beacons that can be seen with the App store Estimate App.
Now I am trying to run the Apple demo app AirLocation AirLocate
I have changed the UUID in the APLDefaults.m file to the default Estimote UUID _supportedProximityUUIDs = #[[[NSUUID alloc] initWithUUIDString:#"B9407F30-F5F8-466E-AFF9-25556B57FE6D"]];
I have enabled the Region to start startMonitoringForRegion as this stackoverflow says.
But they are not showing up, have you seen this ? Or am I missing some Estimate specific.
Regards
The problem is that AirLocate was written for iOS7, and in iOS8, the permissions model for iBeacons and other location operations has changed. In order to get the program to work on iOS 8 when compiled from XCode 6, you need to add code that requests permission in your AppDelegate. Like this:
if([self.locationManager respondsToSelector:#selector(requestAlwaysAuthorization)]) {
[self.locationManager requestAlwaysAuthorization];
}
This will prompt the user to authorize location operations including beacons. You also need to edit the info.plist for the app, and add a new string key called NSLocationAlwaysUsageDescription with a value like "This app needs access to location services" so the OS can prompt the user for this permission.
After you run your app, you can check in settings to see if this permission has been granted properly.
Another problem I have noticed in iOS 9 is that the calibration sometimes does not work. Seems to be an NSNumber conversion issue. The following edit in APLCalibrationCalculator.m fixed it:-
//measuredPower = [[sample valueForKeyPath:#"#avg.rssi"] integerValue];
measuredPower = [[sample valueForKeyPath:#"#avg.rssi"] intValue];
Im actually trying to convert Apple's sample code to swift.
I created an app and an APPID for it in the devcenter. I checked the entitlement for HealthKit (the ones for IAP & GC are greyed and checked automatically).
When the provisioning profile I create for it is downloaded to Xcode and I go into Preferences in Xcode and look at my account's provisioning profiles I can see the name of the profile plus the expiration date and then there are some icons for entitlements. But the provisioning profile I created with HealthKit doesnt have any icon for it, just the 2 default ones, is this normal:
because for some reason the app crashes upon requesting authorization with this error:
2014-10-02 12:16:13.241 SwimFit[549:8824] -[__NSCFConstantString _allowAuthorizationForSharingWithEntitlements:]: unrecognized selector sent to instance 0x107dc1ce0
2014-10-02 12:16:13.251 SwimFit[549:8824] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFConstantString _allowAuthorizationForSharingWithEntitlements:]: unrecognized selector sent to instance 0x107dc1ce0'
If I try to run it on the device I get this:
I have created:
AppId for my app
Activated that AppID for HealthKit
Created Dev provisioning profile for that AppID
Activated HealthKit Capabilities in General
I see the entitlements.plist is created with com.apple.developer.healthkit = yes
The info.plist does have the healthkit value for required capabilities
The only weird thing I did this time and I used to do differently for other apps is that when I clicked on build/run a some point, I let Xcode create an AppID and I get this from devcenter...i cant upload the image but basically all my previous AppIDs are named after the app. This one because its made by xcode is named: Xcode iOS App ID com santiapps SwimFit but its bundle identifier is correct at: com.santiapps.SwimFit. And so is the dev profile: iOS Team Provisioning Profile: com.santiapps.SwimFit and its the one in my Build Settings. Originally I had SwimFit because that was the name of the app so Xcode created an automatic AppID for it with a ProvProfile for it as well. I then thought maybe I should create the appID and provprofile so I did it manually and tried calling it SwimFit2. Both give the same error.
What else could I be missing?
Here is the code:
//1. Add healthstore property
var healthStore: HKHealthStore? //error if not optionally unwrapped
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
//2. Ask for permissions
if (HKHealthStore.isHealthDataAvailable() == true) {
self.healthStore = HKHealthStore() //needs to be var for it to work?
var writeDataTypes = self.dataTypesToWrite()
var readDataTypes = self.dataTypesToRead()
self.healthStore!.requestAuthorizationToShareTypes(writeDataTypes, readTypes: readDataTypes, completion: { (success: Bool, error: NSError!) -> Void in
if (!success) {
NSLog("You didn't allow HealthKit to access these read/write data types. In your app, try to handle this error gracefully when a user decides not to provide access. The error was: %#. If you're using a simulator, try it on a device.", error)
return
} else {
NSLog("success")
}
// Handle success in your app here.
self.setupHealthStoreForTabBarControllers()
})
}
return true
}
Here is a link with a screen capture: http://youtu.be/BBagkNTpfQA
I had the same crash yesterday. The problem is that you put the wrong data type (NSString) for the data types into the method.
The requestAuthorizationToShareTypes method requires you to pass a set of HKBaseType objects, in my case HKQuantityType objects.
So instead of:
[_healthStore requestAuthorizationToShareTypes:[NSSet setWithObject:HKQuantityTypeIdentifierBodyMassIndex]
readTypes:[NSSet setWithArray:inputDataTypes]
completion:
Use this one:
HKQuantityType* type = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMassIndex];
[_healthStore requestAuthorizationToShareTypes:[NSSet setWithObject:type]
readTypes:[NSSet setWithArray:inputDataTypes]
completion:
I'm trying to authenticate the local player using swift, but every time I get a false value for the .authenticated property. Here is the code I'm using, it is called by the main view controller when the app starts.
func authenticateLocalPlayer(){
var localPlayer = GKLocalPlayer()
localPlayer.authenticateHandler = {(viewController, error) -> Void in
if viewController {
self.presentViewController(viewController, animated: true, completion: nil)
}else{
println((GKLocalPlayer().authenticated))
}
}
}
It brings up the log in view just fine, but when I enter a test account login, it just returns the GKLocalPlayer().authenticatedas false. The bundle identifier in iTunes Connect and the info.plist are exactly the same, as is the version and the app name. Everything is enabled for Game Center on iTunes Connect and in Xcode, but I have a feeling it's not a coding error, it's a setup error in the app record somewhere but I can't for the life of me find where.
After further tinkering, I'm getting this error:
Error Domain=GKErrorDomain Code=15 "The requested operation could not be completed because this application is not recognized by Game Center." UserInfo=0x17006b300 {NSLocalizedDescription=The requested operation could not be completed because this application is not recognized by Game Center.}
I have no idea why this is the case, the bundle ID, name and versions all match...
Any help would be greatly appreciated.
This issue has been resolved by Apple - just call:
GKLocalPlayer.localPlayer()
Previously, the issue was that GKLocalPlayer() does not return the GKLocalPlayer singleton, but instead returns a new GKLocalPlayer instance.
If you were on the Xcode 6 BETA, you could add a C function or Objective-C method that returns the real GKLocalPlayer singleton, then use this in Swift. This is the gist of my workaround (with bad naming conventions):
In an Objective-C header:
GKLocalPlayer *getLocalPlayer(void);
In an Objective-C implementation:
GKLocalPlayer *getLocalPlayer(void) {
return [GKLocalPlayer localPlayer];
}
In your bridging header:
#import "ThatHeader.h"
Then whenever you need to access the GKLocalPlayer singleton in Swift, you can just use getLocalPlayer() instead of GKLocalPlayer(). It's probably a better idea to stick that in an method of a GKLocalPlayer category.
However, this is no longer necessary as detailed above.
Even with Xcode 6 Beta 6, on a device using iOS 8 beta 5, making GKLocalPlayer.localPlayer() available, I was still getting the error:
"NSLocalizedDescription=The requested operation could not be completed
because this application is not recognized by Game Centre"
The solution (discovered through Apple's Dev forum) was to go to "Settings" on the device, and then into "Game Centre" and enable "Sandbox" under the developer section.
You can use that, I create a simple class for iOS game center in GitHub
Easy Class Game Center Swift
https://github.com/DaRkD0G/Easy-Game-Center-Swift