Per-User Defines In Xcode - xcode

My team is currently working a project. We all have to connect to specific session of our software when debugging our work. The original solution to this was to hard code the session ID into our login screens when working, but of course this meant having that stuff checked in and wiped out when doing SVN updates.
I thought setting up a User-Defined setting in Xcode would do the trick, but that turns out to be project wide as well.
Is there a way I could store this data in a per-user way, like in xcuserdata, and have it be easily editable as well? I know something like an environment variable would do the trick, but if there's some way to do this via the Build Settings, that would be great.

Why not simply use a compiler constant which can be unset when you want to test with a real session id?
To define:
To use:
NSString *sessionId;
#if USE_TEST_SESSION_ID
sessionId = TEST_SESSION_ID;
#else // !USE_TEST_SESSION_ID
sessionId = sessionIdTextEdit.stringValue; // or whatever
#endif // USE_TEST_SESSION_ID

Put the session info into a new plist file (mySession.plist) in the project folder. Add that plist file to the .gitignore. Add the plist file to the build and have the app grab it from the bundle.

Related

Setting per-build DefaultValue in Settings.bundle/Root.plist

I have two custom build configs development and release with some values defined. Here is what my Development.xcconfig looks like:
//
// Development .xcconfig
//
// Include Pods config.
#include "Pods/Target Support Files/Pods-MyApp/Pods-MyApp.debug.xcconfig"
// Server URL
HOST_NAME = 127.0.0.1:6060
// Use TLS (https, wss)
USE_TLS = NO
// App Settings
APP_NAME = MyApp (test)
APP_BUNDLE_ID = co.my-domain.myapp-test
I reference these values in Info.plist as $(HOST_NAME) and it works fine. But I also want to expose these custom parameters in application preferences as DefaultValue. I.e. I want the app to use localhost:6060 as default host name preference when the target is development and the address of production host when the target is release.
The preferences are defined in Settings.bundle/Root.plist. Unfortunately xcode does not expand references like $(HOST_NAME) in Settings.bundle/Root.plist. I suppose I have to write a build script to update the values. I know how to use PlistBuddy to update entries in Root.plist. What I can't figure out is how to read values from Info.plist and at what point in the build process I should update Root.plist.
I can't read Info.plist early in the build because the values are not yet expanded. The host name still reads as literal string "$(HOST_NAME)".
I suppose I can read the Info.plist as the last step in the build process and then update "$TARGET_BUILD_DIR/$EXECUTABLE_FOLDER_PATH/Settings.bundle/Root.plist", but which Info.plist to read, the one at
"$TARGET_BUILD_DIR/$INFOPLIST_PATH" or the one at
"$DWARF_DSYM_FOLDER_PATH/$DWARF_DSYM_FILE_NAME/Contents/Info.plist"??? Does it matter? Are they always the same? Are they both always present?
Thanks!

How can fabrics upload data only when they have the user's consent?

We use fabrics and crashlytics on the macOS platform. Swift development language is used.
We added Fabric.with([Crashlytics.self]) to the applicationDidFinishLaunching, but we found that it would upload the user's data by default.
We want to say that we give users a tick option to upload the log data we need when the user agrees, instead of always uploading it by default. Of course, when the user removes the tick option, it stops uploading relevant information.
In other words, how do we start and stop uploading the log information collected by app manually?
You are manually initializing crashlytics with Fabric.with([Crashlytics.self]) in AppDelegate.swift
You can actually have a check in place before the initialization, to it initializes only if the user checks the tick option.
#if user.tick
Fabric.with([Crashlytics.self])
#endif

Custom login/lock screen in OS X Mavericks

I'm trying to override the default login/lock screen in OS X to allow the user to login in other way than providing a password (think fingerprint scanner or how "Knock to unlock" works), and I'm looking for a way to do it for hours now - all I found that looks useful is the Authorization Plugin ADC reference and this example: https://developer.apple.com/library/mac/samplecode/NameAndPassword/Introduction/Intro.html#//apple_ref/doc/uid/DTS10004022
This NameAndPassword xcode project is a little outdated, but I managed to build it simply by specifying the Base SDK (there was a hardcoded wrong path), then I put the resulting .bundle file into /Library/Security/SecurityAgentPlugins directory. Nothing changed after I locked my screen, but I know I need to add the authorization role to /etc/authorization file, which I know no longer exists in Mavericks (there is this auth.db file and the whole auth API), but I'm therefore stuck here - I don't know how to put NameAndPassword inside this database.
Please let me know how do I do it right, or if you know some other way to achieve my goal.
I found a way to edit the database - at first, I tried direct /var/private/db/auth.db sqlite modifications, but it didn't work, so after some time I managed to do this easier than I thought I will:
security authorizationdb read system.login.console > outfile.plist
After this, you need to modify the resulting outfile.plist as it's said in the NullAuthPlugin readme:
<key>mechanisms</key>
<array>
<string>NameAndPassword:invoke</string>
(the last line is the one you need to add to the file).
Then, to save it to the database:
security authorizationdb write system.login.console < outfile.plist
Then the changes should be visible on any login/lock screen of your system, but be careful!
You will not be able to authenticate with current version of NameAndPassword example!
Be sure to estabilish a working SSH connection to your Mac before you modify the database, so you will be able to revert the changes using other device (just repeat the db modification process but this time remove the line you added before).

