in Xcode, given a type or a method name, how can I determine the header file(s) to use? For example, if I add either of these lines to my Xcode project
1. AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
2. AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
the compiler says "Unknown type name AVCaptureDevice" or "Use of undeclared identifier 'kSystemSoundID_Vibrate'". (That second one needs #import <AudioToolbox/AudioToolbox.h>.) The header files are not listed in Xcode's documentation files for iOS. Sometimes I get lucky and a code snippet on Stack Overflow will show the header files, but usually the import and include lines are not shown. I always #import <UIKit/UIKit.h>.
How can I find the correct header file(s) to import for a line in Xcode?
There are several approaches, but probably the most fool-proof here would be to lookup AVCaptureDevice in the Xcode docs (Cmd-Shift-0) or at developer.apple.com:
https://developer.apple.com/search/?q=avcapturedevice
This will take you to the main page:
https://developer.apple.com/documentation/avfoundation/avcapturedevice/
And that will show you the correct framework: AVFoundation (observe the path to this file, also visible in the Xcode docs). So you want #import AVFoundation.
From your description, it seems you already found "Audio Toolbox" in the docs. That will pretty reliably be #import AudioToolbox (i.e. just remove the space). I can't think of any cases where existing docs don't match the name of the framework. (There are important cases where the Xcode docs are missing entirely, like CommonCrypto, but I can't think of any where they give the wrong name.)
Note that the vast majority of Apple headers are now modular, so you can and should use the #import syntax with just the name of the framework, rather than the #import syntax with the path to the header.
You could also often option-click (for the docs) or command-click (for this header) AVCaptureDevice in the code. This sometimes requires already importing the correct file, but sometimes it doesn't.
Some things are more obscure, and might not have an obvious documentation page, and Xcode may have trouble finding it if you don't know where to look. In that case, you can search the SDK directly.
Go to the SDK directory you want:
cd $(xcrun --sdk iphoneos --show-sdk-path)/System/Library/Frameworks
You can than search for all references to the symbol you want. This may not immediately give you the correct framework, but it's a quick way to narrow things down:
find . -name '*.h' | xargs grep AVCaptureDevice
Or you might choose to use something like ack or ag to search a bit more nicely.
The Open Quickly command searches all identifiers and filenames in your project and the SDK. You can find Open Quickly in the File menu, but you'll probably want to use a keyboard shortcut, which by default is ⌘⇧O. (That's command shift letter-O, which is different than the command shift zero shortcut for the documentation window that #RobNapier mentions in his answer).
So for example if I start Open Quickly and type ksystemsound, I see this:
This tells me that the symbol is defined in the AudioToolbox framework, so I can import it using either the modern #import directive
// Objective-C
#import AudioToolbox; // <- must end with a semicolon!
or the older #import directive
// Objective-C
#import <AudioToolbox/AudioToolbox.h>
and in Swift I would use the import statement
// Swift
import AudioToolbox
Related
I am working on a project that up to now, despite the mess, it was working ok. Today, believe it or not, I have been updating it to Swift 5.
The project has iOS and tvOS targets as well as frameworks, tests, and top selves extensions. The project also was started using Objective-C and over the years has become 90% Swift.
I am not sure at what point something went wrong but, when compiling, I get the following error for all my top self extensions (mostly all tvOS Targets).
I have found similar questions but I can't understand whats going on.
Any ideas?
You are probably missing an import StoreKit in the Swift files that define IAPHelper. Sometimes this gets imported transitively, and Swift doesn't necessarily need it, but the Swift bridging header does.
Ultimately you need to make sure there's an ObjC #import StoreKit; that is evaluated before this line of code.
First, I have to thank Rob for his tips. I wish he could get the points!
After troubleshooting with the tips provided:
Add StoreKit to your linked frameworks list. -> Didn't work
#import StoreKit; before #import <...-Swift.h> -> Showed error use of #import when modules are disabled
I also saw that "...-Swift.h" was only declared in the Build settings of my "...Topself" targets. Still quite unsure why as I would have thought the whole project still have ObjC dependencies... Still quite new to this challenge.
Furthermore, If I unfold the error I could see that there was some kind of error trying to find "...-Swift.h" file.
At this point, I remembered that I am using cocoapods (I don't like you, you don't like me relationship) and I hated to see the warning "...Overrides Enable modules (C - Objective-C)" so I set it to default for the whole project.
Turns out that that for all "...TopSelf" targets, the default value is NO.
By Overriding Enable modules (C - Objective-C) to YES, clean, and build, everything started working again.
I am making a cydia tweak with a preference bundle using theos in my iPhone
But I'm getting this error!
This is the code I have in:
PSListController
(I have no idea where is the error in my code. The code is too long to paste here. I made a link to my codes)
http://pastebin.com/gQvYvB89
How do I solve this problem?
This isn't an answer but it won't allow me to comment.
A good alternative to IOSOpenDev is Theos, this is more like you are used to as it works the same as on your iphone. You use the make command and have templates.
Installation is fairly involved but here is a good guide.
http://brandontreb.com/beginning-jailbroken-ios-development-getting-the-tools
You should add #import <UIKit/UIKit.h> at the beginning of the header file (this is a common thing: if you encounter a system defined class or protocol - basically every class that starts with NS or UI and some others - you should remove the header generated by class-dump and import the system header, this will save you a lot of headaches).
By the way, you should really NOT compile stuff on device because the GCC that there's on Cydia is very outdated (I think it's from the iOS 3.x days) and using Theos is a pain in the ass anyway: there is another framework that'll help you building preference bundles (and tweaks, siri extensions, toggles for SBSettings, ...), it's called iOSOpenDev and it lets you use Xcode for these projects, which is a MAJOR improvement over compiling on device from the command line (so without code completion, syntax highlighting and all those great improvements Xcode can give you).
PS: if you choose to move to iOSOpenDev feel free to ask for explanations, I have some experience with it ;)
Apple uses the following code in the header of all its framework classes.
#if !defined(__COREFOUNDATION_CFARRAY__)
#define __COREFOUNDATION_CFARRAY__ 1
...
#endif
Is this a recommended approach for eliminating "duplicate symbol" linker errors, when designing classes or categories for framework use, or are these left over protection from the use of #include instead of #import in c?
Research into this has lead me to this article on include guard
NOTE: this question is not asking how to fix a duplicate symbol error, but instead asking if there is any way of preventing your own code from causing the problem if its included more than once in a project.
You're right about the include guard - there's probably some compatibility reason it's not been removed from the source.
However, this won't really protect you against duplicate symbols much.
For example,
What if you have two third party library, each of which uses the SBJSON library (I had this happen to a colleague a few weeks ago).
Each of the libraries was compiled seperately so, from their point of view, SBJSON was only included once. However, when I came to link my app I couldn't because I had duplicate symbols.
I had to solve this by manually removing the symbols from one of the .a library files (This link shows it's quite a common problem!)
EDIT : This link is a much clearer step by step solution to the problem
Apple uses the following code in the header of all its framework classes.
Not necessarily for the ObjC APIs. But CoreFoundation, yes they use include guards. It's still idiomatic in many camps to use traditional #includes in C sources, and to use #import for objc sources (#import is a compiler extension, not traditional C).
Is this a recommended approach for eliminating "duplicate symbol" linker errors
No, it does not prevent linker errors; it can result in duplicate declaration errors during compile phases.
If you're getting duplicate symbol linker errors, the problem is something else, such as visibility of definition. For that, you should provide an example of your troubling program.
I don't want to submit this app to AppStore. I've tried for many times but met so many problems :(
I use class-dump to get all the header files of UIKit.framework. In the UIApplication.h generated by class-dump, I saw the method I want to use----launchApplicationWithIdentifier.
Then I put UIApplication.h in my project and import it. Compile, I got a lot of "Redefinition of enumerator...." error because in the UIKit.framework I use previous, there's another UIApplication.h. But this file doesn't have the method launchApplicationWithIdentifier.
If I delete the previous UIKit.framework and import the folder generated by class-dump. Then it appears like a framework but if I unfold it, it's empty.
Then I want to make all generated header files a framework file ant replace the previous UIKit.framework. But I don't know how. As we can see, under the system framework directory, there's a file which has the same name as the framework and has a 'executed shell script' icon. How can I made this file?
I really got confused. Someone can give me a hand? Thank you.
Just specify the private methods in a category interface above the class implementation where you want to use it, like this:
#interface UIApplication (Private)
- (BOOL)launchApplicationWithIdentifier:(id)identifier suspended:(BOOL)suspended;
#end
Don't import the whole class-dump file and link with the original UIKit framework.
You must be very careful when using private API. These methods can change or be removed in future iOS versions!
Check if the method really exists with respondsToSelector: at runtime and be prepared for the case that it does not exist.
I used a secret MapKit feature in my own application and I knew that the private methods only exist in iOS 5. So my app still works in all iOS versions but this feature is only available in iOS 5 (Apple removed or changed it in iOS 6 beta 1).
I am following a tutorial out of a book and in the .h file of where some of my code is, I have to type in: #import . Where is this file located? Is it part of some framework or do I have to download it somewhere? I've googled this and found a question about math.h on MacRumors, so I know that it has something to do with iOS programming and probably isn't specific to the book.
It's part of the SDK that you have already installed if you are doing iOS development. All you need to do is put the line
#import <math.h>
in your code. You don't need to download anything. You don't need to link against anything (the math library, libm, is part of libSystem on both iOS and OS X, and is linked by default).
Note that this has nothing to do with "iOS programming". <math.h> is part of the C standard library, not specific to any platform.
Have you tried this? Did you encounter a problem?
Well, it depends. In the tutorial you're following, if it imports that header like so:
#import "math.h"
That means it is in the user header search path. In other words, it's not a system library, but something the author created. If that is the case, you'll have to find it online, or maybe in the back of the book you're reading.
If the library instead appears like this:
#import <accelerate/math.h>
Then it's a system library(note the '< >' instead of quotes), in the accelerate framework (just an example, I don't know if there is a math.h in accelerate or not). The first part of the path of the import indicates the framework you'll find the header in.
If you change your question to include the full #import statement in the book, I can more accurately help you.