Implementing NSCoding protocol - objective-c

I'm working on a obj-c project and I want to implement the NSCoding protocol for a class, but I can't get it right. The code looks like this:
#include <Foundation/Foundation.h>
class Object: NSObject, NSCoding {
//Somecode
}
And I get the error: "Base specifier must name a class" and "Expected class name". What am I doing wrong?

You are declaring a C++ class, not a Objective-C one, and you cannot have inheritance from one language to another. You'll need to change your class declaration to something like
#interface Object: NSObject <NSCoding> {
// iVar declarations
}
// method and property declarations
#end
Although not sure how much it will help if your class already has defined C++ methods, as you'll need to port those one to Objective-C definitions.
I highly recommend you go through the link I posted in my comments, and read Apple's documentation on working with classes and objects. This will help you with the transition.

Related

Swift/ObjC circular import

I am working on an existing large codebase that is predominately Objective-C but is in the process of converting to Swift.
New classes are being implemented in Swift, but some of these classes need to be accessed from existing ObjC code. In an attempt to follow both ObjC and Swift best practices, the new classes do not have a prefix, but are defined with a prefix for ObjC.
/**
Create contrived class that is named XXClassA in ObjC and ClassA in Swift.
*/
#objc(XXClassA) class ClassA: NSObject {
let foo = "bar"
}
So far this has been working great; Swift code uses ClassA() and ObjC uses [[XXClassA alloc] init]. Once all ObjC code that references XXClassA is removed, #objc(XXClassA) can also be removed from the Swift class.
Unfortunately this breaks down if you have an ObjC class reference XXClassA and then the Swift code attempts to use that new class inside of ClassA.
Say I create an ObjC class, named XXClassC and it instantiates itself using an XXClassA (which is really the Swift class ClassA)
//
// XXClassC.h
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
#class XXClassA;
#interface XXClassC : NSObject
-(instancetype)initWithA:(XXClassA *)classA;
#end
NS_ASSUME_NONNULL_END
The circular reference is now in place. If I attempt to use XXClassC from inside of the ClassA, the initializer is not available.
If I redefine ClassA as this instead, all is well again.
class XXClassA: NSObject {
let foo = "bar"
}
I understand why this is happening and the fix I have in place, however I want to continue to use this pattern of prefixed ObjC classes. Any ideas on how to avoid the circular import, but also keep the naming convention?
Full code sample here: https://gist.github.com/justAnotherDev/78483f9d94e40fd90c38
I'm having the same problem. My workaround is:
Use an objc-style prefixed name for the Swift class.
Add a typealias: typealias ClassA = XXClassA.
Always use the unprefixed name from Swift code.
With this pattern it's at least easy to remove the prefix when the last objc dependency is gone.

Swift error: class method "someMethod() is unavailable, use object construction Class()"