AppHarbor Web.config transforms not being applied

I am developing an application in ServiceStack and am trying to sort out deployment on AppHarbor, however for some reason my web.config transforms are not being applied.
I had originally a Web.AppHarbor.config file and changed the Environment Setting to "AppHarbor" - once this failed to work after several updates, I gave up and changed the Environment setting to "Release" and copied the desired transformations into the Web.Release.Config file.
App gets deployed OK but config settings do not reflect the values in the transform file (I verify this by login on with twitter and seeing the callback url for Twitter Auth still tries to redirect me to localhost, which is one of the settings I change in my transform file)
I have also tried the transform tester tool and all works as expected.
Manually publishing the web application to a local folder correctly applies the transformations according to the selected configuration
Does anyone have this working? Is there something obvious I'm missing?
Thanks
It sounds like the Web.Release.config file is not included in the build output. You need to set the Build Action attribute to Content to include it in the build output.
You can confirm whether the file is included in the output by downloading the build from the log page.
I stumbled across this post because I was seeing the same lack of action myself. Upon closer inspection (about 15 times that is) of my Web.Release.config I realized one of the nodes in my config file was not marked xdt:Transform="Replace". Unsurprisingly it did nothing when deployed.

Saving CFPropertyLists To Users Folder

I'm trying to save a CFPropertyList to a location in the user's home folder. Using the code below I'm getting errorCode = -10 (unknown error).
CFURLRef fileURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR("~/testfile.txt"), kCFURLPOSIXPathStyle, false );
SInt32 errorCode;
Boolean status = CFURLWriteDataAndPropertiesToResource(fileURL, xmlData, NULL, &errorCode);
If I change the path to something like "/testfile.txt" without the '~' then everything works. How can one save a property list to the current user's home folder? Must one obtain the user's name first and include it in the path such as /users/toffler/testfile.txt?
With Foundation, you can call the NSHomeDirectory function to get the absolute path to the user's home directory. You can then use the path-manipulation methods of NSString or of NSURL, or the equivalent function for CFURL, to tack a sub-path onto that.
However, please don't put files into the top level of my Home folder unless I, as the user, tell you to.
If you want to save a file at the user's request, run a save panel, and then save it where the user told you to.
If you want to save a preferences file, you probably should be using NSUserDefaults or CFPreferences, instead of handling plists yourself.
If you have some other reason to save a user-specific file, it should generally go into either the chewable items folder, the Caches folder, or the Preferences folder. The two functions that I linked to are the easiest ways to access those two of those three folders; the harder way, and the only one that works on all three, is the FSFindFolder function. Unlike most of the Folder Manager, FSFindFolder is not deprecated and is available in 64-bit.
Updates from the year 2012
Nowadays, you should use URLs, not paths. NSFileManager has a method for getting a URL to a desired directory.
Stapling paths (or file URLs) together does not work in a sandboxed application, because you don't have authorization to access the path you just made up. You need to get the path (or URL) from a system API, whether it's NSFileManager, NSSavePanel, or something else.
For saving and restoring file references, use NSURL's security-scoped bookmarks feature.
NSUserDefaults and CFPreferences work as expected in a sandbox.
The Folder Manager is now fully deprecated as of 10.8.
Polluting the user's Home folder is still bad manners.
Automatic ~ expansion is a feature of the shell.
If you are using Cocoa/Foundation, you can use the NSString methods
- (NSString *)stringByAbbreviatingWithTildeInPath;
- (NSString *)stringByExpandingTildeInPath;
otherwise, you'll have to write some code yourself to do this. Getting the user's login name and constructing the path /Users/login-name/ is not the correct way to do this. (While most users will have their home directory here, some will not.)

Resources