iOS代码架构

iOS架构概览

以下是iOS应用架构的核心层次:

graph TB A[用户界面层] --> B[业务逻辑层] B --> C[数据访问层] C --> D[系统框架层] A1[UIViewController] --> A A2[UIView] --> A A3[SwiftUI/UIKit] --> A B1[ViewModel] --> B B2[Manager] --> B B3[Service] --> B C1[Repository] --> C C2[Data Models] --> C C3[Core Data/Realm] --> C D1[Foundation] --> D D2[Core Graphics] --> D D3[Network] --> D D4[Security] --> D

核心架构模式

1. MVC (Model-View-Controller)

swift 复制代码
// Model
struct User {
    let id: Int
    let name: String
    let email: String
}

// View
class UserView: UIView {
    private let nameLabel = UILabel()
    private let emailLabel = UILabel()
    
    func configure(with user: User) {
        nameLabel.text = user.name
        emailLabel.text = user.email
    }
}

// Controller
class UserViewController: UIViewController {
    private let userView = UserView()
    private var user: User?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupView()
        fetchUser()
    }
    
    private func fetchUser() {
        // 获取用户数据
        user = User(id: 1, name: "John", email: "john@example.com")
        userView.configure(with: user!)
    }
}

2. MVVM (Model-View-ViewModel)

swift 复制代码
// Model
struct Product {
    let id: Int
    let name: String
    let price: Double
}

// ViewModel
class ProductViewModel {
    private let product: Product
    
    var displayName: String {
        return product.name
    }
    
    var displayPrice: String {
        return String(format: "$%.2f", product.price)
    }
    
    init(product: Product) {
        self.product = product
    }
}

// View
class ProductViewController: UIViewController {
    @IBOutlet weak var nameLabel: UILabel!
    @IBOutlet weak var priceLabel: UILabel!
    
    var viewModel: ProductViewModel! {
        didSet {
            updateUI()
        }
    }
    
    private func updateUI() {
        nameLabel.text = viewModel.displayName
        priceLabel.text = viewModel.displayPrice
    }
}

3. VIPER (View-Interactor-Presenter-Entity-Router)

swift 复制代码
// Entity
struct Article {
    let title: String
    let content: String
}

// Interactor
protocol ArticleInteractorProtocol {
    func fetchArticles()
}

class ArticleInteractor: ArticleInteractorProtocol {
    weak var presenter: ArticlePresenterProtocol?
    
    func fetchArticles() {
        // 网络请求获取文章
        let articles = [Article(title: "iOS架构", content: "...")]
        presenter?.articlesFetched(articles)
    }
}

// Presenter
protocol ArticlePresenterProtocol: AnyObject {
    func viewDidLoad()
    func articlesFetched(_ articles: [Article])
}

class ArticlePresenter: ArticlePresenterProtocol {
    weak var view: ArticleViewProtocol?
    var interactor: ArticleInteractorProtocol
    var router: ArticleRouterProtocol
    
    init(view: ArticleViewProtocol, interactor: ArticleInteractorProtocol, router: ArticleRouterProtocol) {
        self.view = view
        self.interactor = interactor
        self.router = router
    }
    
    func viewDidLoad() {
        interactor.fetchArticles()
    }
    
    func articlesFetched(_ articles: [Article]) {
        view?.showArticles(articles)
    }
}

核心技术栈

1. 用户界面框架

SwiftUI (现代声明式UI)

swift 复制代码
struct ContentView: View {
    @State private var isLoggedIn = false
    @StateObject private var userModel = UserModel()
    
    var body: some View {
        NavigationView {
            if isLoggedIn {
                DashboardView()
                    .environmentObject(userModel)
            } else {
                LoginView(isLoggedIn: $isLoggedIn)
            }
        }
    }
}

struct LoginView: View {
    @Binding var isLoggedIn: Bool
    @State private var username = ""
    @State private var password = ""
    
    var body: some View {
        VStack(spacing: 20) {
            TextField("用户名", text: $username)
                .textFieldStyle(RoundedBorderTextFieldStyle())
            
            SecureField("密码", text: $password)
                .textFieldStyle(RoundedBorderTextFieldStyle())
            
            Button("登录") {
                authenticateUser()
            }
            .disabled(username.isEmpty || password.isEmpty)
        }
        .padding()
    }
    
