This code snippet is from a iPad app the is currently in the app store and is written using ARC. The code has developed using xCode 4.4.1 (4F1003) and runs properly in the IOS Simulator 5.1 (272.21). I recently installed xCode 4.5 and IOS Simulator 6.0 and I now get EXC_BAD_ACCESS (code=2, address=0x200) when the sqlite3_open returns to my objective C code.
sqlite3 *tempDatabase;
const char *sqlStatement = [s_DBEngineDBName UTF8String];
commandReturn = sqlite3_open(sqlStatement, &tempDatabase); // open main db
if(commandReturn == SQLITE_OK) {
// ...
}
I have previously used the following command to open the database but it also fails in the new environment.
commandReturn = sqlite3_open([s_DBEngineDBName cStringUsingEncoding:NSStringEncodingConversionAllowLossy], &tempDatabase); // open main db
As I stated above stepping thru the SQLite code it all works as expected until the final return statement executes. I am confused as to why objc_storeStrong is even involved.
I tracked the issue down to a forward declaration in an include file:
#class sqlite3;
which is obviously wrong as sqlite3 is a struct. This was causing the ARC to try and reference count it which is what was raising the exception.
Removing the line caused compile errors which were easily resolved by prefixing the use of sqlite3 with the key word "struct".
Thanks for your suggestions as they got me to dig deeper and realize that the compiler was considering sqlite3 to be a class when in reality it is not.
Related
Already checked this question: Weak linking UIPopoverBackgroundView
and already read: http://www.marco.org/2010/11/22/supporting-older-versions-of-ios-while-using-new-apis#fnref:1
I have a custom PopoverBackgroundView declared in a .h and implemented in a .m file. Then, in just one file, I instantiate it like this
self.settingsPopover.popoverBackgroundViewClass = [CustomPopoverBackgroundView class];
I´ve tried doing it like marco says in the link above:
if ([UIPopoverBackgroundView class] != nil) {
self.settingsPopover.popoverBackgroundViewClass = [CustomPopoverBackgroundView class];
}
But I get the same launch error when I run in a 4.3 ipad simulator
dyld: Symbol not found: _OBJC_CLASS_$_UIPopoverBackgroundView
My base sdk is IOS 5.1, and my target deployment is 5.1 as well. Im using LLVM compiler 4.0.
Any ideas? Thanks a lot!
Have you tried using respondsToSelector with the relevant UIPopoverController setBackgroundViewClass method? Remember that properties automatically generate setter and getter methods that you can use in addition to the normal property syntax.
The reason why you're still getting linker errors is because you're still trying to call a method on that class, which doesn't exist.
If it's a case that the entire class doesn't exist, Apple recommends using NSClassFromString(#"UIPopoverController") and checking if the returned result is nil.
When I create a new project with Xcode 4.4 and add these lines:
NSDictionary *test = #{ #"key" : #"test value" };
NSString *value = test[#"key"];
NSLog(#"value is: %#", value);
it compiles with no warnings and executes as expected.
Adding the same lines to an existing project produces the compiler error:
NSString *value = test[#"key"]; <-- Expected method to read dictionary element not found on object of type 'NSDictionary *'
I compared both projects' target build settings but nothing leapt out at me.
Update:
The new project that successfully compiled was for OSX. I tried another new one for iOS with the above lines and it fails to compile, same as my pre-existing (iOS) project.
This has nothing to do with old vs. new project, but rather is a factor of the SDK you use. The problem you're running into is that while this is a compiler feature, it requires SDK support. The iOS 5 SDK does not provide that support, though the iOS 6 SDK does.
For that reason, now you should just use the iOS 6 SDK. Read on if you want to use object subscripting with the iOS 5 SDK.
All you need to do is add a header file so that the compiler will try the call. There's no need to add an implementation; it's handled automatically by arclite. (If you are not using ARC, you will have to force the linker to include arclite. But you still don't have to actually switch to it.)
Create a new interface file, NSObject+subscripts.h.
#if __IPHONE_OS_VERSION_MAX_ALLOWED < 60000
#interface NSDictionary(subscripts)
- (id)objectForKeyedSubscript:(id)key;
#end
#interface NSMutableDictionary(subscripts)
- (void)setObject:(id)obj forKeyedSubscript:(id <NSCopying>)key;
#end
#interface NSArray(subscripts)
- (id)objectAtIndexedSubscript:(NSUInteger)idx;
#end
#interface NSMutableArray(subscripts)
- (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)idx;
#end
#endif
I've put this chunk on github.
Note: I used to suggest adding the required methods to NSObject before explaining how to add them only to the relevant objects. In retrospect, I believe this was an error on my part; it led to errors being caught at runtime rather than compile time, unlike the approach now presented here. That approach is still on my blog, but I now believe it to be more of a cool hack than a useful approach.
Source:
Peter Steinberger, Using Subscripting With Xcode 4.4 and iOS 4.3+
I'm attempting to use this approach, described by Marco Arment, for checking if a class exists before using it. With the correct settings, classes are automatically weak-linked when it's appropriate. As Marco describes, "you can safely subclass or have pointers to whatever you want (as long as you’re careful not to instantiate them when they’re not available)".
My app runs fine on iOS 5. I've followed the conditions mentioned at the link:
Base SDK is Latest iOS (iOS 5.1)
Deployment Target is iOS 4.0
Compiler for C/C++/Objective-C is Apple LLVM compiler 3.1 (also tried LLVM GCC 4.2)
Any time I reference NSMetadataQuery I'm making sure the class exists first:
if ([NSMetadataQuery class] != nil) …
Despite all this my app crashes immediately on launch if I try to run it on an iPod touch with iOS 4.2.1:
dyld: Symbol not found: _OBJC_CLASS_$_NSMetadataQuery
I've tried commenting out all the code any my app runs fine. As soon as I add back in a single reference to NSMetadataQuery, it crashes. I've even tried this:
if ([NSMetadataQuery class] != nil) NSLog(#"OK");
Simply including that line, and no other reference to NSMetadataQuery, crashes the app. Even more strange, checking for other iOS 5 classes doesn't cause any problems:
if ([UIDictationPhrase class] != nil) NSLog(#"OK");
That works fine, as expected.
I have been able to work around the problem using the uglier NSClassFromString() to make sure the class exists, but I'd love to know why the other approach isn't working.
I don't have an explanation to this but I ran into the same problem as you. No matter what I/you do, NSMetadataQuery just won't be weak linked...
Refer to this answer, which is really the best one in another question:
https://stackoverflow.com/a/8426591/129202
In short, other auto weak linking seems to work, it's just NSMetadataQuery* that you have to remove from source and replace with id. Instantiate the class with NSClassFromString() etc. No hiccups on other classes like UIDocument however so you can safely use those in the normal sweat free way.
NSMetadataQuery is available in iOS 5.0 and above, so any versions below that has no clue as to what it is. By merely using it in your code, the class name will be added to a symbol table and looked-up when the app launches.
Code:
struct IRenderingEngine {
virtual void Initialize(int width, int height) = 0;
virtual void Render() const = 0;
virtual void UpdateAnimation(float timeStep) = 0;
virtual void OnRotate(DeviceOrientation newOrientation) = 0;
virtual ~IRenderingEngine() {}
};
Learning opengles from a book for 3d iphone programming and it uses this example code but the book is targeted for xcode 3.x
Somehow I feel like its something with xcode 4....
EDIT:
Heres the actual error:
/Users/Dan/Documents/opengles/Hello Arrow/Hello Arrow/IRenderingEngine.hpp:27:2: error: unknown type name 'virtual' [1]
And that legitamtely is all that it takes to fail to compile, absolutely no other files. (Yes I've tried compiling with literally a main.m and this hpp file)
It is recognizing the hpp file as a cpp header file though, if I try to add it to the compiled files it says that "no rule to process file '$(PROJECT_DIR)/Hello Arrow/IRenderingEngine.hpp' of type sourcecode.cpp.h for architecture i386" so I really have no idea what is going on
Note that I compiled with main.m meaning I compiled another Cocoa/Foundation based application
I tried compiling for a c++ application and everything worked out just fine....
Similarly compiling with a main.mm test file worked fine too
heres the actual project, lemme know how insane I really am:
[Removed considering I lost the file]
Please rename the main.m to main.mm. This worked for me.
If you're using Xcode 4, try changing the name of file "AppDelegate.m" to "AppDelegate.mm". It works for me.
Changing the name of file "AppDelegate.m" to "AppDelegate.mm". It's correct!
I moved the #import "IRenderingEngine.hpp" line from the GLView.h file to the GLView.mm - this prevented it from being imported into the main.m and HelloArrowAppDelegate.m files when they were compiled - and restricted the import into the .mm file, that could handle the C++.
I also had to make a couple of other fixes for bugs I'd introduced when typing in the code - so apologies if that wasn't the only thing that needed to be done, but it might help those with similar problems!
if you call C++ files ( even if you only import them ) you need to change the .m file that call's it to .mm
This is just a stupid guess since I've never tried compiling something with the word virtual in a C compiler... but is there any chance that you were trying to compile this C++ code as C code? That's the only reason I can think of that a compiler wouldn't understand the keyword virtual.
The header <stdlib.h> is not the right one to use in a C++ program. When I replaced it with the c++ version of C's stdio library <cstdlib> then your code compiled for me.
I'm working with the ID3 framework in Xcode (which has since disappeared off the face of the web - including google cache!).
I'm testing out an import mp3 feature which allows them to edit the tags as they import them. One of the test cases is a corrupt or invalid mp3 with no proper id3 header. The problem I'm having is that when updating the tags of the invalid mp3 (updateFile:), the ID3 framework attempts to use id3V1Tag.m (I assume it falls back to this if it can't find the v2 tag) and this is where I get the Xcode error (whilst running the program, not building):
Xcode could not locate source file: id3V1Tag.m (line: 299)
Even in a release build this crashes the program, so it's not something I can really ignore.
I've tried putting a try/catch block around it but it's not treated as an exception so doesn't get caught. The function to load the tag data for the file returns a BOOL but it appears this only returns false if the given file doesn't exist, so this doesn't help either.
Current code:
[tagData release];
tagData = [[TagAPI alloc] initWithGenreList:nil];
tagsLoaded = [tagData examineFile:exportPath];
if(tagsLoaded) {
[tagData setTitle:title];
[tagData setArtist:artist];
[tagData setComments:comments];
#try {
[tagData updateFile];
}
#catch (id e){
NSLog(#"h");
}
}
The error you're getting is that Xcode is trying to locate your source file id3V1Tag.m in order to show it during debugging. No code you write will affect this.
If you don't have the id3V1Tag.m source file in your framework distro, there's nothing you can do about this, and there's little to do but ignore it (other than seeing if you can avoid causing it to be requested, like not setting a breakpoint in it, not stepping into it, and not crashing in it).
If you do have it, and are building it, then perhaps you're not building with the right debug information, so you'll have to tell us more about your build setup.
So the problem you're having is that your program is crashing when you attempt to compile id3V1Tag.m or while running the program. I'm a bit confused on that.
If its crashing while running maybe this is an issues with a code file missing from a library? How are you reading the ID3 tag information exactly? Is it through your own code or through a 3rd party library/class.