单例的使用

1. OC中

  1.1 NetworkTool.h 文件

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

/**
   应用场景: 场景工具,音频工具
 */
@interface NetworkTools : NSObject

/// 单例的全局访问点   + 表示类函数
+(instancetype)sharedTools;

@end

NS_ASSUME_NONNULL_END

  1.2 NetworkTool.m 文件

#import "NetworkTools.h"

@implementation NetworkTools

+(instancetype)sharedTools{
    static id instance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[self alloc]init];
    });
    return instance;
}

@end

  1.3 调用

#import "ViewController.h"
#import "NetworkTools.h"
@interface ViewController ()
@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    NSLog(@"%@",[NetworkTools sharedTools]);
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    NSLog(@"%@",[NetworkTools sharedTools]);
}
@end

2. Swift 中

  1. 创建 SoundTools 文件

class SoundTools: NSObject {

    override init() {
        print("sharedTools2")
        super.init()
    }
    
    //静态区的对象只能设置一次数值
   @objc static let sharedTools2 = SoundTools()
    
    //Swift 中的单例写法和懒加载几乎一样 ‘static let’
    //同样也是在第一次使用时,才会创建对象
    static let sharedTools3: SoundTools = {
        print("sharedTools3")
        return SoundTools()
    }()
    
    //以下代码是仿 OC 的写法
    //在 Swift 中不允许在函数中定义静态成员
    private static var instance: SoundTools?
    private static let onceToken = NSUUID().uuidString
    
    //1.提供全局的访问点
     class func sharedTools() -> SoundTools{
        DispatchQueue.once {
            instance = SoundTools()
        }
        
        return instance!
    }
}

  2.2 DispatchQueue.once 以弃用,自定义扩展类 DispatchQueue+Extension.swift

import Foundation

public extension DispatchQueue {
    private static var _onceTracker = [String]()

    class func once(file: String = #file, function: String = #function, line: Int = #line, block:()->()) {
        let token = file + ":" + function + ":" + String(line)
        once(token: token, block: block)
    }
    
    /**
     Executes a block of code, associated with a unique token, only once.  The code is thread safe and will
     only execute the code once even in the presence of multithreaded calls.

     - parameter token: A unique reverse DNS style name such as com.vectorform.<name> or a GUID
     - parameter block: Block to execute once
     */
     class func once(token: String, block:()-> ()) {
        objc_sync_enter(self)
        
        defer { objc_sync_exit(self) }
        
        if _onceTracker.contains(token) {
            return
        }
        
        _onceTracker.append(token)
        block()
    }
}

  2.3 调用

import UIKit

class DemoViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        //print(SoundTools.sharedTools)
        //print(SoundTools.sharedTools2)
        print(SoundTools.sharedTools3)
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        //print(SoundTools.sharedTools)
        //print(SoundTools.sharedTools2)
        print(SoundTools.sharedTools3)
    }
}

3.OC & Swift 混合开发

  3.1 Swift 调用 OC 

    3.1.1 在项目的桥接头文件/项目名称-Bridging-Header.h 中 添加 .h 文件
  //目的:让Swift 能够调用 OC
  //使用 让所有 Swift 需要访问的 OC 的头文件在此处引入
   #import "NetworkTools.h"
    3.1.2 调用
import UIKit
class DemoViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        print(NetworkTools.shared())
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        print(NetworkTools.shared())
    }
}

  3.2 OC 调用 Swift

    3.2.1 ProductName-Swift.h  注意 ProductName 不能包含中文和数字的组合~

      点击项目,选择 TARGETS 中 Build Settings 选项卡,索搜 Product Name 修改值为 单例演示, 重新 Clean Build 项目

    3.3.2 调用
#import "ViewController.h"
//ProductName-Swift.h  注意 ProductName 不能包含中文和数字的组合
//Swift 调用 OC 不会有问题
//但是 OC 无法访问 Swift 中的特殊语法,列如: 枚举!
#import "单例演示-Swift.h"
@interface ViewController ()
@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];

    NSLog(@"%@", [SoundTools sharedTools2]);
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

    NSLog(@"%@", [SoundTools sharedTools2]);
}
@end
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在Python中,单例指的是一个类只能有一个实例,并提供一个全局的访问点。常见的实现方式包括使用__new__()方法、装饰器、基于类装饰器的单例实现以及基于元类的单例实现。 1. 使用__new__()方法实现单例 ```python class Singleton: _instance = None def __new__(cls): if not cls._instance: cls._instance = super().__new__(cls) return cls._instance s1 = Singleton() s2 = Singleton() print(s1 is s2) # 输出:True ``` 2. 使用装饰器实现单例 ```python def singleton(cls): instances = {} def get_instance(*args, **kwargs): if cls not in instances: instances[cls] = cls(*args, **kwargs) return instances[cls] return get_instance @singleton class MyClass: pass m1 = MyClass() m2 = MyClass() print(m1 is m2) # 输出:True ``` 3. 基于类装饰器的单例实现 ```python def singleton(cls): instances = {} class SingletonWrapper: def __init__(self, *args, **kwargs): if cls not in instances: instances[cls] = cls(*args, **kwargs) def __call__(self): return instances[cls] return SingletonWrapper @singleton class MyClass: pass m1 = MyClass() m2 = MyClass() print(m1 is m2) # 输出:True ``` 4. 基于元类的单例实现 ```python class Singleton(type): _instances = {} def __call__(cls, *args, **kwargs): if cls not in cls._instances: cls._instances[cls] = super().__call__(*args, **kwargs) return cls._instances[cls] class MyClass(metaclass=Singleton): pass m1 = MyClass() m2 = MyClass() print(m1 is m2) # 输出:True ``` 以上四种方式都可以实现单例,具体使用哪种方式取决于实际情况和个人习惯。需要注意的是,使用单例也可能会带来一些问题,例如线程安全性、生命周期管理等问题,需要谨慎使用

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hanyang Li

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值