    private func authenticateUser() {
        // 认证逻辑
        isLoggedIn = true
    }
}

UIKit (传统命令式UI)

swift 复制代码
class ProfileViewController: UIViewController {
    private let tableView = UITableView()
    private let profileHeaderView = ProfileHeaderView()
    private var user: User?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupTableView()
        setupConstraints()
        loadUserData()
    }
    
    private func setupTableView() {
        tableView.delegate = self
        tableView.dataSource = self
        tableView.register(UserInfoCell.self, forCellReuseIdentifier: "UserInfoCell")
        view.addSubview(tableView)
    }
    
    private func loadUserData() {
        UserService.shared.fetchUser { [weak self] user in
            self?.user = user
            self?.tableView.reloadData()
        }
    }
}

2. 数据持久化

Core Data

swift 复制代码
// Core Data Stack
class CoreDataStack {
    static let shared = CoreDataStack()
    
    lazy var persistentContainer: NSPersistentContainer = {
        let container = NSPersistentContainer(name: "MyApp")
        container.loadPersistentStores { description, error in
            if let error = error {
                fatalError("Unable to load persistent stores: \(error)")
            }
        }
        return container
    }()
    
    var context: NSManagedObjectContext {
        return persistentContainer.viewContext
    }
}

// Data Model
class UserEntity: NSManagedObject {
    @NSManaged var id: Int64
    @NSManaged var name: String
    @NSManaged var email: String
}

// Repository Pattern
class UserRepository {
    private let context: NSManagedObjectContext
    
    init(context: NSManagedObjectContext = CoreDataStack.shared.context) {
        self.context = context
    }
    
    func saveUser(_ user: User) throws {
        let userEntity = UserEntity(context: context)
        userEntity.id = Int64(user.id)
        userEntity.name = user.name
        userEntity.email = user.email
        
        try context.save()
    }
    
    func fetchUsers() throws -> [User] {
        let request: NSFetchRequest<UserEntity> = UserEntity.fetchRequest()
        let entities = try context.fetch(request)
        return entities.map { User(id: Int($0.id), name: $0.name, email: $0.email) }
    }
}

3. 网络层架构

swift 复制代码
// API Client
protocol APIClient {
    func request<T: Decodable>(_ endpoint: Endpoint) async throws -> T
}

class NetworkManager: APIClient {
    private let session: URLSession
    private let baseURL = "https://api.example.com"
    
    init(session: URLSession = .shared) {
        self.session = session
    }
    
    func request<T: Decodable>(_ endpoint: Endpoint) async throws -> T {
        let request = try endpoint.urlRequest(baseURL: baseURL)
        let (data, response) = try await session.data(for: request)
        
        guard let httpResponse = response as? HTTPURLResponse,
              (200...299).contains(httpResponse.statusCode) else {
            throw NetworkError.invalidResponse
        }
        
        return try JSONDecoder().decode(T.self, from: data)
    }
}

// Endpoint Protocol
protocol Endpoint {
    var path: String { get }
    var method: HTTPMethod { get }
    var parameters: [String: Any]? { get }
    var headers: [String: String]? { get }
}

extension Endpoint {
    func urlRequest(baseURL: String) throws -> URLRequest {
        guard let url = URL(string: baseURL)?.appendingPathComponent(path) else {
            throw NetworkError.invalidURL
        }
        
        var request = URLRequest(url: url)
        request.httpMethod = method.rawValue
        request.allHTTPHeaderFields = headers
        
        if let parameters = parameters {
            if method == .get {
                var components = URLComponents(url: url, resolvingAgainstBaseURL: false)
                components?.queryItems = parameters.map { 
                    URLQueryItem(name: $0.key, value: "\($0.value)") 
                }
                request.url = components?.url
            } else {
                request.httpBody = try JSONSerialization.data(withJSONObject: parameters)
            }
        }
        
        return request
    }
}

依赖管理

Swift Package Manager

swift 复制代码
// Package.swift
// swift-tools-version:5.5
import PackageDescription

