📖 简介

在iOS中大型项目开发中,单例模式是使用频率最高、最简单且最重要的创建型设计模式。几乎所有企业级项目都会用到单例,例如网络管理、用户信息、全局配置等。本文通俗易懂讲解单例模式核心概念、底层原理、企业级标准写法、真实开发使用场景,附带可直接复用的完整示例代码,同时总结开发注意事项与避坑要点,适合新手学习、面试背诵、项目开发参考。

一、单例模式核心概念

1.1 什么是单例模式?

单例模式属于创建型设计模式,它可以保证:在整个App程序生命周期中,一个类有且仅有一个实例对象,并且对外提供统一的全局访问入口

1.2 核心四大特征

  • 唯一性:全局有且仅有一个实例,初始化仅执行一次;

  • 全局性:项目任意页面、任意模块均可直接访问;

  • 私有化构造器:禁止外部手动创建实例,杜绝重复初始化;

  • 生命周期常驻:对象内存常驻,跟随App进程销毁而释放。

1.3 底层实现原理

Swift中单例底层实现逻辑十分简单:

  1. 使用静态常量生成唯一实例;

  2. 私有化 init\(\)构造方法,禁止外部创建;

  3. Swift静态常量天然线程安全,底层编译器保证初始化仅执行一次,无需手动加锁。

二、Swift企业级标准单例写法

2.1 最简通用写法(生产项目首选✅)

该写法简洁、线程安全、无冗余代码,是目前99% Swift中大型项目通用写法。

final class Manager {
    // 1. 全局唯一静态实例
    static let shared = Manager()
    // 2. 私有化构造方法,禁止外部init创建
    private init() {}
}

2.2 进阶加固写法(防止拷贝篡改)

为避免外部拷贝、复制单例对象,禁止拷贝方法,适合严谨商业项目:

final class UserManager {
    static let shared = UserManager()
    private init() {}
    // 禁止拷贝
    private func copy() {}
    private func mutableCopy() {}
}

2.3 调用方式

无需初始化,全局任意位置直接点语法调用:

UserManager.shared.xxx

三、单例模式真实开发使用场景

单例不可滥用,仅适合全局唯一、需要频繁跨页面调用的管理类,以下为iOS企业级项目固定使用场景:

3.1 网络请求管理器

统一管理全局请求头、Token、超时时间、请求拦截、异常处理,避免重复创建请求会话,统一管控网络逻辑。

3.2 全局用户信息管理器

存储用户登录状态、用户ID、昵称、权限信息,全局快速判断登录态,统一处理登录、退出登录逻辑。

3.3 App全局配置管理器

管理环境切换(开发/测试/生产)、主题配色、全局开关、埋点配置、动态域名等。

3.4 本地缓存/文件管理器

统一封装沙盒读写、缓存清理、图片缓存、数据持久化逻辑,规范本地存储操作。

3.5 第三方SDK统一管理器

推送、支付、分享、崩溃监控、统计SDK统一初始化,集中管理SDK生命周期。

3.6 全局事件状态管理器

监听登录注销、暗黑模式、语言切换、版本更新等全局状态,实现跨页面通信。

四、项目实战完整示例代码

4.1 实战一:全局网络请求单例

封装通用GET/POST请求,统一配置基础参数,项目直接复用:

import Foundation
/// 全局网络请求管理器
final class NetworkManager {
    // 单例
    static let shared = NetworkManager()
    private init() {
        setupBaseConfig()
    }
    /// 基础配置
    private func setupBaseConfig() {
        print("初始化:配置超时、请求头、公共参数")
    }
    /// 通用GET请求
    func getRequest(url: String, completion: @escaping (Data?, Error?) -> Void) {
        guard let url = URL(string: url) else { return }
        URLSession.shared.dataTask(with: url) { data, _, error in
            completion(data, error)
        }.resume()
    }
}
// 业务层调用
NetworkManager.shared.getRequest(url: "https://www.baidu.com") { data, error in
    if let data = data {
        print("请求成功:\(data)")
    }
}

4.2 实战二:全局用户信息单例

管控用户登录态,任意页面快速获取用户信息:

import Foundation
/// 全局用户信息管理器
final class UserManager {
    static let shared = UserManager()
    private init() {}
    
    /// 用户信息
    var userId: String = ""
    var nickName: String = ""
    var isLogin: Bool = false
    
    /// 登录
    func login(userId: String, nickName: String) {
        self.userId = userId
        self.nickName = nickName
        self.isLogin = true
    }
    /// 退出登录
    func logout() {
        userId = ""
        nickName = ""
        isLogin = false
    }
}
// 使用示例
UserManager.shared.login(userId: "10001", nickName: "iOS开发工程师")
if UserManager.shared.isLogin {
    print("当前登录用户:\(UserManager.shared.nickName)")
}
UserManager.shared.logout()

五、单例模式优缺点总结

5.1 优点

  • 节省内存:全局仅创建一次实例,避免重复开辟内存空间;

  • 统一管理:集中管控通用逻辑,代码规范性更强;

  • 调用简单:无需初始化,全局任意位置直接调用;

  • 线程安全:Swift静态常量天然线程安全,无需额外加锁。

5.2 缺点

  • 常驻内存:生命周期跟随App,不会主动释放,长期占用内存;

  • 耦合度高:过度依赖单例会造成代码耦合严重,不利于模块解耦;

  • 测试困难:全局强依赖,不方便做单元测试。

六、开发规范与避坑指南(重点⚠️)

  1. 严格控制使用范围:仅用于管理器类(网络、用户、SDK),普通业务页面、临时业务类禁止使用;

  2. 必须私有化构造器:强制添加 private init\(\),防止外部随意创建实例;

  3. 禁止单例嵌套引用:避免多个单例互相持有,造成内存泄漏;

  4. 轻量化设计:单例内部不要编写复杂冗余业务逻辑,保持工具纯净性;

  5. 禁止滥用全局变量:不要在单例中随意定义大量全局属性,防止内存膨胀。

七、总结

单例模式是iOS开发最简单、最高频的设计模式,static let shared + private init() 是Swift项目企业级标准写法。开发中要明确使用场景,只用于全局通用管理类,切忌滥用;合理使用单例可以简化代码、统一管控逻辑,滥用则会造成代码耦合、内存常驻问题。

本文所有代码均可直接复制到项目中使用,适合新手入门、面试复习、生产项目开发。


更多推荐