no Objective-C description available - Why? - objective-c

I really have no idea why on this particular project my debugger is extremely 'disabled'.
For example I'll want to get info on an object:
(lldb) po [_model dictionaryValue]
[no Objective-C description available]
I'm wondering why this is. It's making debugging extremely difficult and it's only on this current project. I'm guessing I've done something to the settings at some point. It's on almost any po someObject I try to inspect. The variables in scope can be seen in the pane to the left of the debug console however.
I'm on Xcode 5, I have Cocoapods in my project, and it's a Unit Testing Target.
Any insights or any way to fix this?
Update:
For clarity, part of how the test case is implemented:
#interface WWCGateModelTests : XCTestCase
{
WWCGate *_model;
}
#end
#implementation WWCGateModelTests
- (void)setUp
{
[super setUp];
// Put setup code here; it will be run once, before each test case.
_model = [WWCGate loadGateModelWithIdentifier: kGateName]; // defined, not nil
}
- (void)tearDown
{
[super tearDown];
NSError *error = nil;
[_model saveModelOrError:&error];
// Breakpoint here. po _model does not print the model.
// This has been possible with other projects... po error will print
// nil to the console. How is an ivar not in scope?
}

This is likely happening because Unit Testing Targets typically are set up to run with "Release" configurations. "Release" configurations are ones where the debugging symbols have been stripped or optimized away.
I suspect you won't have this problem if you make certain you're running with a non-optimized, symbols-in-place Debug version of your app. You can change that in Xcode's scheme editor (e.g. when doing "Test" or "Profile", use the "Debug" configuration).

Are you sure you aren't using it on primitive types? Use p intVariable on those.
Every object will respond to description by at least printing class and memory address.

I've tracked down the issue (but haven't fixed it fully yet). It has to do with the Mantle Framework. In its description method it wants to spit out the contents of an NSDictionary that it generates at that point. There's something wrong with the way I set up my model I believe so creating this dictionary (based probably on how I configured some property) is basically failing.
I overrode the description method to return a standard description:
- (NSString*)description
{
return [NSString stringWithFormat:#"<%#: %p>", self.class, self];
}
and everything is fine and good again on planet Earth. ;-)
Thanks to those who were particularly patient. A more detailed discussion about this issue can be found at UPDATE 3 of the following post: http://horseshoe7.wordpress.com/2013/05/26/hands-on-with-the-mantle-model-framework/

Related

Cannot inspect Self in method while debugging

I have a method on one of my ViewController's that is called by one of its view's and delivered some value. It then sends out a message to a manager object with some information about the VC's state.
- (void)elementXChangedWithValue:(float)value {
ParameterManager * pMan = [ParameterManager sharedInstance];
[pMan updateParameter:self.elementX.parameter value:value];
}
In debugging, it was important for me to inspect what the .SomeElement.parameter state was so I could know what was getting lost in translation by the time I get to my ParameterManager.
Unfortunately, although Self is definitely non-nil and accessible the debugger shows scant information about the class making quick and practical glancing of the value difficult. (i will sometimes invoke "po" command in the debugger command line, however).
Not sure if it helps but this project is running heavy with the Objective-C/Swift interoperability although the ViewController is a fully Objective-C class.
Here is an image of what I am getting in the debugger. The drop-down arrow shows nothing but empty.
The debugger isn't perfect and sometimes you just cant see what is in certain areas, such as self. What does always work is NSLog's placed in code though, so if all else fails, add one of those in at the right place to print out the object you wish to know about.
The debugger may show more info after you make it execute these commands:
expr #import UIKit;
expr #import Foundation;
This loads the whole UIKit and Foundation symbols in the debugger at runtime, you only need to execute it once per debug session.
You can automate this with a user-defined breakpoint that'll be triggered every time your application starts in the debugger.
Source : http://furbo.org/2015/05/11/an-import-ant-change-in-xcode/

Objective-C: Do non-imported classes get compiled and linked into final binary?