let package = Package(
    name: "MyApp",
    platforms: [
        .iOS(.v15)
    ],
    products: [
        .library(
            name: "MyApp",
            targets: ["MyApp"]),
    ],
    dependencies: [
        .package(url: "https://github.com/Alamofire/Alamofire.git", from: "5.6.0"),
        .package(url: "https://github.com/SnapKit/SnapKit.git", from: "5.6.0")
    ],
    targets: [
        .target(
            name: "MyApp",
            dependencies: ["Alamofire", "SnapKit"]),
        .testTarget(
            name: "MyAppTests",
            dependencies: ["MyApp"]),
    ]
)

测试架构

swift 复制代码
// Unit Tests
class UserViewModelTests: XCTestCase {
    var viewModel: UserViewModel!
    var mockService: MockUserService!
    
    override func setUp() {
        super.setUp()
        mockService = MockUserService()
        viewModel = UserViewModel(userService: mockService)
    }
    
    func testUserLoading() async {
        // Given
        let expectedUser = User(id: 1, name: "Test User", email: "test@example.com")
        mockService.user = expectedUser
        
        // When
        await viewModel.loadUser()
        
        // Then
        XCTAssertEqual(viewModel.user?.name, "Test User")
    }
}

// UI Tests
class LoginUITests: XCTestCase {
    var app: XCUIApplication!
    
    override func setUp() {
        super.setUp()
        app = XCUIApplication()
        app.launch()
    }
    
    func testSuccessfulLogin() {
        let usernameTextField = app.textFields["username"]
        let passwordTextField = app.secureTextFields["password"]
        let loginButton = app.buttons["login"]
        
        usernameTextField.tap()
        usernameTextField.typeText("testuser")
        
        passwordTextField.tap()
        passwordTextField.typeText("password123")
        
        loginButton.tap()
        
        XCTAssertTrue(app.navigationBars["Dashboard"].exists)
    }
}

基础

graph LR A[Swift语法基础] --> B[iOS SDK基础] B --> C[UIKit入门] C --> D[简单项目实践] A1[变量与类型] --> A A2[控制流] --> A A3[函数与闭包] --> A A4[面向对象] --> A B1[Cocoa Touch] --> B B2[Foundation框架] --> B B3[Auto Layout] --> B

进阶

  • 架构模式:深入理解MVC、MVVM
  • 网络编程:URLSession、RESTful API
  • 数据持久化:Core Data、UserDefaults
  • 并发编程:GCD、Operation Queue

高级

  • 响应式编程:Combine框架
  • 现代UI:SwiftUI深度掌握
  • 性能优化:内存管理、性能调优
  • 测试驱动开发:单元测试、UI测试

专家

  • 架构设计:VIPER、Clean Architecture
  • 工程化:CI/CD、模块化
  • 底层原理:Runtime、内存管理机制
  • 跨平台:Flutter、React Native对比学习

官方资源

相关推荐
非专业程序员3 小时前
从0到1自定义文字排版引擎:原理篇
前端·ios
2501_915918415 小时前
Video over HTTPS,视频流(HLSDASH)在 HTTPS 下的调试与抓包实战
网络协议·http·ios·小程序·https·uni-app·iphone
2501_9160137415 小时前
iOS 26 系统流畅度检测 从视觉特效到帧率稳定的实战策略
android·macos·ios·小程序·uni-app·cocoa·iphone
咕噜企业签名分发-淼淼19 小时前
App防止恶意截屏功能的方法:iOS、Android和鸿蒙系统的实现方案
android·ios·harmonyos
游戏开发爱好者81 天前
iOS 26 崩溃日志深度解读,获取方式、系统变动、定位策略
android·macos·ios·小程序·uni-app·cocoa·iphone
深盾科技1 天前
如何读懂Mach-O:构建macOS和iOS应用安全的第一道认知防线
安全·macos·ios
FreeBuf_1 天前
iOS 0Day漏洞CVE-2025-24085相关PoC利用细节已公开
macos·ios·cocoa
林鸿群1 天前
MacOS arm64 编译GStreamer iOS平台库
macos·ios
2501_916007472 天前
iOS 混淆与团队协作,研发、安全、运维、测试如何在加固流程中高效配合(iOS 混淆、ipa 加固、协作治理)
android·ios·小程序·https·uni-app·iphone·webview