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对比学习

官方资源

相关推荐
tangweiguo030519875 小时前
SwiftUI布局完全指南:从入门到精通
ios·swift
T1an-19 小时前
最右IOS岗一面
ios
坏小虎12 小时前
Expo 快速创建 Android/iOS 应用开发指南
android·ios·rn·expo
光影少年13 小时前
Android和iOS原生开发的基础知识对RN开发的重要性,RN打包发布时原生端需要做哪些配置?
android·前端·react native·react.js·ios
北京自在科技13 小时前
Find My 修复定位 BUG,AirTag 安全再升级
ios·findmy·airtag
Digitally14 小时前
如何不用 USB 线将 iPhone 照片传到电脑?
ios·电脑·iphone
Sim14801 天前
iPhone将内置本地大模型,手机端AI实现0 token成本时代来临?
人工智能·ios·智能手机·iphone
Digitally1 天前
如何将 iPad 上的照片传输到 U 盘(4 种解决方案)
ios·ipad
报错小能手1 天前
ios开发方向——swift并发进阶核心 @MainActor 与 DispatchQueue.main 解析
开发语言·ios·swift
LcGero1 天前
Cocos Creator 业务与原生通信详解
android·ios·cocos creator·游戏开发·jsb