Objective-C APIs do a lot of object construction using class methods:
+ (NSDate *)date;
+ (NSURL *)urlWithString:(NSString *)string;
+ (instancetype)layerWithSession:(AVCaptureSession *)session
Sometimes I even see these appearing in old Swift tutorials as class methods, but when I try to call them, I get compiler errors like these:
date() is unavailable, use object construction NSDate()
urlWithString() is unavailable, use object construction NSURL(string:)
layerWithSession() is unavailable, use object construction AVCaptureVideoPreviewLayer(session:)
(I see declarations like convenience init(URL url: NSURL) in the docs, and in Xcode's generated Swift interfaces for SDK classes, but what do they have to do with any of this?)
This even happens when I declare class methods in my own ObjC code, like for a singleton pattern:
#interface MyManager: NSObject
+ (instancetype)manager;
#end
When I try to use them from Swift, I get the same kind of errors:
let manager = MyManager.manager()
// error: 'manager()' is unavailable, use object construction 'MyManager()'
What gives? How do I fix these errors?
Swift does away with the alloc/init initialization pattern from Objective-C and replaces it with a construction syntax similar to that seen in Java or C++.
When, in a Swift class interface (or in Apple's documentation), you see something like:
class Thing {
init(number: Int)
}
That means you can create a Thing by calling it with the following "construction syntax":
let thingTwo = Thing(number: 2)
It doesn't matter if it's a class or a struct, or if you see other things like convenience or required or public before init... that's how you use it. (Of course, replace Thing with the type you're using, number with any parameter label(s) in the actual initializer you want, and 2 with an appropriate value for that parameter.)
When classes originally defined in ObjC are imported into Swift, the Swift compiler does a bunch of things to make those APIs look and feel more like native Swift code. One of those things is to replace the common pattern of using class methods as convenience constructors with real initializers.
All the examples from the question:
+ (NSDate *)date;
+ (NSURL *)urlWithString:(NSString *)string;
+ (instancetype)layerWithSession:(AVCaptureSession *)session;
... are such convenience constructors. That means they import into Swift not as class methods (NSDate.date(), NSURL.urlWithString(), etc), but as initializers:
class NSDate {
init()
}
class NSURL {
init?(string: String)
}
class AVCaptureVideoPreviewLayer {
init!(session: AVCaptureSession)
}
... and you call them with object construction syntax:
let date = NSDate()
let url = NSURL(string: "http://apple.com")
let layer = AVCaptureVideoPreviewLayer(session: mySession)
In fact, when you see error messages about "is unavailable, use object construction", Xcode pretty much always offers an automatic fix-it to insert the proper syntax.
How does this work? Swift looks for possible "base names" of a class and matches between those names and the class method / initializer method names. (It also checks for class methods that return an instance of that class, initializers that start with "init...", etc.)
For example, Swift sees the following as a convenience constructor:
#interface PDQMediaManager: NSObject
+ (PDQMediaManager *)manager;
#end
This may be a problem if what you (or the original developer of PDQMediaManager) intend is for that class to act as a singleton, and the +manager method to return the singleton instance — if a Swift developer writes PDQMediaManager(), they'll be constructing a new instance instead of retrieving the singleton.
In this case, one good solution is to rename the singleton method:
+ (PDQMediaManager *)defaultManager;
This won't get seen as a convenience constructor, so Swift clients can call PDQMediaManager.defaultManager() to get the singleton instance.
You can also use the NS_SWIFT_NAME to rename the singleton method only for Swift clients:
+ (PDQMediaManager *)manager NS_SWIFT_NAME(defaultManager());
If you don't control the codebase with the offending method, your best bet is probably to write your own ObjC code to forward to the singleton method and expose that to your Swift code via a bridging header.

Declaring method prototypes in header and implementation

I am learning object orientated programming from the online Stanford courses there is a part I am unsure of regarding declarations. I thought that you must always declare the prototype in the header and then write the code in the implementation file, but the professor wrote a method in the implementation without a declaration prototype in the header file, how come?
Also, may someone please clear the difference between private and public and if the method without a prototype is public or private? The method without a prototype is not from a super class.
That is a perfectly legal way to declare methods that are not to be used outside the class implementation itself.
The compiler will find methods in the implementation file as long as they precede the method in which they are used. However that will not always be the case, as the new LLVM compiler allows methods to be declared in any order and referenced from a given file.
There are a couple of different styles for declaring methods inside an implementation file:
//In the Header File, MyClass.h
#interface MyClass : NSObject
#end
//in the implementation file, MyClass.m
//Method Decls inside a Private Category
#interface MyClass (_Private)
- (void)doSomething;
#end
//As a class extension (new to LLVM compiler)
#interface MyClass ()
- (void)doSomething;
#end
#implementation MyClass
//You can also simply implement a method with no formal "forward" declaration
//in this case you must declare the method before you use it, unless you're using the
//latest LLVM Compiler (See the WWDC Session on Modern Objective C)
- (void)doSomething {
}
- (void)foo {
[self doSomething];
}
#end
If you write the method in you header file it is public and accessible for other classes / objects. If you do not declare it in the header file the method is a private method meaning that you can access it internally in you class but no other class can use this method.

Does Objective-C have something like C++ virtual functions?

In objective-c it is possible to add a #dynamic to a property.
Is this also possible for normal instance methods?
EDIT
I think i wasn't clear enough.
I want to do the following:
#interface MyClass
#property (retain) NSObject *somePropertyObject;
- (void) myMethod;
#end
#implementation MyClass
#dynamic somePropertyObject;
//Make myMethod dynamic. I do not want to implement it. Like C++ Virtual
#end
If you mean "How can I declare a method, but not provide a definition which I will subsequently provide at runtime?" Then it's easy, just use a category. Like this:
#interface MyObject : NSObject
// Methods I'll define
- (void)doFoo;
#end
#interface MyObject (DynamicallyProvidedMethods)
// Methods I won't
- (void)myDynamicMethod;
#end
#implementation MyObject
// Methods I'll define
- (void)doFoo
{
}
#end
The compiler will not complain, however if you call -myDynamicMethod at runtime, unless you have provided an implementation for it somehow, it will crash with "unrecognized selector." You can, of course, test for that at runtime by calling respondsToSelector:.
Relatedly, if you're looking to do a near-equivalent of a base class pure virtual method, I would recommend providing an empty implementation that asserts when called if it has not been overridden by a subclass. You can do that like so:
NSAssert((class_getInstanceMethod([self class], _cmd) == class_getInstanceMethod([MyObject class], _cmd)),
#"Subclass of %# must override -%#",
NSStringFromClass([MyObject class]),
NSStringFromSelector(_cmd));
// ...where overridesSelector:ofBaseClass: looks like:
//
// return ;
Of course, that won't alert you to problems at compile time, but it's better than nothing.
HTH
I think you might be asking how to declare a method that will be implemented some time later somewhere else.
The Objective-C way to do that is to use Protocols.
You declare a protocol like this, usually in a header file
#protocol MyProtocol <NSObject> {
#optional
- (void)optionalMethod;
#required
- (void)requiredMethod;
}
#end
This declares two methods, one which is optional and one is required. To use this protocol you declare the conformance when declaring the class that will implement the protocol
#interface MyConformingClass : NSObject <MyProtocol> {
}
// you don't have to redeclare methods that are declared in the protocol
#end
This new class is checked at compile time for the implementation of requiredMethod so it has to implement it, but it can choose whether or not to implement the optionalMethod
Now, any class that requires instances of objects to conform to the protocol can declare this, for example, in the interface
#interface RequiringClass : NSObject {
MyConformingClass <MyProtocol> *conformingClassObject;
}
…
#end
Again, this is checked at compile time
To make sure that the conforming class implement the #optional methods, we can use this handy structure
if [conformingClassObject respondsToSelector:#selector(optionalMethod)] {
[conformingClassObject optionalMethod];
} else {
// Do something here because the optional method isn't provided
}
Examples of this are all over Cocoa - it's a class can provide a list of actions that it would like to farm out to it's delegate, the delegate adopts the protocol and provides the implementations of those delegate methods. The calling object can then check if this delegate responds to those methods at runtime as I've described above, and call those methods to perform actions, or provide information where ever it needs to.
This is used quite a lot in Objective-C, where classes provide a list of methods that they would like some other class to perform, unlike virtual functions, where a class declares functions it wants subclasses to provide implementations for. Particularly as Composition is favoured over inheritance in the language. Rather than create a subclass to provide an implementation, you just create another class that can do the same thing, and add a reference to that in the class instead.
No.
#dynamic is just an instruction to the compiler that says: "Don't bother generating accessors for this property, I'm going to provide my own."
Using #dynamic with other methods wouldn't be helpful because the compiler doesn't generate any methods other than accessors for you, and of course you're supplying the other methods anyway.
What are you trying to accomplish?

