Cannot resolve enum values by name in Xcode debugger - ios

With an enum typedef'd in a global header file used throughout my project, I am unable to refer to the individual enum values by name while using lldb in Xcode.
For example, if I am stopped at a breakpoint anywhere the enum type is available, and I try to evaluate something at the lldb prompt in Xcode (e.g. (lldb) p (int)EnumConstant), lldb complains:
error: use of undeclared identifier 'EnumConstant'
Furthermore, if I try to set a conditional breakpoint using an enum constant in the condition (e.g. right-click breakpoint in Xcode > Edit Breakpoint... > Condition: EnumConstant == someLocalVar), then Xcode complains every time it tries to evaluate that condition at that breakpoint:
Stopped due to an error evaluating condition of breakpoint 1.1: "EnumConstant == someLocalVar"
Couldn't parse conditional expression:
error: use of undeclared identifier 'EnumConstant'
Xcode's code completion popover even resolves a suggestion for the enum constant when I begin typing the name in the "Edit Breakpoint..." window, so Xcode itself doesn't have a problem resolving it.
Is there an option I can set in lldb or Xcode so that lldb maintains the enum identifiers after compilation? I'm assuming the enum constants get translated to their ordinal value during compilation, causing the executable to discard the identifiers, but thats just my naive speculation.
When I use the equivalent code in a simple GNU C program in Linux or Cygwin (minus the class definitions obviously), but using gcc/gdb instead of Xcode/lldb, I don't have these problems. It is able to resolve the enum values no problem.
I've created a tiny Xcode iPhone project to demonstrate what I mean. Using any of the enum_t constants below within the ViewController.m context (the for-loop is a good place to demo) will produce the same results.
ViewController.h:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
typedef enum
{
eZero, eOne, eTwo, eCOUNT
}
enum_t;
extern NSString const * const ENUM_STR[];
#end
ViewController.m:
#import "ViewController.h"
#implementation ViewController
NSString const * const ENUM_STR[eCOUNT] = { #"eZero", #"eOne", #"eTwo" };
- (void)viewDidLoad
{
[super viewDidLoad];
for (enum_t value = eZero; value < eCOUNT; ++value)
{
NSLog(#"%-8# = %d", ENUM_STR[value], value);
}
}
#end

This is a bug (fairly longstanding) in how the name->Debug Information lookup-accelerator tables for enums are built. While enum types are listed, enum values are not. That was surely done to save output debug info size - debug information gets quite big pretty quickly, and so there's a constant tension between the cost of adding more info and the utility of that more info. So far this one hasn't risen to the level of inclusion.
Anyway, doing a search through "all debug information for anything with a name that matches 'eZero'" is prohibitively slow even for decent sized projects, and gets really bad for large ones. So lldb always uses these name->Debug Info tables for its first level access.
Because the accelerator tables do contain the enum type by name (and more important for you typedefs by name as well), the workaround is to do:
(lldb) expr enum_t::eZero
(int) $0 = 0
Of course, if you have truly anonymous enums, then you are pretty much out of luck till this info gets added to the accelerator tables.
BTW, the Xcode symbol completion in the Debugger Console window is done using the Xcode SourceKit indexer, not lldb. So the completions offered from Xcode are not a reflection of lldb's knowledge of the program.
BBTW, gdb doesn't use compiler-made accelerator tables (these were an Apple extension up till the new DWARF 5 standard) but manually builds an index by scanning the debug info. That allows them to index whatever seems best to the debugger. OTOH, it makes debugger startup quite a bit slower for big projects.

Related

In Objective-C, does the binding of method really happen at "run-time"?

I heard that Objective-C is influenced by the "message passing mechanism" of SmallTalk.
Objective-C, like Smalltalk, can use dynamic typing: an object can be
sent a message that is not specified in its interface. This can allow
for increased flexibility, as it allows an object to "capture" a
message and send the message to a different object that can respond to
the message appropriately, or likewise send the message on to another
object.
And I felt for codes like [anObject someMethod], the binding of someMethod to the machine code may happen at run-time..
Therefore, I write a demo like this:
#import <Foundation/Foundation.h>
#interface Person : NSObject {
#private char *name;
}
#property (readwrite, assign) char *name;
- (void)sayHello;
#end
#implementation Person
#synthesize name;
- (void)sayHello {
printf("Hello, my name is %s!\n", [self name]);
}
#end
int main() {
Person *brad = [Person new];
brad.name = "Brad Cox";
[brad sayHello];
[brad sayHelloTest];
}
I tried [brad sayHelloTest] to send brad a message sayHelloTest which brad doesn't know how to handle with.. I expect the error will NOT happen at compile-time..
However, the compiler still throws an error:
main.m:24:11: error: instance method '-sayHelloTest' not found (return type defaults to 'id') [-Werror,-Wobjc-method-access]
[brad sayHelloTest];
^~~~~~~~~~~~
main.m:3:12: note: receiver is instance of class declared here
#interface Person : NSObject {
^
Change [(id)brad sayHelloTest] to [(id)brad sayHelloTest]; doesn't work either.. (The compiling command is clang -Wall -Werror -g -v main.m -lobjc -framework Foundation -o main)
In Objective-C, does the binding of method really happen at "run-time"? If so, why will there be a compiler error like this?
If the binding doesn't happen at "run-time", why was "Objective-C" called "dynamic typing language"?
Does anyone have any ideas about this?
One job of a compiler is to catch as many errors at compile time as possible. If it can tell that the call will fail at runtime, you generally want it to complain.
You can suppress this via casting to show that runtime resolution is happening:
[(id)brad sayHelloTest];
Because the IDE can infer the obvious error from the context.
When you write if (a = 1),you will get a warning. A good IDE should help you find mistakes as early as possible.
I figured out the reason finally..
It throw errors during compiling because -Werror flag is included, which will turn warning into error..
http://clang.llvm.org/docs/UsersManual.html#cmdoption-Werror
After I delete -Werror flag, everything works as expected and the error only happens at run-time.
It has become a compiler error only within the last five years for there to be no known declaration of a method. It has to do with Automatic Reference Counting. Under ARC, the compiler is now responsible for the reference-counting-based memory management that Cocoa uses.
Given that responsibilty, it must be able to see the declarations of methods for any messages before they are sent, so that it knows what retains and releases are appropriate.
The method resolution (the lookup of the method on the class) does still happen at runtime, and -- particularly if you disable ARC -- you can still take advantage of message forwarding.
One way around ARC's requirement was given by Marcelo Cantos -- cast the receiver to id. Another is to use performSelector:. A third -- though I can't recommend it -- is to use objc_msgSend() directly.
Note that the "binding" of the method does, and always did, happen at compile time. Methods are associated with classes, when the classes are defined. Messages are distinct from methods, and it is they that resolve at runtime to a method.

Getting "Expected a type" error in XCode

I'm getting this error:
/Class/GData/OAuth/GDataOAuthViewControllerTouch.m:116:22: Expected a type
That line is:
authentication:(GDataOAuthAuthentication *)auth
Inside of this block of code:
- (id)initWithScope:(NSString *)scope
language:(NSString *)language
requestTokenURL:(NSURL *)requestURL
authorizeTokenURL:(NSURL *)authorizeURL
accessTokenURL:(NSURL *)accessURL
authentication:(GDataOAuthAuthentication *)auth
appServiceName:(NSString *)keychainAppServiceName
delegate:(id)delegate
finishedSelector:(SEL)finishedSelector {
NSString *nibName = [[self class] authNibName];
I'm a newb XCode developer. So far I've created and compiled a calculator app based from an online class but that's it.
Is this a library that is not being included?
Background: The previous developer abandoned the project and the owner sent the project code to me. I'm trying to replace the existing graphics with new graphics and recompile it with support for iOS 6, which I thought I should be able to do without any coding, but have run into this error and many others when I opened the project. I have the latest XCode.
The :22 (and the position of the caret within the editor) tell you exactly where on the line the error is. In this case it's telling you that where it sees GDataOAuthAuthentication it was expecting a type. So, implicitly, it doesn't recognise that GDataOAuthAuthentication is a type.
Objective-C still sits upon compilation units ala C — each .m file is compiled in isolation then the lot are linked together. You use #import (or #include if you want; #import just guarantees the same file won't be included twice) to give each individual file visible sight of any external definitions it needs.
So, that's a long-winded way of reaching the same conclusion as Rick did five minutes ago: you've probably omitted a necessary #import.
A few things to look for:
Did you #import the file where the GDataOAuthAuthentication type is defined? (e.g. #import "GDataOAuthAuthentication.h")
Is there a variable named GDataOAuthAuthentication which is causing the compiler to think GDataOAuthAuthentication is a variable not a type?

swift failed with exit code 1 while compiling in Xcode - possibly related to Bridging-Headers

I have an Obj-C Project I'm trying to migrate to Swift. I did succeed with various classes but recently ran into an issue I can't seem to make sense of. When I try to compile my current code base I get the following (SUPER UNHELPFUL ERROR MESSAGE)
Command /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc failed with exit code 1
My only assumption is its somehow related to my bridging-headers but Xcode isn't giving me enough information to figure out if this is actually true.
I'm using Cocoapods to add the CorePlot to my project. I'm trying to migrate the following class to Swift:
Obj-C Class (ScatterPlotContainer.h)
#import <Foundation/Foundation.h>
#class CPTScatterPlot;
#interface ScatterPlotContainer : NSObject
#property (nonatomic, strong) CPTScatterPlot *ahrsAlt;
#property (nonatomic, strong) CPTScatterPlot *calibration;
#property (nonatomic, strong) CPTScatterPlot *coreAlt;
#property (nonatomic, strong) CPTScatterPlot *pitch;
#property (nonatomic, strong) CPTScatterPlot *roll;
#property (nonatomic, strong) CPTScatterPlot *slip;
#end
Obj-c Class (ScatterPlotContainer.m)
#import <CorePlot/CPTScatterPlot.h>
#import "ScatterPlotContainer.h"
#implementation ScatterPlotContainer {
}
#end
Swift Conversion
import Foundation
class ScatterPlotContainer : NSObject {
public var ahrsAlt : CPTScatterPlot;
public var calibration : CPTScatterPlot;
public var coreAlt : CPTScatterPlot;
public var pitch : CPTScatterPlot;
public var roll : CPTScatterPlot;
public var slip : CPTScatterPlot;
}
My bridging headers file
#import <CorePlot/CPTScatterPlot.h>
What I've tried thus far
When I comment out the #import <CorePlot/CPTScatterPlot.h> from the Bridging headers file - I get an error in swift because it doesn't know what CPTScatterPlot is
I've also tried #import <CPTScatterPlot.h> which didn't work either.
Thoughts
So the only thing I can think of is perhaps because I'm using a cocoa pod there is some sort of module name I need to add. The error message really isn't that useful. Does anybody have a suggestion about some blaring error I've made or how to get a more descriptive error message to figure out what is going on?
I did the same all answer says but mine issue was not resolved. I did figured out that issue was related to broken function call.
A function syntax was not wrong but its calling mechanism was wrong.
To check the exact error for this issue check following:
Select issue navigator > Click on error will show logs for error > In that select All Messages tab.
This will show all detail logs for this error.
Scroll down and You got logs like, in my case
So, by reading this I figure out that something wrong with function calling. I browse my code and resolved it, Below was correct and wrong code.
Wrong Way:
var region = MKCoordinateRegionMake(self.mapView.userLocation.coordinate, span)
// It will not shown error here but when you build project compiler shows error.
Right Way:
let region = MKCoordinateRegion(center: self.mapView.userLocation.coordinate, span: span)
I run into this last night and nothing above was solving my problem.
I was about to do something very bad at my laptop when I saw, all by pure luck, that ONE (1) file was is text encoding set to UTF-16 ?!?! WTF??
This was the last file I was working on, and probably, one bad cut/paste "import" a strange character into the arena. I did a cut/paste of my code in this file to a bare bone text editor. I deleted the file, recreate it and paste back my code... and voilà! it work.
So do the above, but also check your file encoding! :-)
I had the same error message.
What helped, was to set the optimization level in the swift compiler settings to None.
This is not really a solution for me and I think that's one of the many bugs in the swift compiler.
Another solution for this issues is to check that you don't have 2 or more files with the same file names. It solved the problem for me.
Thank you #Kampai for the advice on going through the error log message. I read through, and some files were missing:
<unknown>:0: error: no such file or directory:
Somehow, some files were removed during a pull from GitHub. The files are in the directory, but not in the Xcode project.
Right click on a folder and click 'Add files to ...' to manually add missing files to Xcode. That fixed the problem for me.
This happened to me several times already, but now I know how to fix it \o/
I was getting the same error for including this code in a didSet block:
didSet {
// Test whether this view is currently visible to the user.
if super.isViewLoaded() && (super.view.window != nil) {
// (build fails even if this block is empty)
}
}
It took a lot of trial/error to hunt this down. Removing super. allowed the build to proceed.
had a horrible time with this bug for over 3 hours by meticulously going from file to file and reverting the changes and seeing if that file had the issue in it. I tried the first answer but didn't give me any answers. Found the issue and it was because I had a non computed property named the same as a computed property of a subclass. I really hope the debugger becomes more robust with handling these sorts of cases in future updates :(
Simply deleting derived data and cleaning helped me
1) Identify the file there the problem is. You can copy and paste the compilation instruction to the console and the last screen will contain the error description. Note the pid number there the problem was identified. Then scroll up and find the pid and related instruction - there will be one file per pid, so you will find the file you have problem it.
2) Look through the file and check all you last changes. If you have git initialized you can use
git diff <file name>
As for #Kampal, I'm still struggling to figure out how much to specify in a function call. For instance, creating a UIColor object sometimes requires that UIColor be specified, and sometimes doesn't.
These both work:
playButton.backgroundColor = .darkGrayColor()
playButton.setTitleColor(UIColor.whiteColor(), forState: UIControlState.Normal)
This yields the exit code 1 error on compilation, without any debugger warning. #time-sucking debug vortex
playButton.setTitleColor(.whiteColor(), forState: UIControlState.Normal)
So I have a new rule: when using a function that takes more than one parameter, be explicit.
Now back to playing swift: AVOID THE VORTEX
Since everyone else has been showing theirs, I'll show mine:
class Foo : UIView {
var pathPosition:Double = 0.0 { didSet {
pathPosition = min(max(0.0, pathPosition), 1.0) // crashes if this line is present
self.pathPosition = min(max(0.0, pathPosition), 1.0) // but not here
}}
}
Incredibly, this does not come up in Playground, but does fail when placed in code in a framework. Although it is legal syntax (used to work, still works in playground), the Swift compiler seems to want pathPosition to be qualified with self.. Note that is (relatively) old code and used to compile, maybe something broke in 6.1.
Edit:
I feel like I am going insane, but it feels like there is a greater complexity problem going on here, where surrounding code can impact this problem. I saw things compile last night, changed some code and settings again today, and it failed on me again. Today, I had to hack in a bunch of really stupid code to get it to work:
var pathPosition:Double = 0.0 { didSet {
// bug: insane!! - have to clobber the value before resetting!
let bugOldValue = pathPosition
self.pathPosition = 1.0 // fails without this nonsensical line!
self.pathPosition = min(max(0.0, bugOldValue), 1.0)
}}
For what it's worth, the actual error message I got, per the helpful instructions above, was:
PHI node has multiple entries for the same basic block with different incoming values!
%14 = phi double [ 1.000000e+00, %10 ], [ %11, %10 ], [ 1.000000e+00, %9 ], [ 0.000000e+00, %9 ], !dbg !4818
label %10
double 1.000000e+00
%11 = phi double [ %7, %entry ], !dbg !4815
LLVM ERROR: Broken function found, compilation aborted!
I'm scared for tomorrow.
I just had this same error, the problem was that I had overridden a method with a non-optional parameter and had made the parameter optional in the override. (the method parameter below)
func logNetworkCallDurationForMethod(method:String, path:String, milliseconds: UInt) {
}
override func logNetworkCallDurationForMethod(method:String?, path:String, milliseconds: UInt) {
}
Ran into this issue today actually. Was the result of a recent pull from git on a project where a file had been deleted, but it didn't update in my local project.
Clicking on the error brought up the location of the "missing" file, went and deleted it's reference in the Project Navigator. Fixed the error, did a clean, and compiled successfully.
This happened to me when trying to reference a method from an inmutable protocol argument(by mistake, I thought the member was a property):
Having an interface as follows:
public protocol NSValidatedUserInterfaceItem {
func tag() -> Int
}
Compilation crash
func validateUserInterfaceItem(anItem: NSValidatedUserInterfaceItem) -> Bool {
print(anItem.tag) // oopsie, tag is a function
return false
}
Compilation success
func validateUserInterfaceItem(anItem: NSValidatedUserInterfaceItem) -> Bool {
print(anItem.tag()) // this is cool for swift
return false
}
This happened to me and after reading the log in issue navigator I found out that I have two swift files with same name. This was creating the issue and I was getting build failed.
I got this error due to a missing file in my project. Added this file again and voila everything worked.
In my case it was wrong method overriding. Base class:
open func send(_ onSuccess: #escaping ((SomeType) -> Void)) -> SomeType { }
Subclass:
open override func send(_ onSuccess: ((SomeType) -> Void)) -> SomeType { }
As you see #escaping is missing. Swift3 converter in XCode8 doesn't consider inheritance relations, moreover, that type mistakes aren't marked as errors.
In My Case it was Simulator bug just uninstall app from simulator and clean project then run project.
I had accidentally dragged symlinks (aliases) to source files into the project instead of the actual files.
I had CoreData generated files twice (and added myself). Check the files are not duplicate.
Unfortunately this error is often caused by a glitch inside Swift's compiler. It is not always easy to find the reason. If cleaning doesn't work, my suggestion is to try to comment the last code you wrote (even the whole file if necessary). Usually commenting the last code you entered would restore the compilation and you'll get more meaningful errors. From there on you have to try to uncomment the code piece by piece until you get to the instruction which caused this error. The Swift compiler is still pretty young and from time to time it reports weird errors. These kind of errors are completely useless, because instead of helping the developers they only confuse them even more. I would suggest Apple to change the compiler to give more detailed information and avoid this annoying error from appearing anymore.
NSString const *kGreenColor = #"#00C34E";
I had above line in my Constant.h file. which was meant for preprocessors only.
Removing that line worked for me.
moving the Bridge file to project level resolve my problem.
In my case I had renamed a file. After committing I found that the file name still hasn't changed in the Xcode project (not sure why), the file was greyed out. Changing the name and committing again did the trick.
So we have to keep an eye out for this error, when making changes to files using source control.
In my case deleted a couple of files directly from SourceTree but their reference was still there in Xcode. Logs show their names. Removed them and error went away.

Error adding enum type to Swift Array

I'm trying to add an enum type to an Array and am getting an error. I am able to add a String and other types, but this enum is failing. Does anyone know what might be going wrong here?
enum Domain {
case Default
}
let domains: Array<Domain> = [.Default]
Thread 1:EXC_BAD_INSTRUCTION(code=EXC_i386_INVOP, subcode=0x0)
This is definitely an Apple bug - log it! https://bugreport.apple.com
Add a second case to your Enumeration (e.g. case Other) and see that the error no longer occurs. Something crazy is going on in Swift when an Enumeration has only one case.
It looks like, at least in my playing with a playground, if the enum definition contains the word 'Domain' at all anywhere in the name the enum fails to compile/work.
I think it's just a compiler bug on Apple's part... If I have the following code, and only this code, everything runs fine:
var points = TestEnum[]()
points += TestEnum.TestValue
enum TestEnum {
case TestValue
case SecondTestValue
}
However, I have code above that code (a simple RPN implementation, but it doesn't matter). The RPN code runs fine by itself. But with the TestEnum code in there, the RPN code crashes. The crash is an EXC_BAD_ACCESS and crashes on a random line and different address based on what lines of code are in the program (I'm guessing because the offsets in the executable change). For instance, I added a println after the points += call, and it crashed at a different part of my RPN code.
Both the RPN code and the TestEnum code run fine by themselves. This is almost definitely an Apple bug.

How to implement the ADLivelyTableView class in a project that uses ARC

I have gone through the ADLivelyTableView demo project but have not been able to import the ADLivelyTableView h and m files into my project successfully. It appears that the main issue is to do with ARC. I have experimented by converting the demo project into arc, specifically but converting just the LDMasterView.m file, and this simply removes all references to releasing objects, and so after this conversion, the use ARC option under build settings is now ON and the app works. So i figured that the ADLivelyTableView .m and .h files dont need converting, but when these are imported into my project, i get all sorts of ARC errors for these two blocks of code:
if (block != _transformBlock) {
Block_release(_transformBlock);
_transformBlock = Block_copy(block);
}
}
and
#implementation ADLivelyTableView
- (void)dealloc {
Block_release(_transformBlock);
[super dealloc];
}
I dont get why these errors didnt show when turning on ARC in the demo project. id prefer finding a solution rather than trying to import my entire application to the demo project instead! The errors are as follows:
ARC Casting Rules: Cast of block pointer type 'ADLivelyTransform (aka NSTimeINterval (^)CALayer*_strong, float) to C pointer type 'const void *' required a bridged cast.
ARC Casting Rules: Cast of C Pointer ....(Same as above)
Also, once this issue is resolved, it is supposed to be as simple as just importing the ADLivelyTableView .h and .m files and then adding the line :
ADLivelyTableView * livelyTableView = (ADLivelyTableView *)self.tableView;
livelyTableView.initialCellTransformBlock = ADLivelyTransformFan;
into my viewDidLoad section? or is that bit supposed to be edited for my specific table?
Thanks for your help,
Regards,
Rami
You can modify the Compiler Flags for ADLivelyTableView.m.
Kindly try to add -fno-objc-arc.

Resources