I want create singleton class But I don't know how?
Example:
class Singleton {
Singleton singleton = null;
public static Singleton getInstance()
{
if (singleton == null)
singleton = new Singleton();
return singleton;
}
}
Simply add static before in the singleton class.
class Singleton {
static Singleton singleton = null;
public static Singleton getInstance()
{
if (singleton == null)
singleton = new Singleton();
return singleton;
}
}
Related
I hope the title is precise enough.
I was wondering, how I can pass a interface implementation to an object in objc language.
In java it would look like:
public interface MyInterface {
void onData();
}
The implementing class
public class ImplementMyInterface {
// ...
// other methods
///
void registerInterface(){
MyInterface myInterface = new MyInterface(){
#Override
public void onData(){
// process data here within the class
}
};
}
}
And in objc?
id myinterface.
How to implement it in the class?
Is there only the possibility to let the class inherit the interface?
Like
interface MyInterface : NSObject
and the implementing class
MyImplementingClass : MyInterface
Or is there another possibility?
Thank you in advance
Objective-C has anonymous functions (blocks), but it doesn't have anonymous classes. So, the only way to implement a protocol (which is the objective-c term for an interface) is to make some class conform to that protocol (using your terminology, make that class "inherit" from that protocol) and add a protocol implementation inside that class' implementation.
I was able to solve my problem.
I was only able to import the MyInterface header file in my ImplementMyInterface.m file, but rather in the ImplementMyInterface.h file.
So everything I could do was inside the ImplementMyInterface.m file.
// ImplementMyInterface.m
#import "MyInterface.h"
// inner class
#interface MyInternalInterface : NSObject<MyInterface>
#property (retain) ImplementMyInterface * implementation;
#end
// the actual class
#implementation ImplementMyInterface
MyInternalInterface * _internalInterface;
+(instancetype) build {
// construct myself
ImplementMyInterface * implementatMyInterface = [[ImplementMyInterface alloc] init];
// init inner class object
_internalInterface = [[MyInternalInterface alloc] init];
// register myself
[_internalInterface setImplementation:implementatMyInterface];
return implementatMyInterface;
}
- (NSString *) theActualData {
return #"The actual data";
}
// end of implementation class
#end
// implementation of inner class
#implementation MyInternalInterface
#synthesize implementation;
- (NSString *) onData {
if(implementation != nil)
return [implementation theActualData];
return #"";
}
// end of ImplementMyInterface.m
I need to write a method that returns a class.
#implementation MyFactory
- (Class)defaultViewClass {
return [MyView class];
}
#end
The returned class is not type safe. You can cast it to any random class. You can also call any random initializer method without a compiler error.
MyFactory *factory = [MyFactory new];
Class viewClass = [factory defaultViewClass];
RandomView *view = [[viewClass alloc] initWithRandomStuff];
How do I redefine my method to return a Class of a particular type? I want to do something like this, but the compiler complains that it can't return specific class types.
- (AbstractViewClass)defaultViewClass {
return [ConcreteViewClass class];
}
The reason why I need to deal with classes rather than object pointers is because I need to call a static function polymorphically.
You won't get the benefit of compile-time type checking when working with Class objects in Objective-C due to the dynamic nature of the language. However, you can enforce such constraints in a strictly typed language like Swift.
protocol AbstractView {
init(parameter: Int)
}
class ConcreteView: AbstractView {
required init(parameter: Int) { }
}
class ViewFactory {
func defaultViewClass() -> AbstractView.Type {
return ConcreteView.self
}
}
let factory = ViewFactory()
let viewClass = factory.defaultViewClass()
let view = viewClass.init(parameter: 0)
print("\(view.self)", terminator: "") // Prints "ConcreteView"
AbstractView is a protocol as there is no concept of an abstract class in Swift, although it could just as easily be a class.
I'm having some trouble accessing a Swift Singleton from Objective-C.
#objc class SingletonTest: NSObject {
// swiftSharedInstance is not accessible from ObjC
class var swiftSharedInstance: SingletonTest {
struct Singleton {
static let instance = SingletonTest()
}
return Singleton.instance
}
}
swiftSharedInstance can not be reached.
Nicky Goethlis's answer is correct but I just want to add another way of Singleton creation termed as One line Singleton" in Swift which I came across recently and it does not use Struct:
Singleton.swift
#objc class Singleton: NSObject {
static let _singletonInstance = Singleton()
private override init() {
//This prevents others from using the default '()' initializer for this class.
}
// the sharedInstance class method can be reached from ObjC. (From OP's answer.)
class func sharedInstance() -> Singleton {
return Singleton._singletonInstance
}
// Some testing
func testTheSingleton() -> String {
return "Hello World"
}
}
SomeObjCFile.m
Singleton *singleton = [Singleton sharedInstance];
NSString *testing = [singleton testTheSingleton];
NSLog(#"Testing---> %#",testing);
Swift 5 and above
final class Singleton: NSObject {
#objc static let shared = Singleton()
#objc var string: String = "Hello World"
private override init() {}
}
use in Objective-C
#import <ProjectName-Swift.h> // change ProjectName to actual project name
NSLog("Singleton String = %#", [Singleton shared].string);
For now I have the following solution. Maybe I am overlooking something that would enable me to access "swiftSharedInstance" directly?
#objc class SingletonTest: NSObject {
// swiftSharedInstance is not accessible from ObjC
class var swiftSharedInstance: SingletonTest {
struct Singleton {
static let instance = SingletonTest()
}
return Singleton.instance
}
// the sharedInstance class method can be reached from ObjC
class func sharedInstance() -> SingletonTest {
return SingletonTest.swiftSharedInstance
}
// Some testing
func testTheSingleton() -> String {
return "Hello World"
}
}
Then in ObjC I can get the sharedInstance class method (after importing the xcode generated swift header bindings)
SingletonTest *aTest = [SingletonTest sharedInstance];
NSLog(#"Singleton says: %#", [aTest testTheSingleton]);
To make members of the SingletonTest class accessible (swiftSharedInstance is a member of this class), use #objcMembers modifier on the class, or add #objc modifier directly on the swiftSharedInstance:
#objc #objcMembers class SingletonTest: NSObject {
// swiftSharedInstance is not accessible from ObjC
class var swiftSharedInstance: SingletonTest {
struct Singleton {
static let instance = SingletonTest()
}
return Singleton.instance
}
}
Or:
#objc class SingletonTest: NSObject {
// swiftSharedInstance is not accessible from ObjC
#objc class var swiftSharedInstance: SingletonTest {
struct Singleton {
static let instance = SingletonTest()
}
return Singleton.instance
}
}
After creating the Bridging header, be sure to have the Objective-C Generated Interface Header Name set in your Build Settings from your app target. If the value is empty, add the following value:
$(SWIFT_MODULE_NAME)-Swift.h
You need add #objc property wrapper to your singleton:
#objc final class Singleton: NSObject {
#objc static let sharedInstance = Singleton()
#objc func foo() { }
}
Then, in the Objective-C class, import the following:
// Replace the "App" with your Target name.
#import "App-Swift.h"
Finally, after compiling the project, you will be able to use your singleton from Swift inside your Objective-C class:
[[Singleton sharedInstance]foo];
You pretty much have it. To use Swift classes in Obj-C you both need to #import "SingletonTest-Swift.h the generated header or forward declaration with #class MySwiftClass.
Additionally the class needs to inherit from an Obj-C class like you have don here with NSObject or be marked with #objc to expose it. You don't need to do both though, #objc is there to be a more granular option when choosing things to expose.
Apple has some good documentation on all of this and there are two different WWDC sessions you can watch on the topic of Obj-C interoperability as well.
Don't forget to set sharedInstance as public
public final class TestSwiftMain: NSObject {
#objc public static let sharedInstance = TestSwiftMain()
private override init() {}
#objc public func test() {
print("testing swift framework")
}
}
Using it in Objc
[[testSwiftMain sharedInstance] test];
Update 12 Oct 2022
ObcMember So you won't have to write objC behind every function
Swift Class
#objcMembers class SwiftHelpingExtentions: NSObject {
static let instanceShared = SwiftHelpingExtentions()
func testingMethod() {
print("testing")
}
}
}
On objective C View Controller
import : #import "App-Swift.h"
Call The method:
[SwiftHelpingExtentions.instanceShared testingMethod];
In Java, I would do the following:
final class Person {
private Person() { }
public static Person makeNewPerson() {
Person p = new Person();
// any initialization code...
return p;
}
}
In Objective-C, my first attempt would be:
#interface Person : NSObject
// How to hide constructors here?
+ (Person *) makeNewPerson;
#end
#implementation Person
+ (Person *) makeNewPerson
{
Person *p = [[Person alloc] init];
// setup...
return p;
}
#end
The reason I want to do this is mainly because I will have many instances of this class, and I would like to use a cache to reuse instances instead of allowing the creation of copies.
Thanks!
In objective-c is not necessary to create declaration for methods. Create only implementation and is all you need to make method "private".
Private in quotes because there is no way to make truly private methods.
I need to call a class method on a variable of type Class, which I know holds a subclass of a base class, MyBaseClass...
- (void)foo:(Class)clazz {
// Now i want to call +myClassMethod on clazz
}
I don't know if this is actually possible. If it is, is there a safer way to guarantee that clazz is actually a subclass of MyBaseClass?
Thanks in advance
You can use -respondsToSelector:, just like you would with any Objective-C object. You can also use +isSubclassOfClass: to test whether the class is a subclass of another class.
- (void)foo:(Class)clazz
{
if ([clazz respondsToSelector:#selector(myClassMethod)])
{
[clazz myClassMethod];
}
else
{
// clazz does not implement that class method.
}
if ([clazz isSubclassOfClass:[MyBaseClass class]])
{
[clazz myClassMethod];
}
else
{
// clazz is not a subclass of MyBaseClass.
}
}
Try this:
if ( [clazz isKindOfClass:[MyBaseClass class]] ) {
[clazz myClassMethod];
}