I have a category (on NSDate) that contains a method that is only called from another method within the category, so there is no need to expose the method in the category's header file.
However, as expected, if I call the method from a unit test, the compiler shouts that
No visible #interface for 'NSDate' declares the selector 'myMethod:'
I'd like to be able to turn off these particular errors (for the unit test target only, of course).
Can someone point me in the direction of the correct compiler flag?
Instead of turning them off why not just redeclare it? If you turn the warnings off completely then you lose the fact that the compiler will give you warnings in genuine places.
So just declare it above the unit test
#interface NSDate (UnitTests)
// your method sig
#end
#implementation YourUnitTest
//...
Related
I am trying to update my Xamarin Mixpanel iOS bindings that I have here. While updating I figured I'd try re-enable a thing I had disabled before I continue to roll out updates all the way to the latest 5.0 release.
Current status is I am attempting to bind v3.6.2 (which is a little outdated) and I am having issues with the binding of some protocol/interface things. The source file that is being bound is MixpanelType.h.
A short example of this is
#protocol MixpanelType <NSObject>
- (BOOL)equalToMixpanelType:(id<MixpanelType>)rhs;
#end
#interface NSString (MixpanelTypeCategory) <MixpanelType>
#end
The generated code that comes out of objective sharpie looks like this,
// #protocol MixpanelType <NSObject>
/*
Check whether adding [Model] to this declaration is appropriate.
[Model] is used to generate a C# class that implements this protocol,
and might be useful for protocols that consumers are supposed to implement,
since consumers can subclass the generated class instead of implementing
the generated interface. If consumers are not supposed to implement this
protocol, then [Model] is redundant and will generate code that will never
be used.
*/[Protocol]
[BaseType (typeof(NSObject))]
interface MixpanelType
{
// #required -(BOOL)equalToMixpanelType:(id<MixpanelType>)rhs;
[Abstract]
[Export ("equalToMixpanelType:")]
bool EqualToMixpanelType (MixpanelType rhs);
}
// #interface MixpanelTypeCategory (NSString) <MixpanelType>
[Category]
[BaseType (typeof(NSString))]
interface NSString_MixpanelTypeCategory : IMixpanelType
{
}
I don't understand Category, Model, or Protocols in objective-c is so I am not entirely sure what it is trying to become. Based on the other things in MixpanelType.h it looks like the code is just trying to allow certain class types to exist.
The code is natively used in a method like this,
- (void)addGroup:(NSString *)groupKey groupID:(id<MixpanelType>)groupID {
which gets bound automatically to look like:
// -(void)addGroup:(NSString * _Nonnull)groupKey groupID:(id<MixpanelType> _Nonnull)groupID;
[Export ("addGroup:groupID:")]
void AddGroup (string groupKey, MixpanelType groupID);
I am unsure if MixpanelType is meant to be IMixpanelType and I am unsure if things like NSString_MixpanelTypeCategory are meant to exist.
Keeping it as above (but changing MixpanelType to `IMixpanelType) and attempting to compile I get the following errors:
Xam.Plugin.Mixpanel.iOS/NSString_MixpanelTypeCategory.g.cs(51,69,51,83): error CS0714: 'NSString_MixpanelTypeCategory': static classes cannot implement interfaces
Xam.Plugin.Mixpanel.iOS/NSString_MixpanelTypeCategory.g.cs(51,69,51,83): error CS0535: 'NSString_MixpanelTypeCategory' does not implement interface member 'IIMixpanelType.EqualToMixpanelType(IMixpanelType)'
Xam.Plugin.Mixpanel.iOS/NSString_MixpanelTypeCategory.g.cs(51,69,51,83): error CS0535: 'NSString_MixpanelTypeCategory' does not implement interface member 'INativeObject.Handle'
Xam.Plugin.Mixpanel.iOS/NSString_MixpanelTypeCategory.g.cs(51,69,51,83): error CS0535: 'NSString_MixpanelTypeCategory' does not implement interface member 'IDisposable.Dispose()'
The first error is odd as this isn't a static class.
The second error is odd and I can't get rid of it by implementing the method.
The third and fourth errors are odd because this class has a base type of NSString and I thought this would have been handled.
Any help on this so I can successfully bind the entire library without MixpanelGroups being disabled would be appreciated.
I'm working on my first Cocoa application, and I'm hoping very much that
[NSWindowController loadWindow]: failed to load window nib file 'Genius Document'
means that there's something very specific I've done wrong, because if I have to go back and redo all the bindings I'll want to kill myself.
FWIW, I'm working with a document-based application that has (so far) only one XIB file and no NIB files.
I can post code/screenshots of my bindings but in case that's not necessary I didn't want to make people wade through them.
Thanks for the help.
The error you have described ultimately occurs because a call to load the nib file is failing. Make sure you've supplied the correct name for your Interface Builder file.
You can supply the correct value in a number of ways (depending on your use of AppKit), so I'll lay out the two most common possibilities and you can track down which one applies to you. Given what you've said in your question, I suspect you'll be dealing with the first scenario.
NSDocument windowNibName
If you are relying on the document architecture's defaults, you are probably not making the call in question directly. Instead, the framework makes the call on your behalf, using whatever nib name you specify on the given document class.
For example, if you were to make a new document-based project with a document class of "XYZDocument," the Xcode template would provide you with a basic XYZDocument class and a XYZDocument.xib file. The XYZDocument implementation file would have the following in it:
// XYZDocument.m
- (NSString *)windowNibName {
return #"XYZDocument"; // this name tells AppKit which nib file to use
}
If you were to alter this value, you would create the [NSWindowController loadWindow] error.
NSWindowController initialization methods
If you are making this call yourself (perhaps on your own subclass of NSWindowController), then you will have written a line like the following.
// XYZWindowController.m (a subclass of NSWindowController)
- (id)init {
self = [super initWithWindowNibName:#"XYZDocument"];
if (self) {
// initializations
}
return self;
}
If the string argument you've supplied does not match the name of the nib file, the same error will occur.
I ran a Clean (Cmd-Shift-K) in Xcode and that solved the issue for me.
When a method is declared in .h file is detected by intelisense and the warnings are not raised, when the method is used in .m file.
When a method is declared only in .m file, the intelisense doesn't detect it if is declared below the method where is being used.
To avoid the warnings there is a flag in xcode, but I prefer don't disable it.
There is any way to declare the methods in .m in order to be detected by intelisense and without the warning?
Thanks.
Two ways to fix it:
Either: Use a class extension to declare private methods at the top of the .m file:
#interface Foo ()
- (void)privateMethod;
#end
Or: Upgrade to Xcode 4.3.1, which contains a more recent version of clang. This newer version of the compiler does not need previously declared methods to call them in the same compilation unit.
Class extensions are still good for compatibility or to declare private properties, though.
You can use a category to declare additional methods on a class.
For instance, adding this at the top of your .m file:
#interface MyClass (PrivateCategory)
-(void)foo;
-(void)bar;
#end
will let Xcode know that MyClass additionally responds to foo and bar. The (PrivateCategory) tells the compiler that you're adding methods that should be "grouped" under the category PrivateCategory. You can pick whatever name you want, or even no name at all (although an "anonymous category" has slightly different semantics).
I've got a call like this [Class method] and a warning saying that Class may not
respond to "method" message.
The "method" message does not indeed exist but my code use unknown message catching
(using forwardingTargetForSelector) so it will run fine and it is build to run that way.
How can I hide this annoying warning ?
If you intend to send a possibly-unimplemented message to an object, and you know that you're going to catch failures, you should use the invocation:
id myClone = [anObject performSelector:#selector(copy)];
That declares your intent more directly that you are calling a method that may not exist, and you're cool with that. This is a more clear way to do it than to suppress the warning or fake out the method.
You could define a category that declares that method. Having the definition in scope at the time of compilation would avoid the warning. Something like
#interface MyClass (ShutUpTheCompilerMethods)
- (void)method;
#end
...
[MyClass method] //no warning here
I'm writing a Cocoa API for a project and the API takes a delegate. The protocol that I came up with declares all the methods as optional, but why would I do that instead of just documenting the delegate methods in a header file and taking a plain id as a parameter?
For the benefit of your users. If the object takes delegates conforming to some protocol and they pass something else in, the compiler can tell them. That isn't possible if you take an id and use a category as the delegate method interface.
Because having "all of these methods" optional isn't quite the same as permitting "anything you care to send".
It also produces code that is more usable in the IDE. For example if I'm looking at
#interface MyController : NSObject <FooBarDelegate> {
}
#end
I can command+double click in Xcode to jump to the definition of FooBarDelegate. With a category there's no formal declaration of intent to be a delegate.
Also, #required can be a problem for future plans with regard to backward binary compatibility and a new preferred method signature.