I'm relatively new to iOS development, and am trying to implement CocoaLumberjack logging.
I downloaded the latest source from https://github.com/robbiehanson/CocoaLumberjack, have included the required files in my project, made the necessary code changes, and am getting the run-time linker error that follows below.
The environment is Xcode 4.2 Build 4C199, with the project Target set to Device=iPad and DeploymentTarget=4.3. The project was initially written using retain/release, so I left the original source as-is, adding the compiler flag "-fobjc-arc" for the Lumberjack files I'm using: DDFileLogger.m, DDLog.m and DDTTYLogger.m.
The console output is:
GNU gdb 6.3.50-20050815 (Apple version gdb-1708) (Fri Sep 16 06:56:50 UTC 2011)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "--host=i386-apple-darwin --target=arm-apple-darwin".tty /dev/ttys001
sharedlibrary apply-load-rules all
target remote-mobile /tmp/.XcodeGDBRemote-10996-56
Switching to remote-macosx protocol
mem 0x1000 0x3fffffff cache
mem 0x40000000 0xffffffff none
mem 0x00000000 0x0fff none
[Switching to process 11779 thread 0x2e03]
[Switching to process 11779 thread 0x2e03]
dyld: lazy symbol binding failed: Symbol not found: _objc_storeStrong
Referenced from: /var/mobile/Applications/32E4EEB9-765E-4C72-83C8-F5707253AA99/Demo.app/Demo
Expected in: /usr/lib/libobjc.A.dylib
dyld: Symbol not found: _objc_storeStrong
Referenced from: /var/mobile/Applications/32E4EEB9-765E-4C72-83C8-F5707253AA99/Demo.app/Demo
Expected in: /usr/lib/libobjc.A.dylib
warning: Attempting to create USE_BLOCK_IN_FRAME variable with block that isn't in the frame.
(gdb)
My project initializes the environment as follows, where fileLogger is an instance variable defined in the corresponding AppDelegate.h file:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
/*
* Configure the Lumberjack logging framework (we'll use it instead of NSLog)
*/
// the TTY logger is the Xcode console
[DDLog addLogger:[DDTTYLogger sharedInstance]];
// we'll also use a file logger
fileLogger = [[DDFileLogger alloc] init];
fileLogger.rollingFrequency = 60 * 60 * 24; // 24 hour rolling
fileLogger.logFileManager.maximumNumberOfLogFiles = 7;
[DDLog addLogger:fileLogger];
// Override point for customization after application launch.
DDLogInfo(#"didFinishLaunchingWithOptions: entered");
// create instance of the view controller
MainViewController *aViewController = [[MainViewController alloc]
initWithNibName:#"MainView" bundle:nil];
self.mainViewController = aViewController; // same as: [self setMainViewController:aViewController];
[aViewController release];
// Add the main view controller's view to the window and display.
self.window.rootViewController = self.mainViewController;
[self.window makeKeyAndVisible];
return YES;
}
Has anyone encountered this problem, and know of a solution or workaround? Is what I'm doing even possible... having mixed ARC and non-ARC files in a project?
For future reference, this seems to be a shortcoming of the current Xcode toolchain that seems to forget to include the ARC library when the currently built target has the ARC support turned off (and uses ARC-enabled static libraries). You can easily force the linker to include the library using the -fobjc-arc flag, see this related question for a complete description.
I just heard back from one of the CocoaLumberjack developers, this is what he said:
There seems to be a bug in (maybe) the LLVM compiler. Here's what I've
discovered:
If you have an Xcode project without ARC turned on by default, and you
have a file that uses ARC (via -fobjc-arc), and that file attempts to
alloc/init stuff within '+ (void)initialize', then it will blow up at
runtime.
It seems to work, however, if you convert the project to ARC...
EDIT: Additional information from the developer:
The 1.2.3 tag can be used without ARC.
You can grab an archive from here:
https://github.com/robbiehanson/CocoaLumberjack/tags
Related
I've got a great programming font Deccy that only looks good with font smoothing (anti aliasing) disabled in Xcode. With Xcode 8 the following would do the trick:
defaults write com.apple.dt.Xcode NSFontDefaultScreenFontSubstitutionEnabled -bool YES
defaults write com.apple.dt.Xcode AppleAntiAliasingThreshold 24
But this no longer works with Xcode 9.
Would it be possible to disable font smoothing in Xcode 9?
Mischief managed?
Here's a screenshot of my Xcode 9 with Deccy at 13pt:
I believe the above is what you want. Here's stock Xcode displaying the same file:
But how?
I probed deep for a noninvasive way to accomplish this, and failed. As far as I can tell, the text rendering path in Xcode 9 very deliberately turns on font smoothing.
Before going any further, please file a feature request with Apple. It only takes a few minutes, and it's your best hope for an answer that that can be discussed in front of those with sound security instincts and strained cardiovasculature:
https://bugreport.apple.com/
I wrote an Xcode plugin. You might have heard that Xcode 9 uses code signing restrictions to forbid the loading of plugins. This is true, but a few mavericks press on, and tonight we ride with them.
Step one
There is a tool, update_xcode_plugins. You can use it to strip the code signature from your copy of Xcode, and with it the bundle-loading restriction:
$ gem install update_xcode_plugins
$ update_xcode_plugins --unsign
If you change your mind, you can do this to revert to (a backup copy, I think?) of signed Xcode:
$ update_xcode_plugins --restore
Step two
There is another tool, Alcatraz. It's a plugin manager for Xcode. I chose to install it because it provides a plugin which provides a project template for plugins. I followed these instructions to install Alcatraz, which boil down to this:
$ git clone https://github.com/alcatraz/Alcatraz.git
$ cd Alcatraz
$ xcodebuild
I launched Xcode, clicked through the dialog warning me about the new plugin, and then used the newly-added Window > Package Manager to install the "Xcode Plugin" template.
Step three
I made a project with this template.
As I write this, the "Xcode Plugin" template hasn't been updated to support Xcode 9. No worries. I ran this command to grab Xcode 9's compatibility UUID:
$ defaults read /Applications/Xcode.app/Contents/Info DVTPlugInCompatibilityUUID
I visited my new project's Info.plist and added that UUID to the DVTPlugInCompatibilityUUIDs array.
Then, I linked SourceEditor.framework into my project. That was a two-step process:
Visit the target's Build Settings. Add this to Framework Search Paths:
/Applications/Xcode.app/Contents/SharedFrameworks/
Visit the target's Build Phases. Add a new "Link Binary With Libraries" phase. Hit the plus. Navigate to the directory above (you can just press the / key and then paste the path in) and choose SourceEditor.framework. It should appear in the list. The project should still build.
Then, I made my plugin's .mm file look like this (I deleted the .h file, it's unneeded for this PoC):
#import <AppKit/AppKit.h>
#include <dlfcn.h>
extern void CGContextSetAllowsFontAntialiasing(CGContextRef, BOOL);
static void hooked_sourceEditorSetFontSmoothingStyle(CGContextRef ctx) {
CGContextSetAllowsFontAntialiasing(ctx, NO);
}
#interface NoAA : NSObject
#end
#implementation NoAA
+ (void)pluginDidLoad:(NSBundle *)plugin
{
NSArray *allowedLoaders = [plugin objectForInfoDictionaryKey:#"me.delisa.XcodePluginBase.AllowedLoaders"];
if (![allowedLoaders containsObject:[[NSBundle mainBundle] bundleIdentifier]])
return;
Class cls = NSClassFromString(#"SourceEditorScrollView");
NSBundle* bundle = [NSBundle bundleForClass:cls];
void *handle = dlopen(bundle.executablePath.fileSystemRepresentation, RTLD_NOW);
if (!handle)
return;
uint8_t* set_font_smoothing_fn = dlsym(handle, "sourceEditorSetFontSmoothingStyle");
if (!set_font_smoothing_fn)
goto fin;
void* set_font_smoothing_fn_page = (void*)((long)set_font_smoothing_fn & -PAGE_SIZE);
if (mprotect(set_font_smoothing_fn_page, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC))
goto fin;
set_font_smoothing_fn[0] = 0xe9; // jmp
uint32_t* jmp_arg = (uint32_t*)(set_font_smoothing_fn + 1);
*jmp_arg = (uint32_t)((long)hooked_sourceEditorSetFontSmoothingStyle - (long)(jmp_arg + 1));
mprotect(set_font_smoothing_fn_page, PAGE_SIZE, PROT_READ | PROT_EXEC);
fin:
dlclose(handle);
}
#end
…I think the gotos add character. Basically, it just defines a function that takes a CGContextRef and turns off text antialiasing for it. Then, it overwrites the beginning of a function inside the SourceEditor framework which ordinarily configures antialiasing settings — don't need that anymore — to jump to our function instead. It does all of this in an incredibly unsafe way, so if something goes wrong, Xcode may politely crash.
Build and run the project, which automatically installs the plugin. Accept the addition of your plugin, and that's that.
What now?
If anything here doesn't work because I messed up, let me know. I'm not planning to roll this into an Alcatraz plugin myself, but you or anyone else should free to do so with credit (after filing a feature request with Apple).
Happy hacking!
If you 'live' in XCode and need a crisp rendering of this TrueType font, then editing XCode application defaults with PrefEdit.app, or defaults write com.apple.dt.Xcode.* has no effect.
Thinking outside the box you might be interested in the following to achieve crispyness all-over your Mac.
Since the Deccy font is best viewed at 12pt, it makes sense to raise the AppleAntiAliasingThreshold in the global domain to 13, the default for this setting is 4.
You can also suggest no AppleFontSmoothing.
defaults write -g AppleFontSmoothing -int 0
defaults write -g AppleAntiAliasingThreshold -int 13
In addition to these tweaks a bit more can be achieved in the Accessibility Preference pane in System Preferences: The Display has 2 checkmarks that you should try: 'Differentiate without color', and 'Increase contrast'.
"Beauty is in the eye of the beholder", I hope this helps.
Here are alternative steps that might work for you.
Try to find the com.apple.dt.Xcode.plist file under Macintosh HD/Library/Preferences.
Copy the file to desktop
Open file and add NSFontDefaultScreenFontSubstitutionEnabled to (Boolean)YES
add AppleAntiAliasingThreshold to (Number)24
Replace this file with preference file
Restart the system and Xcode
Note: For safer side keep backup of the original file.
I am using Hockeyapp for crash reporting and collecting logs when the app crashes. Using the method below.
- (void)setupLumberjack {
// Configure CocoaLumberjack
[DDLog addLogger:[DDASLLogger sharedInstance]];
[DDLog addLogger:[DDTTYLogger sharedInstance]];
// Initialize File Logger
// initialize before HockeySDK, so the delegate can access the file logger!
_fileLogger = [[DDFileLogger alloc] init];
_fileLogger.maximumFileSize = (1024 * 128); // 128 KByte
_fileLogger.logFileManager.maximumNumberOfLogFiles = 5;
[_fileLogger rollLogFileWithCompletionBlock:nil];
[DDLog addLogger:_fileLogger];
}
Setting the log level:
static const int ddLogLevel = LOG_LEVEL_ALL;
Now I would like to get ALL log levels still sent to Hockeyapp reports, but surpress ANY output in the xcode console.
How can I achieve that? Probably missing something here.
Using version 1.9.2 but willing to update to 2.x if that would be necessary.
Xcode logs are always displayed in the Xcode console.
You don't have any way to disable them.
But you can hide the output window :P
You also can set a Custom Compiler Flags for your Debug build settings.
Then you code a DLog() macro that will echo NSLog() only if this flag is there => only when debugging with Xcode.
With this the users won't have any log on their device.
The answer I was looking for was posted in a comment.
Simply removing this line did the trick:
[DDLog addLogger:[DDTTYLogger sharedInstance]];
I just started porting an Android app to iOS, and am hitting a major roadblock that I can't figure out despite scouring many similar questions.
I am attempting to follow the pattern implemented in the CastVideos sample where the GoogleCast API is encapsulated in a singleton class which I've called CastManager. To use my singleton class, I #import "CastManager.h" in AppDelegate.m. Then in CastManager.h, I #import <GoogleCast/GoogleCast.h> so that I can use classes and protocols from it as part of CastManager's public interface. However, because I'm importing CastManager.h in both CastManager.m and AppDelegate.m, the linker is finding duplicate symbols from the GoogleCast framework.
This is my CastManager.h:
#import <GoogleCast/GoogleCast.h>
#import <Foundation/Foundation.h>
#interface CastManager : NSObject
#property(nonatomic, strong) GCKDeviceScanner *deviceScanner;
+ (instancetype)sharedCastManager;
#end
And corresponding CastManager.m:
#import "CastManager.h"
#implementation CastManager
+ (instancetype)sharedCastManager {
NSLog(#"sharedCastManager");
static CastManager *singleton = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
singleton = [[self alloc] init];
});
return singleton;
}
- (instancetype)init {
NSLog(#"init()");
if (self = [super init]) {
self.deviceScanner = [[GCKDeviceScanner alloc] init];
}
return self;
}
#end
And this is the main part of my AppDelegate.m:
#import "AppDelegate.h"
#import "CastManager.h"
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
CastManager *castManager = [CastManager sharedCastManager];
return YES;
}
However, this results in the following error from the linker when attempting to build the project:
duplicate symbol _kGCKDeviceCapabilityVideoOut in:
/Users/nate/Library/Developer/Xcode/DerivedData/MyCastApp-ezrgxdnlvywpanerezulnarzknno/Build/Intermediates/MyCastApp.build/Debug-iphonesimulator/MyCastApp.build/Objects-normal/x86_64/AppDelegate.o
/Users/nate/Library/Developer/Xcode/DerivedData/MyCastApp-ezrgxdnlvywpanerezulnarzknno/Build/Intermediates/MyCastApp.build/Debug-iphonesimulator/MyCastApp.build/Objects-normal/x86_64/CastManager.o
... many similar errors ommitted for brevity ...
duplicate symbol _kGCKDeviceCapabilityAudioIn in:
/Users/nate/Library/Developer/Xcode/DerivedData/MyCastApp-ezrgxdnlvywpanerezulnarzknno/Build/Intermediates/MyCastApp.build/Debug-iphonesimulator/MyCastApp.build/Objects-normal/x86_64/AppDelegate.o
/Users/nate/Projects/MyCastApp/GoogleCast.framework/GoogleCast(GCKDevice.o)
ld: 8 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
As far as I can tell, this exactly copies the pattern as defined in the CastVideos sample, but the sample compiles fine, and mine doesn't, and I've scoured through both projects trying to find what is different, but I just don't see it. Further, I don't see anything really wrong with doing this, and would expect it to work fine. I can't think of any other way to do it, really.
Here are the relevant files from the CastVideos sample for comparison:
ChromecastDeviceController.h
ChromecastDeviceController.m
AppDelegate.m
Other questions point to solutions that don't apply or don't fix it:
I'm not importing a .m file on accident.
I don't have duplicate references to any files in the project.
The "Compile Sources" section of the "Build Phases" project setting doesn't include any duplicates.
I've added the '-ObjC' linker flag as described by the GoogleCast API docs, though it has the same error with or without it.
I've tried deleting the delegate data and doing a clean before building.
This is with Xcode 6.3.1 running on OS X Yosemite 10.10.3 and the GoogleCastSDK-2.6.0 package from the SDK documentation page
I have checked in my sample project with the problem at https://github.com/nshafer/MyCastApp
Any help is greatly appreciated!
Edit: the duplicate is somewhat related, it's definitely about the same symbols, but the answers there didn't help, as I'm not using Object-C++, but rather just Objective-C. I don't have a .mm file, just a .m file.
For me it helped to switch the "No Common Blocks" compiler setting to NO:
It pretty much seems to make sense, the setting is explained here: What is GCC_NO_COMMON_BLOCKS used for?
The linker tells you that you have a variable named kGCKDeviceCapabilityVideoOut in two files, AppDelegate.m and CastManager.m. Since it's not in your source code, it's most likely in the GoogleCast code that you are including.
Either change the GoogleCast.h file, or make sure it is only included in one .m file. Including it from CastManager.h means it is indirectly included in every file that includes CastManager.h, so I would avoid that and only include it from CastManager.m. You'll probably have to add
#class GCKDeviceScanner;
in your CastManager.h file.
I found another fix, which is to edit GCKDevice.h in the GoogleCast.framework/Headers folder. Change the 4 constants from GCK_EXPORT to GCK_EXTERN near the top of the file.
/** Device capability flag for video out. */
GCK_EXTERN const NSInteger kGCKDeviceCapabilityVideoOut;
/** Device capability flag for video in. */
GCK_EXTERN const NSInteger kGCKDeviceCapabilityVideoIn;
/** Device capability flag for audio out. */
GCK_EXTERN const NSInteger kGCKDeviceCapabilityAudioOut;
/** Device capability flag for audio in. */
GCK_EXTERN const NSInteger kGCKDeviceCapabilityAudioIn;
I detailed this in a bug report I filed with Google's issue tracker, but it was marked as a duplicate of another somewhat related issue. Either way, it will perhaps get fixed in the next version. Until then, I would suggest going with changing the "No Common Blocks" setting as detailed in Joobik'com's answer, as that doesn't involve changing the 3rd party code.
I've been wrestling with an issue in iOS causing improper allocation, getting less memory back from malloc than I should have for a CPP object. I recently discovered it was due to two translation units including the same header, one of which along its include chain had a few occurrences of #pragma pack.
Now, I'm not sure how to properly trace back to whichever file is using it and ensure that it fixes it. I've added a bunch of #pragma pack(show) and have nailed down the offending file from the top (the offending file being the file that causes others files to have the same pack setting of 1). I've opened that file in Xcode and run preprocess on it.
In most cases, it looks like code is setting pack back to default (8 on arm64). Are there any tools that can help verify which is the offender along the chain?
The only tip that I have (a case of a pack 1, which is what the pack was being set to), is a header from the iOS SDK. But even it looks to be ok.
# 54 "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.1.sdk/usr/include/sys/kauth.h" 2 3 4
#pragma pack(1)
typedef struct {
u_int8_t sid_kind;
u_int8_t sid_authcount;
u_int8_t sid_authority[6];
u_int32_t sid_authorities[16];
} ntsid_t;
#pragma pack()
As I mentioned, when searching through the preprocessed source file, I wasn't able to find any instance of #pragma pack that wasn't undoing its setting shortly after. However, I wasn't aware that there was another way to set packing, via #pragma options align=(packed|reset). It turns out that it wasn't being undone, but I was looking for #pragma pack.
I'm seeing a strange behavior with Xcode 6 debugger.
I have created a singleton shared instance using the following code:
+ (instancetype)shared
{
static DataBaseManager *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[DataBaseManager alloc] init];
});
return sharedInstance;
}
Right after the object is initialized by calling the method like this:
DataBaseManager *manager = [DataBaseManager shared];
NSLog(#"");
I have placed a breakpoint on the "NSLog", and i'm seeing the following debugger status:
I have made sure I'm launching on debug mode, and that the build settings are fine, following the question here: Xcode debugger doesn't print objects and shows nil, when they aren't
Any ideas on why this is happening?
This is the first time i have ever seen this kind of strange behavior.
Any help would be much appreciated.
**UPDATE**
A bug was reported to apple bug report system.
The bug status is: Duplicate of 17164538 (Closed)
so it is probably a known bug in Xcode.
You shouldn't be in Release mode while you are debugging your code.
If you want to see variable values you have to be in Debug mode. The steps are
Click on your project name on the top left corner near start/stop buttons
Go in Edit scheme
Go in Run settings
Go in Info tab and then Build Configuration
Set it to Debug
If it was on "Release" that's the matter you saw all nil.
If still not working then try following in the project Build Settings
Set Strip debug symbols during copy to NO
Optimization Level to None -O0
Try setting Deployment Postprocessing to NO inside your Build Settings and check.
Make sure you have Link-Time Optimization set to No for debug mode in Build Settings.