In Objective-C, do all source files in the project get compiled and linked into the final binary even if they are not imported by any classes?
That depends on your target settings. If you go to the target's Build Phases, anything listed under Compile Sources will be compiled.
If the source file is part of the build then its classes end up in the binary and available at runtime. That's because the runtime is reflective and can be queried later to find them. The compiler cannot be certain that won't happen.
EDIT: a classic use case is an informal protocol. You may write code like:
- (void)initWithObject:(id)object
{
self = [super init];
if(self)
{
_title = [object title];
_value = [object value];
}
return self;
}
Then you might decide you want to add an implementation of that informal protocol to e.g. NSString:
#interface NSString (MYPropertyProtocol)
#end
#implementation NSString (MYPropertyProtocol)
- (NSString *)title
{
return #"Content";
}
- (NSString *)value
{
return self;
}
#end
Just because nobody imports the NSString category doesn't mean the methods aren't used.
Going beyond that, in my current app we have a protocol like (this is a heavily cut-down version):
#protocol MYTableViewCell
+ (NSArray *)acceptedObjectClasses;
- (void)setObject:(id)object;
#end
Subsequently UITableView subclasses can opt to implement MYTableViewCell. If so they are found automatically by traversing objc_getClassList (and a lot of caching) and used automatically by my table view data source if it wants to display any object type declared as supported by acceptedObjectClasses. So that's taken most of the hassle out of writing the table view data source — I've got just one, which can accept any combination of objects used anywhere in the app, yet it's very short and easy mentally to check for errors, and need never grow even as the app learns about more things that need to be displayed in tables.
Nobody ever explicitly imports those table view cells, because it'd just mean having to do the same work twice — declare the class in Objective-C, which the compiler will check for me, then go and redeclare it to the custom cut-down lookup system that I've implemented instead of just using Objective-C's, which I probably need to do manual verification on.
Click on a .m file in the Project Navigator on the left side of Xcode, then open the right-hand tile (with the right-hand "View" button in the toolbar) and look at the "Target Membership" section. There is a checkbox with your project name beside it. If the box is checked, that .m file is included in the build. If the checkbox is not checked then the .m is essentially ignored.
You can also check this by clicking on your project name at the top of the ProjectNavigator column, selecting the project under "TARGETS", selecting "Build Phases", and selecting "Compile Sources". All of the included .m files will be shown and you can add or delete files from the list using the + - buttons at the bottom of the list.

Unable to see Code Coverage in Xcode 4.2