Is it possible to declare a method as private in Objective-C?

Is it possible to declare a method as private in Objective-C?
If you're working in Objective-C 2.0, the best way to create methods that are "hard" for others to call is to put them in a class extension. Assuming you have
#interface MyClass : NSObject {
}
- (id)aPublicMethod;
#end
in a MyClass.h file, you can add to your MyClass.m the following:
#interface MyClass () //note the empty category name
- (id)aPrivateMethod;
#end
#implementation MyClass
- (id)aPublicMethod {...}
- (id)aPrivateMethod {...} //extension method implemented in class implementation block
#end
The advanage of a class extension is that the "extension" methods are implemented in the original class body. Thus, you don't have to worry about which #implementation block a method implementation is in and the compiler will give a warning if the extension method is not implemented in the class' #implementation.
As others have pointed out, the Objective-C runtime will not enforce the privateness of your methods (and its not too hard to find out what those methods are using class dump, even without the source code), but the compiler will generate a warning if someone tries to call them. In general, the ObjC community takes a "I told you not to call this method [by putting it in a private class extension or category or just by documenting that the method is private] and you called it anyways. Whatever mess ensues is your fault. Don't be stupid." attitude to this issue.
No, any object can send any message to any other object. You can, however, put the method in a category that's part of the class's implementation file. That way, you'll get a "Class may not implement this method" warning if you try to call it anywhere else. That's the normal way of making a method "private."
There is nothing that will prevent the method being called (since objective-c is message based anything can be sent any message), but you can declare them outside of the header so they are not visible and the compiler will generate warnings if used.
This works for both class and instance methods.
E.g.
#import "SomeClass.h"
// Interface for hidden methods
#interface SomeClass (hidden)
+(void) hiddenClassMethod;
-(void) hiddenInstanceMethod;
#end
Note: Do NOT declare variables like this or they will become class-variables - e.g. only one variable will be used by all instances.
You can do so by using categories. I've got a fuller description in my answer to this SO question.
As has been said, you can't stop anyone sending a message to a selector, but by using categories you can reduce the visibility of these functions.
Also, you can have more than one category extending a class. So, by using informative category names you can group private functions into related blocks, improving the self-documenting nature of your code.
As others mentioned, you can't have code that's
a method, and
impossible to call from outside a class.
Folks have already pointed out that you can abandon point 2, and get a method that's hard-but-not-impossible to call. Alternatively, why not abandon point 1?
static id myPrivateMethod(MyObject *me, int arg1, id arg2) { ... }
Now the code can only be called from within same file. You don't get any of the magic private-member access you can get with a method, so this is by no means a perfect solution. But there's no better way to achieve privacy.
To implement hidden methods (instance and/or class)
// ===========================
// = File: SomeClass.m
// ===========================
#import "SomeClass.h"
// =================================
// = Interface for hidden methods
// =================================
#interface SomeClass (hidden)
-(void) hiddenInstanceMethod;
#end
// ================================
// = Implementation for SomeClass
// ================================
#implementation SomeClass
-(void) hiddenInstanceMethod
{
printf( "Hidden instance method\n" );
}
-(void) msg
{
printf("Inside msg()...\n");
[self hiddenInstanceMethod];//private method calling
}
#end
http://macdevelopertips.com/objective-c/private-methods.html
reffer this link it will be helpful .