I just pulled the latest doxygen from github, compiled it on my Mac, and ran it on a mix of Objective-C and C++ in .mm files. For some of the the C++ classes, the output HTML makes the methods look like Objective-C. For example, code like:
void Thing::foo(int x)
Is shown in the HTML like:
- (void) foo (int) x
Any way to fix this?
Update
It appears that a forward declared Objective-C class causes a problem. For example, something like this, in a .h file:
#class NSMutableString;
...
class Thing {
public:
int foo(double x);
}
Causes it to render the Thing methods like Objective C. I cut that one line #class NSMutableString and it renders correctly like C++ functions.
C++ classes in .mm files are rendering like Objective-C all the time.
Related
I created a Swift enum as an Int (so it will work with Objective-c).
When I build the project, everything is fine. However, as soon as I try to import the class in a .h file (using a forward declaration #ClassName), the generated header file errors out with Redefinition of 'ClassName' as a different kind of symbol
Looking in the generated .h file I can see it generated the new type like so:
typedef SWIFT_ENUM(NSInteger, ClassName, closed) {
type1 = 1,
type2 = 2,
};
It underlines the ClassName saying it's been re-declared. However, it exists nowhere else in the header file (doing a search and it comes up only once) and it's only declared once in a swift file.
Any suggestions on what is going on?
Enums are not classes in Objective-C, so you need to use typedef instead of forward declaration in your .h file:
typedef NS_ENUM(NSInteger, ClassName);
and then in .m file, you need to import Module-Swift.h file.
I've just found out that Swift's private access modifier is file level, as stipulated in the docs under "Access Levels":
Private access in Swift differs from private access in most other languages, as it’s scoped to the enclosing source file rather than to the enclosing declaration. This means that a type can access any private entities that are defined in the same source file as itself, but an extension cannot access that type’s private members if it’s defined in a separate source file.
So this means the following code will compile when the types are in the same file:
class FirstType {
private var privateProperty: String = ""
}
class SecondType {
private let firstType = FirstType()
func messWithFirstType() {
firstType.privateProperty = "👻" // this compiles and works!
}
}
As far as I can see, this breaks encapsulation completely. On the other hand, it might be nice to have some related types grouped together in the same file for readability, especially if the related types are tiny, like enums.
Private extensions are an exception because they are extending the same type the file is meant to contain. And private extensions do bring some nice things.
Are there any other reason, apart from facilitating private extensions, for the file scope private access modifier to be in Swift?
It isn't clear to me why private was originally implemented with regard to files, but rest assured that the Swift folks know this is not the only possible meaning of private and that it isn't ideal for some purposes, and are working to change it. There's already a proposal on the table, accepted for Swift 3, that will turn the current private into fileprivate and add a new level of private that will be scoped to the type rather than the file. You can expect to see this become part of Swift 3 in the very near future.
When you wonder about anything that seems "weird" in Swift, most of the time the answer is "because of Objective-C".
For some perspective, I consider 3 access level common to many modern programming languages:
private: only accessible to the class in which it is defined.
protected: only accessible to the class in which it is defined and its subclasses.
public: accessible to any outside program.
Let's take one step further back, to the world of C. C has no access modifier whatsoever, not being an OOP language. However, in reality, it's closer to having a private / public system. If you want other programs to know your symbols (functions, macros, data types, etc.), you define them in your header (.h) file. If not, you define them in your source (.c) file or a private header file. Whatever program interested in your symbol will include the corresponding header file:
#include "foo.h"
This #include is no more than a compiler-assisted copy & paste. The compiler copies all the symbols in foo.h and redeclare them in your source file.
Since Objective-C is a strict superset of C, every valid C program is also a valid Objective-C program. Objective-C continues this tradition: declare your public methods in the header file, keep private methods declaration to the implementation file:
// ------------------------------------------
// MyClass.h
// ------------------------------------------
#interface MyClass: NSObject
- (void) publicMethod;
#end
// ------------------------------------------
// MyClass.m
// ------------------------------------------
#import "MyClass.h"
// Declare your private methods here.
// You can move this to a separate file, i.e. MyClass+Private.h if you want
#interface MyClass()
- (void) privateMethod;
#end
#implementation MyClas
- (void) publicMethod () { ... }
- (void) privateMethod() { ... }
#end
So at glance, Objective-C seems to inherit C's system of public / private declarations. However, Objective-C is a very dynamic language. You can query its runtime for all methods to a class, private or public. Access control in Objective-C is more about "use what I tell you in the documentation" rather than "this method is off limit to you".
This poses a paradox: how do you implement protected in Objective-C? It has no good answer for that. One common pattern is to move all protected methods into a separate declaration file and import them into the main class and subclass's implementation:
// ------------------------------------------
// MyClass+Protected.h
// ------------------------------------------
#interface MyClass (Protected)
- (void) protectedMethod;
#end
// ------------------------------------------
// MySubClass.m
// ------------------------------------------
#import "MyClass+Protected.h"
...
Swift simply carries on that tradition, for better or worse. There is an accepted proposal to change this in Swift 3. If anything, Chris Lattner and the Swift team has shown little affinity for the past and the legacies of C. You can see evidence of that in Swift 2.2 with the removal of ++ and C-style for loops.
Like:
#interface ClassXXName(private)
- (void) xxxfunctions
#end
or user category methods?
#interface Foo() creates a class extension (I stand corrected, props to bbum) on interface Foo which is like additional methods added to the interface. Some people also use #interafce Foo(Private) (category) instead of a class extension with (). It's more like "injecting" new methods into a class from outside the class.
Placing this in the .m file just keeps other things from "seeing it" in the .h file, but that's it. Basically people normally use categories or class extensions in .m files to specify private interfaces, but they are also used for things like UIKit uses categories to add row and section public methods to NSIndexPath. (This can be confusing.)
You don't really need to define private methods this way, but if you have a method called bar that calls method foo before foo is defined in the source file you'll get a compiler warning something like "object self may not respond to foo". You can get rid of that by defining foo before you define bar or any other foo-calling code. It's the same with plain C and functions.
Like Ole says this doesn't stop anyone from calling the private methods, it just declares your intention that they be private and causes the compiler to generate the "may not respond to" warnings even if they import the .h file.
I was facing the same error as asked in this question
I overcome with this error by solution of declaring class ahead of time in my .h file with the class parameter
I am having FFTBufferManager.h and FFTBufferManager.cpp file and using it in HomeView.h and HomeView.mm file
class FFTBufferManager,CAStreamBasicDescription,DCRejectionFilter;
But now I am having error as
#include "FFTBufferManager.h"
#include "aurio_helper.h"
#include "CAStreamBasicDescription.h"
class CAStreamBasicDescription,FFTBufferManager; //here it shows this error
EXpected Unqualified-id befor ',' token
#interface HomeView
{
FFTBufferManager* fftBufferManager;
//it shows erros
EXpected Unqualified-id befor ',' token
ISO c++ forbids declaration of FFTBufferManager with no type
}
#property FFTBufferManager* fftBufferManager;
//shows error
'FFTBufferManager' is not a type
I'm gathering you're using both C++ and Objective-C.
I'd suggest renaming all your .cpp and .m files in which Objective-C and C++ code are meeting to use the extension .mm - this tells the compiler to use "Objective-C++" rules, and will stop a lot of compiler troubles.
Also, it seems CAStreamBasicDescritpion is a C++ class - you'll have to forward-declare it with class CAStreamBasicDescritpion;, not #class CAStreamBasicDescritpion; (note, no "at" sign) - the second form is only for forward-declaring Objective-C classes. This I suspect is the root cause of the particular error you have observed.
EDIT in response to comment: I'm not sure about your first new issue - that should work fine so long as both FFTBufferManager and CAStreamBasicDescription are C++ classes. As to your second one, depending on where exactly that line of code is (CAStreamBasicDescription thruFormat;) you may need to include the header rather than just the forward-declare: you're declaring an instance of CAStreamBasicDescription here, and the compiler needs to know its structure to do so.
You can't declare more than one class at a time.
Change your declarations to
class CAStreamBasicDescription;
class FFTBufferManager;
The compiler is looking for an unqualified-id because it believes that you're declaring a variable of type CAStreamBasicDescription, so it expects a variable name where you gave it a comma.
Looks like you are trying to create a class that already exists in one of the Cocoa frameworks.
As I heard it is possible to use C++ Code within an iPhone (Objective C) project, I want to use an encryption library which is written in C++. However, the library uses a C++ type struct which uses a constructor, that I can't get right.
The Struct looks like this:
struct SBlock
{
//Constructors
SBlock(unsigned int l=0, unsigned int r=0) : m_uil(l), m_uir(r) {}
//Copy Constructor
SBlock(const SBlock& roBlock) : m_uil(roBlock.m_uil), m_uir(roBlock.m_uir) {}
SBlock& operator^=(SBlock& b) { m_uil ^= b.m_uil; m_uir ^= b.m_uir; return *this; }
unsigned int m_uil, m_uir;
};
full source is available here: http://www.codeproject.com/KB/security/blowfish.aspx
what's the easiest way to get around that issue?
I've read the article about using c++ code on apple's developer site, but that didn't help much.
It's definitely possible and the trick is extremely simple: when you are going to use C++ code in your Objective-C++ applications, name your files .mm instead of .m.
So if you have YourViewController.h and YourViewController.m, rename the latter to be YourViewController.mm. It will cause XCODE to use C++ compiler instead of C compiler with your Objective-C++ code.
YourViewController.mm:
- (void) yourMessage {
// will compile just fine and call the appropriate C++ constructor
SBlock sb(1,1);
}
Just change the filename extension of your .m file to .mm and include the C++ headers. Wow, I type too slow, lol.