I'm creating an iPhone 5.0 project in Xcode 4.2 and would like to find the code coverage when the unit tests are executed. I'm quite new to the Xcode environment, and I've followed the steps provided here. I'm able to modify the Build Settings for the test target correctly, and link the "libprofile_rt.dylib" file fine.
At this point, when I execute the tests (using Command-U), the code compiles and the tests pass. I do not encounter the problem described here. In addition, I've installed CoverStory.
The author in the first link mentions "Just run your unit tests and view the code coverage data as usual"; however, I cannot find .../Objects-normal/i386.
Just to get things working, I created a new project with the following class:
#import "SomeClass.h"
#implementation SomeClass
#synthesize someValue;
-(void)performWork:(BOOL)now withValue:(int)value {
if (now) {
someValue = value;
}
else {
someValue = value - 1;
}
}
#end
and test class:
#import "CodeCoverageTests.h"
#import "SomeClass.h"
#implementation CodeCoverageTests
- (void)testExample {
SomeClass *obj = [[SomeClass alloc] init];
[obj performWork:YES withValue:3];
STAssertEquals(obj.someValue, 3, #"Value was not 3");
}
#end
Ideally, I'd like to be notified in some way that when the tests execute, the else clause in the performWork method is never fired.
I thus have the following questions:
Is the root problem that there's no support for what I'm trying to do with the new compiler?
Is the only solution the one described by user chown in response to the question I linked above?
Will I be able to use CoverStory (or something similar) if I follow the solution from 2) ?
Update:
After some struggle, I was finally able to find the location of the "SomeClass.gcno" and "SomeClass.gcda" files (thanks #bjhomer - see this link), and they depicted beautifully that the if part of the conditional statement in performWork was covered (and the else was not). To make sure, I modified the test as follows:
- (void)testExample
{
SomeClass *obj = [[SomeClass alloc] init];
[obj performWork:NO withValue:3];
STAssertEquals(obj.someValue, 2, #"Value was not 2");
}
After re-building and re-execution of the unit test, I reloaded the .gcno and .gcda files. CoverStory showed that the coverage changed to the else part of the performWork method. There was one small caveat however:
I needed to modify the build settings of the <TargetName> (not the <TargetNameTest> as shown here) in order for the "SomeClass.gcno" and "SomeClass.gcda" files to be created in ...<TargetName>.build/Objects-normal/i386/ directory.
Thanks again for your help!
It sounds like your main problem is that you cannot find the Build/Intermediates/<SchemeName>.build/<ConfigurationName>-<PlatformName>/<TargetName>.build/Objects-normal/<ArchitectureName> directory. That directory is always used when building, whether or not you're doing code coverage. That's where all the intermediate files generated by the compiler are stored, and is also where the final .gcno and .gcda files should exist if you're doing code coverage. If you cannot find that directory, the problem is not related to coverage, the problem is that you need to find that directory.
To answer your questions.
Code coverage is supported in the LLVM Compiler, as of Xcode 4.2. It will not work with LLVM-GCC, so make sure you're not using that.
No, it is not necessary to hack in support for GCC 4.2 in Xcode 4.2. I'm running code coverage with Xcode 4.2 right now, having done none of the above.
You should be able to use CoverStory either way; hacking in support for GCC 4.2 would not change where the built products go.

error in ASIHttpRequest

Now I'm involved in a project which needs to download a huge amount of images from server. Following the recommendation online, I tried the ASIHttpRequest. But when I copied all the necessary classes into my project, I got 30+ errors in those classes. Most of the errors are about using retain, release or autorelease. Because I'm using Xcode 4.2.1, explicit retain, release and autorelease is forbidden. But some other errors are quite ridiculous.
for example, in class ASIDataCompressor.m, following method should return NSData
- (NSData *)compressBytes:(Bytef *)bytes length:(NSUInteger)length error:(NSError **)err shouldFinish:(BOOL)shouldFinish
but I see one portion of the method return NO
if (status == Z_STREAM_END) {
break;
} else if (status != Z_OK) {
if (err) {
*err = [[self class] deflateErrorWithCode:status];
}
return NO;
}
Some other classes also have similar problems.
My questions are:
Did I download the wrong package?
How to let compiler ignore those explicit retain, release and autorelease?
"Xcode 4.2.1, explicit retain, release and autorelease is forbidden" because you have ARC enabled when you created your project. Disable ARC.
ASIDataCompressor.m method looks fine here. Don't know how you got it wrong.
Since you just picked up ASIHTTP in your project I would recommend switching to AFNetworking because read this: [request release]
As stated above, when using ARC, you cannot use (and no longer need) retain/release/etc.
If you want your overall project to still have ARC, you can disable it for that one file.
When you migrate a project to use ARC, the -fobjc-arc compiler flag is set as the default for all Objective-C source files. You can disable ARC for a specific class using the -fno-objc-arc compiler flag for that class.
In Xcode, go to target Build Phases tab > open the Compile Sources group to reveal the source file list > double-click the file for which you want to set the flag > enter -fno-objc-arc in the pop-up panel, then click Done.

Weird EXC_BAD_ACCESS in a trivial PDFKit program

I have written this trivial action method associated to a textfield.
Every time I enter text into a textfield a search in a PDF is performed and PDFView automatically scroll to selection:
- (IBAction) search:(id)id
{
NSString *query = [self.searchView stringValue]; // get from textfield
selection = [document findString: query fromSelection:NULL withOptions:NSCaseInsensitiveSearch];
if (selection != nil)
{
[self.pdfView setCurrentSelection:selection];
[self.pdfView scrollSelectionToVisible:self.searchView];
}
}
Problem is that after 3 or 4 searches I get EXC_BAD_ACCESS on row (i).
If I debug I see that query contains an NSCFString and not an NSString.
I think it is a memory management problem..but where?
I replicated the same issue inside a trivial testcase:
#interface PDFRef_protoTests : SenTestCase {
#private
PDFDocument *document;
}
........
- (void)setUp
{
[super setUp];
document = [[PDFDocument alloc] initWithURL: #"a local url ..."];
}
- (void)test_exc_bad_access_in_pdfdocument
{
for (int i =0 ;i<100; i++)
{
NSString *temp;
if (i % 2 == 0) temp = #"home";
else if (i % 3 ==0) temp = #"cocoa";
else temp=#"apple";
PDFSelection *selection = [document findString: temp
fromSelection:nil
withOptions:NSCaseInsensitiveSearch];
NSLog(#"Find=%#, iteration=%d", selection, i);
}
}
Update:
1) It seems that it happens also if I use asynchronous search (method beginFindString: withOptions) every time I perform second search.
2) I found a similar problem to mine in MacRuby Issue Tracking: http://www.macruby.org/trac/ticket/1029
3) It seems that if I disable temporarily garbage collection it works but memory goes up.
I wrote something like:
[[NSGarbageCollector defaultCollector] disable];
[[NSGarbageCollector defaultCollector] enable];
surrounding search code
Another Update
Very weird thing is that sometimes all works. Than I clean and Rebuild and problem arises again. From a certain point of view is is not 100% reproducible. I suspect a bug in PDFKit or some compiler setting I have to do
Update Again
Dears it seems very crazy. I'd concentrate on testcase which is very trivial and which replicates easily the problem. What's wrong with it? This testcase works only if I disable (by code or by project setting) GC
Another Update
Boys it seems a bug but I downloaded an example called PDFLinker from Apple website (http://developer.apple.com/library/mac/#samplecode/PDFKitLinker2/Introduction/Intro.html#//apple_ref/doc/uid/DTS10003594). This example implements a PDFViewer. Code of my app and this example are quite similars. For the same search action on same PDF, my memory rises at 300/400 MB while PDFLinker rises at 190MB. Clearly there is something wrong in my code. But I am comparing it bit by bit and I don't think I am inserting memory leaks (and Instrument doesn't give me any evidence). Maybe is there some project-wide setting ?
Update Yet
Changing from 64 bit to 32 bit memory consumption lowered. Surely there is a problem with 64bit and PDFKit. BTW still EXC_BAD_ACCESS on second search
SOLUTION
Crucial point is that PDFKit with Garbage collection is bugged.
If I disable GC all works correctly.
I had another issue that had complicated my analysis: I disabled GC on Project Setting but GC remained enabled on Target Settings. So Apple's example PDFLinked2 worked while mine not.
I agree you have found a bug in PDFKit.
I got various forms of errors (segmentation fault, selector not understood, etc) running your test case. Wrapping the code in #try/#catch doesn't prevent all errors associated with this method.
I also got errors printing the log message.
To work around the bug(s), I suggest you disable GC during your invocation of -findString:fromSelection:, as you've already discovered.
Also, be sure to make copies of the values of interest from selection before re-enabling GC. Don't just copy selection either.
If you conduct searches from multiple places in your code I also suggest you extract a separate method to perform the search. Then you can invoke that one to conduct the searches for you without duplicating the GC disable/enable nesting.
This sort of thing is usually evidence that you're hanging onto a pointer to an object that has been destroyed. Turn on zombie objects (with NSZombieEnabled) to see exactly where and when you're accessing a bad object.
Judging from your screen shot it doesn't seem like you have NSZombie turned on. Probably the reason why it doesn't help you. Here's how you turn it on:
How to enable NSZombie in Xcode?
The screenshot you provided was otherwise very useful, but you really need NSZombie to figure out this kind of errors. Well, unless it's obvious, which it isn't from the code you posted.
EDIT: I read the comment that you're using garbage collection. I'm an iOS developer, so I have very limited experience with garbage collection in Objective-C, but as far as I understand NSZombie doesn't work in a garbage collected environment.
I'm not sure it should be possible to get EXC_BAD_ACCESS in a garbage collected environment, unless you create your own pointer and try to call methods on it without having created an object and I don't see why you would do that.
I've heard that some frameworks doesn't work well with garbage collection, but I wouldn't think PDFKit was among them. Anyway, the solution might be to not use garbage collection. Perhaps you should file a bug report with Apple.
keep PDFSelection *selection as a member variable and pass it in fromSelection: instead of nil.
It is possible that PDFDocument keeps the returned PDFSelection instance to improve the performance.
Did you try retaining the searchview stringvalue object before using it?
As you say it happens when you type fast and it happens for async calls, it is possible that the object stringValue is pointing to is being released between the time your query object is pointing to it, and the time you use it int the search.
You could try something like this to see if the problem persists:
- (IBAction) search:(id)id
{
NSString *query = [[self.searchView stringValue] retain]; // get from textfield
selection = [document findString: query fromSelection:NULL withOptions:NSCaseInsensitiveSearch];
if (selection != nil)
{
[self.pdfView setCurrentSelection:selection];
[self.pdfView scrollSelectionToVisible:self.searchView];
}
[query release];
}
Of course there is also the possibility that document is relased. How do you declare it? is it a property with retain? Can it be released by the time you are searching?
EDIT:
I see that you posted the code with the second parameter as NULL, but in your screenshot, this value is nil.
The documentation says you should use NULL when you want to start the search from the beginning.
http://developer.apple.com/library/mac/#documentation/GraphicsImaging/Reference/QuartzFramework/Classes/PDFDocument_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40003873-RH2-DontLinkElementID_1
And as the compiler interprets nil and NULL differently, this could be leading to some weird behavior internally.