Swift與iOS內存管理機制深度剖析

前言

內存管理是每一位 iOS?開發者都繞不開的話題。雖然?Swift 的 ARC(自動引用計數)極大簡化了開發者的工作,但只有深入理解其底層實現,才能寫出高效、健壯的代碼,避免各種隱蔽的內存問題。本文將從底層原理出發,系統梳理?Swift?與?iOS?的內存管理機制,結合實戰經驗,分享常見問題與優化建議。

一、ARC 的底層實現原理

1.1 ARC?的本質與設計目標

ARC(Automatic Reference Counting,自動引用計數)并非傳統意義上的垃圾回收器(如 Java?的 GC),而是一種編譯器驅動的內存管理機制。其核心設計目標包括:

  • 自動管理對象生命周期,有效防止內存泄漏和野指針問題;
  • 高性能,最大限度減少運行時的性能損耗;
  • 開發者友好,讓開發者專注于業務邏輯,無需手動管理內存。

1.2 編譯器插樁機制

ARC 的實現依賴于編譯器插樁:在源碼編譯階段,編譯器會自動在合適的位置插入?retain、release、autorelease?等內存管理指令。開發者無需手動調用這些方法,編譯器會根據變量作用域、閉包捕獲等場景自動生成相應的代碼。

例如,以下 Swift?代碼:

func foo() {let obj = MyClass()obj.doSomething()
}

Swift 編譯器會在需要時插入?swift_retain?和?swift_release?調用,編譯后,等價于如下偽代碼:

let obj = swift_alloc(MyClass)
swift_retain(obj)
obj.doSomething()
swift_release(obj)

開發者無需手動管理這些操作,編譯器會根據變量作用域、閉包捕獲等場景自動插入合適的指令。

1.3?retain/release 的底層原理

每當你增加或減少一個對象的強引用時,Swift 底層會自動用?swift_retain?或?swift_release?這類函數。

  • retain:將對象的引用計數加一。
  • release:將對象的引用計數減一。如果計數減到零,系統會自動調用對象的析構方法(deinit),并釋放其占用的內存。

在多線程環境下,可能會有多個線程同時對同一個對象進行 retain?或?release 操作。為了避免數據競爭和計數錯誤,Swift?在底層實現中采用了原子操作(atomic operation),例如 C++11 的?std::atomic。這樣可以確保每一次引用計數的增加或減少都是安全且不可分割的,避免出現“加錯”或“減錯”的情況,從而保證了?ARC?在多線程下的正確性和穩定性。

1.4 對象銷毀的完整流程

  1. 當引用計數減為零:當最后一個強引用消失,release?操作使引用計數變為 0。
  2. 調用析構方法:Swift 自動調用對象的?deinit?方法(Objective-C 為?dealloc),用于資源清理、通知等。
  3. 釋放成員變量:對象的所有成員變量(包括強引用的其他對象)會被依次?release,遞歸觸發它們的引用計數變化。
  4. 回收內存:對象的內存塊被系統回收,徹底釋放。

1.5?ARC?的作用范圍

  • ARC 主要作用于類(class)類型的實例。只有引用類型(如?class、NSObject?及其子類)才有引用計數,受?ARC?管理。
  • 結構體(struct)和枚舉(enum)為值類型,生命周期由作用域自動管理,不參與 ARC。

1.6?引用計數的類型

ARC 支持多種引用類型,不同類型對引用計數的影響不同:

  • 強引用(strong):默認引用類型,持有對象時引用計數加一,保證對象在引用期間不會被釋放。
  • 弱引用(weak):不增加引用計數,目標對象釋放后自動置為?nil,常用于避免循環引用。
  • 無主引用(unowned):同樣不增加引用計數,但目標對象釋放后不會自動置為?nil,如果訪問已釋放對象會導致程序崩潰。適用于生命周期綁定但不會為?nil?的場景。

二、Swift?對象的內存布局與引用計數存儲

在理解?ARC 的底層實現時,首先要搞清楚?Swift 類對象在內存中的真實樣子。其實,每個 Swift 類對象在內存中都包含了類型信息、引用計數和實際的數據。下面我們用通俗的方式來拆解。

2.1 Swift 對象的內存結構是什么樣的?

你可以把?Swift 的類對象想象成一排盒子,每個盒子里裝著不同的信息。

假設你有這樣一個類:

class Dog {var age: Int32      // 4字節var weight: Double  // 8字節
}

當你寫?let dog?=?Dog()?時,系統會在內存里為這個對象分配一塊連續的空間。

這塊空間的內容和順序大致如下:

| 盒子1 | 盒子2 | 盒子3?| 盒子4 | 盒子5 |

|---------------|-----------------|---------|---------|---------|

| isa指針?| 引用計數/標志位 | padding | age屬性 | weight屬性 |

每個盒子裝的是什么?
  • isa指針:告訴系統“我是什么類型”,比如“我是Dog類”。用于類型識別、方法分發等。
  • 引用計數/標志位:記錄有多少人在用這個對象(ARC用來決定何時釋放內存),有時還包含一些標志位(如是否用旁表、是否已釋放等)。
  • padding:有時候為了讓后面的數據對齊,系統會加點“空盒子”。
  • age屬性:你定義的?age?變量。
  • weight屬性:你定義的 weight 變量。

2.2?偽代碼結構

struct DogObject {uintptr_t isa;         // 8字節,類型信息uint32_t refCount;     // 4字節,引用計數uint32_t padding;      // 4字節,填充int32_t age;           // 4字節,age屬性double weight;         // 8字節,weight屬性
};
2.2.1 為什么要有 padding(填充)?

因為有些數據類型(比如?Double)要求在內存中“對齊”,這樣 CPU?讀取更快。

如果前面不是8的倍數,就會加點“空盒子”讓后面的數據排整齊。

2.2.2?假設內存地址從低到高排列:

| isa | refCount | padding | age | weight |

  • isa(8字節)
  • refCount(4字節)
  • padding(4字節,為了讓 weight?對齊)
  • age(4字節)
  • weight(8字節)

2.3?引用計數的內容和格式

引用計數字段不僅僅是一個簡單的數字,通常還包含一些標志位,比如:

  • 是否已經被釋放
  • 是否正在使用旁表
  • 是否是無主引用(unowned)

這些信息一般通過位運算存儲在同一個字段里。

2.4?引用計數的存儲方式

Swift?的引用計數有兩種存儲方式:

2.4.1. 內聯計數(Inline Refcount)

大多數情況下,Swift 對象的引用計數直接存儲在對象頭部(即結構體中的?refCount?字段)。這種方式被稱為內聯計數(Inline?Refcount)。

2.4.1.1?為什么要這樣設計?
  • 高效訪問:引用計數和對象本身在同一塊內存區域,CPU?讀取和修改都非常快,無需額外尋址。
  • 空間節省:絕大多數對象的引用計數都不會很大,直接用對象頭部的幾個字節就能滿足需求,避免了為每個對象單獨分配計數空間。
  • 局部性原理:對象和其引用計數在內存上相鄰,提升了緩存命中率,進一步加快了訪問速度。
2.4.2. 旁表(Side Table)

在?Swift?的 ARC?內存管理體系中,Side?Table(旁表)是一種用于輔助管理對象引用計數和其他元數據的全局數據結構。它的本質是一個哈希表。key?是對象的內存地址,value 是該對象的引用計數及相關信息

2.4.2.1?為什么需要 Side Table?

大多數情況下,對象的引用計數直接存儲在對象頭部(內聯存儲),這樣效率最高。但有些特殊場景下,內聯存儲就不夠用了:

    • 引用計數溢出:比如一個對象被成千上萬個地方強引用,內聯計數位數不夠用。
    • 需要存儲額外信息:如弱引用(weak)、無主引用(unowned)等元數據,或者調試信息。
    • 對象參與復雜的內存管理策略:如與 Objective-C?混用時的特殊處理。

    這時,Swift?會自動將該對象的引用計數和相關信息遷移到 Side?Table 中。

    2.4.2.2?Side Table?的結構和原理

    Side?Table?可以理解為一個全局的哈希表,結構大致如下(偽代碼):

    struct SideTableEntry {int strongRefCount;   // 強引用計數int unownedRefCount;  // 無主引用計數// 可能還有其他元數據
    }std::unordered_map<void*, SideTableEntry> sideTable;
    • 查找:通過對象的內存地址查找對應的 Side?Table?Entry。
    • 操作:對 Entry?里的計數進行原子加減,保證線程安全。
    2.4.2.3?Side Table?的性能影響
    • 絕大多數對象不會用到 Side Table,只有極少數“特殊對象”才會遷移到旁表。
    • 這樣設計的好處是:常規對象的引用計數操作非常快,只有極端情況才會犧牲一點性能,換取更大的靈活性和安全性。
    2.4.2.4?Side?Table?與弱引用(weak)的關系
    • 當你在?Swift?里聲明?weak?屬性時,系統會為該對象在?Side?Table?里登記一份弱引用信息。
    • 當對象引用計數為?0、即將銷毀時,Side?Table?會負責把所有指向它的?weak?指針自動置為?nil,防止野指針。
    2.4.2.5?Side?Table 的生命周期
    • Side?Table?的?Entry?會在對象銷毀后自動清理,避免內存泄漏。
    • 你無需手動管理 Side Table,Swift?運行時會自動處理。

    Side?Table 是?Swift?ARC 內存管理體系中一個“幕后英雄”,它為極端場景下的對象引用計數和弱引用管理提供了強有力的支持。雖然大多數開發者感受不到它的存在,但正是有了?Side?Table,Swift?才能兼顧高性能與高靈活性,安全地管理各種復雜對象的生命周期。

    三、Swift 與 Objective-C?ARC 的底層差異

    在?iOS?開發中,Swift?和 Objective-C?都采用了?ARC(自動引用計數)來管理內存,但它們在底層實現上有一些重要的區別。理解這些差異,有助于我們在混合開發或排查內存問題時更加得心應手。

    3.1 引用計數的存儲方式

    • Objective-C 的對象引用計數不會存儲在對象頭部。每個?OC?對象的頭部只有一個 isa?指針(指向類的元數據)。引用計數信息存儲在一個全局的?Side?Table(旁表)中。每次?retain/release?操作,系統會通過對象地址查找?Side?Table?并更新計數。這種方式實現簡單,但頻繁查表會帶來一定性能開銷。
    • Swift 對象的引用計數更為高效。大多數情況下,Swift?會把引用計數直接存儲在對象頭部的某些比特位中(Inline Refcount)。只有在引用計數非常大或需要特殊管理時,才會像?Objective-C?一樣轉移到旁表。這種設計減少了查表次數,提高了性能。

    3.2 對象元數據結構

    • 在?Objective-C 中,每個對象的內存布局非常簡單。對象的頭部第一個字段就是一個?isa?指針。這個指針指向該對象所屬類的元數據(class?object),元數據中包含了方法列表、屬性列表等信息。通過?isa?指針,Objective-C?運行時可以實現方法查找、類型判斷等功能。
    • Swift?的類對象同樣在頭部包含一個指向元數據的指針,這個指針在?Swift?中通常被稱為metadata?pointer,有時也叫?isa。這個指針同樣位于對象內存的起始位置,即對象的第一個字段。該指針指向?Swift 的類型元數據(metadata),元數據結構比 Objective-C?更復雜,包含類型信息、協議、方法表等。這樣可以支持更多高級特性,比如泛型和協議擴展。

    3.3 引用類型的差異

    • Objective-C 只有強引用(strong)和弱引用(weak),沒有無主引用(unowned)的概念。弱引用在對象釋放后會自動置為 nil,防止野指針。
    • Swift 除了?strong?和?weak,還引入了 unowned(無主引用)。unowned?引用不會增加引用計數,但對象釋放后不會自動置為 nil。如果訪問已釋放的對象會導致崩潰。unowned 適用于生命周期綁定但不會為 nil?的場景,比如?delegate。

    3.4 ARC?的橋接與兼容

    Swift 和 Objective-C 的對象可以互相引用,ARC 機制能夠自動適配。例如,Swift?的類繼承自 NSObject?時,ARC 會自動橋接引用計數,保證內存安全。開發者在混合開發時無需手動干預,大多數情況下可以無縫協作。

    3.5 小結

    Swift 和?Objective-C 的?ARC?雖然目標一致,但底層實現各有優化。Swift?更注重性能和類型安全,采用了更高效的引用計數存儲方式,并引入了?unowned 引用類型。了解這些差異,有助于我們寫出更高效、更安全的代碼,尤其是在?Swift?與?Objective-C?混合開發時。

    四、內存管理中的底層陷阱與調試技巧

    4.1 循環引用的本質與解決方法

    在?ARC 機制下,循環引用(Retain Cycle)是最常見的內存泄漏問題。它的本質是:兩個或多個對象之間互相持有強引用,導致它們的引用計數永遠不會變為?0,內存無法被釋放。

    舉個例子:
    class Person {var pet: Pet?
    }class Pet {var owner: Person?
    }

    如果?Person?和?Pet?互相強引用對方,即使它們都不再被外部引用,也不會被釋放,造成內存泄漏。

    解決方法:

    Swift?提供了兩種弱引用方式:

    • weak(弱引用):不會增加引用計數,引用對象被釋放后自動變為?nil,適合可選類型。
    • unowned(無主引用):不會增加引用計數,引用對象被釋放后不會變為?nil,適合生命周期一致的非可選類型。

    推薦做法:

    在需要打破循環引用的地方,將一方聲明為?weak?或?unowned,比如:

    class Pet {weak var owner: Person?
    }

    這樣就能保證對象在不再被需要時正確釋放。

    4.2 閉包與?self?的循環引用

    Swift?的閉包(Closure)默認會強引用捕獲的對象,尤其是?self。如果在類中將閉包作為屬性,并在閉包內訪問?self,就會形成循環引用。

    典型場景:
    class MyClass {var closure: (() -> Void)?func setup() {closure = {self.doSomething()}}
    }
    解決方法:

    使用捕獲列表,將?self?以?weak?或?unowned?方式捕獲:

    closure = { [weak self] inself?.doSomething()
    }

    這樣可以有效避免循環引用。

    如果對閉包有疑問,可以看我的博客:Swift閉包(Closure)深入解析與底層原理

    4.3 AutoreleasePool?的底層機制

    雖然 Swift 很少直接用?@autoreleasepool,但在與 Objective-C 代碼交互或大量臨時對象創建時,AutoreleasePool?依然很重要。

    AutoreleasePool?的本質是一個棧結構,存儲了“待釋放”的對象指針。每當?pool?被銷毀或“排空”時,棧中的對象會統一調用?release,從而釋放內存。

    典型場景:

    在?for?循環中大量創建臨時對象時,可以手動包裹?@autoreleasepool,及時釋放內存,避免內存峰值過高。

    for _ in 0..<10000 {autoreleasepool {// 創建大量臨時對象}
    }

      5.4 內存泄漏與僵尸對象的調試

      Swift?和 iOS?提供了多種工具幫助我們發現和定位內存問題:

        • Xcode Instruments:使用?Leaks、Allocations 工具可以追蹤對象的分配、引用計數變化和泄漏點。
        • 靜態分析:Xcode?的?Analyze 功能可以在編譯時發現潛在的內存泄漏。
        • NSZombieEnabled:設置環境變量?NSZombieEnabled=YES,可以讓已釋放的對象變成“僵尸對象”,幫助定位野指針訪問問題。

        總結

        本文系統梳理了?Swift 與 iOS?的內存管理機制,從 ARC?的底層原理、對象內存布局、引用計數存儲方式,到?Swift?與 Objective-C?ARC 的差異,再到常見內存陷阱與調試技巧,力求讓開發者對?iOS 內存管理有更深入、全面的理解。

        Swift 的?ARC?通過編譯器插樁自動管理對象生命周期,極大簡化了開發者的工作,但其底層實現卻蘊含諸多細節與優化。例如,Swift?采用內聯引用計數與旁表(Side Table)相結合的方式,既保證了性能,又兼顧了靈活性和安全性。與?Objective-C?相比,Swift?在類型安全、引用類型(如?unowned)等方面也做了更多優化。

        在實際開發中,循環引用、閉包捕獲?self、AutoreleasePool 的使用等,都是內存管理的高頻考點。只有理解底層原理,才能在遇到復雜場景時游刃有余,寫出高效、健壯的代碼。善用 Xcode?Instruments、靜態分析、NSZombieEnabled?等工具,可以幫助我們及時發現和定位內存問題,提升代碼質量。

        總之,內存管理是每一位 iOS 開發者的必修課。希望本文能幫助你建立起系統的知識體系,少踩坑,多寫優雅高效的?Swift 代碼。如果你有更多關于 Swift 內存管理的疑問或經驗,歡迎在評論區交流討論!


        如果覺得本文對你有幫助,歡迎點贊、收藏、關注我,后續會持續分享更多?iOS?底層原理與實戰經驗!

          本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
          如若轉載,請注明出處:http://www.pswp.cn/bicheng/78863.shtml
          繁體地址,請注明出處:http://hk.pswp.cn/bicheng/78863.shtml
          英文地址,請注明出處:http://en.pswp.cn/bicheng/78863.shtml

          如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

          相關文章

          【機器學習】?碳化硅器件剩余使用壽命稀疏數據深度學習預測

          2025 年,哈爾濱工業大學的 Le Gao 等人基于物理信息深度學習(PIDL)方法,研究了在稀疏數據條件下碳化硅(SiC)MOSFET 的剩余使用壽命(RUL)預測問題,尤其關注了其在輻射環境下的可靠性。該研究團隊通過一系列實驗,采用 ??Co γ 射線作為輻射源,以 50rad/s 的劑量率照…

          Spring Boot API版本控制實踐指南

          精心整理了最新的面試資料和簡歷模板&#xff0c;有需要的可以自行獲取 點擊前往百度網盤獲取 點擊前往夸克網盤獲取 引言 在API迭代過程中&#xff0c;版本控制是保障系統兼容性的重要機制。合理的版本控制策略可以幫助開發團隊平滑過渡接口變更&#xff0c;同時支持多版本客…

          AI 語音芯片賦能血壓計,4G Cat.1語音模組重構血壓監測體驗,重新定義 “智能健康管理

          一、技術升級背景 全球老齡化進程加速與慢性病管理需求激增的背景下&#xff0c;傳統血壓計面臨三大核心痛點&#xff1a; 操作門檻高&#xff1a;老年群體對復雜按鍵操作適應性差&#xff0c;誤觸率達42%&#xff08;參考WHO數據&#xff09; 數據孤島化&#xff1a;87%的居家…

          WebServiceg工具

          WebServiceg工具 幾年前的簡單記錄一下。 /*** 調用webService 接口返回字符串* param asmxUrl 提供接口的地址 https://app.***.**.cn/Ser.asmx* param waysName 設置要調用哪個方法 上面接口打開后需要調用的方法名字 * param params 請求的參數 參數* return*/…

          qt中寫一個簡易的計算器

          以下是添加了詳細代碼注釋的版本&#xff1a; cpp #include <iostream>using namespace std;定義加法函數&#xff08;已注釋掉&#xff09; //int add(int a, int b) { // return a b; //}定義減法函數&#xff08;已注釋掉&#xff09; //int min(int a, int b) {…

          SecureCRT配置端口轉發-通過跳板機SSH到其他服務器

          在項目開發中遇到這樣一個問題&#xff0c;客戶服務器有一臺操作系統的CentOS JAVA服務器和MySQL服務器&#xff0c;本地電腦通過VPN SSH到這2臺服務器進行日常維護。最近因為修改了遠程Mysql服務器導致重啟時連不上Mysql服務器了。但是JAVA服務器可以SSH到Mysql服務器。通過各…

          vue3使其另一臺服務器上的x.html,實現x.html調用中的函數,并向其傳遞數據。

          vue3例子 <template><div><iframeload"loadIFreamSite"id"loadIframeSite":src"iframeSrc1"frameborder"0"scrolling"no"allowtransparency"true"style"width: 100%"></iframe&g…

          JQ6500語音模塊詳解(STM32)

          目錄 一、介紹 二、傳感器原理 1.原理圖 2.引腳描述 三、程序設計 main文件 usart.h文件 usart.c文件 四、實驗效果 五、資料獲取 項目分享 一、介紹 JQ6500是一種支持串口驅動的語音模塊&#xff0c;提供串口的MP3芯片&#xff0c;集成了MP3、WMV的硬解碼。同時軟…

          如何讓自己的博客可以在百度、谷歌、360上搜索到(讓自己寫的CSDN博客可以有更多的人看到)

          發現自己寫的博客文章名復制&#xff0c;然后粘貼到百度進行搜索&#xff0c;發現搜索不到自己的&#xff0c;但是會顯示其他人的CSDN博客。于是查找相關資料&#xff0c;整理出以下搜索引擎資源收錄入口&#xff0c;把自己的文章鏈接輸入進去&#xff0c;然后經過審核通過后&a…

          1. 用戶之窗

          前端開發簡介 1. 什么是前端&#xff1f; 前端開發&#xff08;Front-End Development&#xff09;是構建網站或應用 用戶直接交互界面 的技術領域&#xff0c;涵蓋&#xff1a; 視覺呈現 &#xff08;布局、色彩、動畫&#xff09;交互邏輯 &#xff08;點擊、滾動、表單&a…

          無過擬合的記憶:分析大語言模型的訓練動態

          Kushal Tirumala? Aram H. Markosyan? Luke Zettlemoyer Armen Aghajanyan Meta AI 研究 {ktirumala,amarkos,lsz,armenag}fb.com 原文鏈接&#xff1a;[2210.09262] Physics-Driven Convolutional Autoencoder Approach for CFD Data Compressions 摘要 盡管超大語言模型…

          黑馬Redis(三)黑馬點評項目

          優惠卷秒殺 一、全局唯一ID 基于Redis實現全局唯一ID的策略&#xff1a; Component RequiredArgsConstructor public class RedisIdWorker {private static final Long BEGIN_TIMESTAMP1713916800L;private static final int COUNT_BITS 32;Resourceprivate final StringRed…

          flume----初步安裝與配置

          目錄標題 **flume的簡單介紹**?flume的**核心組件**?**核心特點** **安裝部署**1&#xff09;**解壓安裝包**2&#xff09;**修改名字** **&#xff08;配置文件時&#xff0c;更方便&#xff09;****3&#xff09;??配置文件**4&#xff09;**兼容Hadoop**5&#xff09;**…

          深度整合Perforce P4+Jira+Confluence:游戲開發團隊協作工具鏈搭建指南

          現場對話 游戲開發團隊最頭疼的版本管理問題是什么&#xff1f; SVN宕機&#xff1f; Git倉庫爆炸&#xff1f; 還是美術資源管理一團亂&#xff1f; 在4月11-12日的GGS 2025全球游戲峰會上&#xff0c;Perforce中國授權合作伙伴-龍智的銷售和技術支持團隊&#xff0c;與行業…

          k8s基本概念-YAML

          YAML介紹 YAML是“YAML Aint a Markup Language” (YAML不是一種置標語言)的遞歸縮進寫,早先YAML的意思其實是:“Yet Another Markup Language”(另一種置標語言) YAML是一個類似XML、JSON的標記性語言。YAML強調以數據為中心,并不是以標識語言為重點。因而YAML本身的定義…

          ECharts散點圖-散點圖20,附視頻講解與代碼下載

          引言&#xff1a; ECharts散點圖是一種常見的數據可視化圖表類型&#xff0c;它通過在二維坐標系或其它坐標系中繪制散亂的點來展示數據之間的關系。本文將詳細介紹如何使用ECharts庫實現一個散點圖&#xff0c;包括圖表效果預覽、視頻講解及代碼下載&#xff0c;讓你輕松掌握…

          Infrared Finance:Berachain 生態的流動性支柱

          在加密市場中&#xff0c;用戶除了參與一級和二級交易&#xff0c;還有一種低門檻參與的就是空投。從 2021 年 DeFi 成為主流開始&#xff0c;空投一直都是“以小搏大”的機會&#xff0c;通過參與項目早期的鏈上交互和任務以獲取空投獎勵&#xff0c;近幾年已成為一種廣受歡迎…

          附1:深度解讀:《金融數據安全 數據安全分級指南》——數據分類的藝術專欄系列

          文章目錄 一、文件背景與意義1.1 文件背景1.2 文件意義 二、文件結構與核心內容2.1 文件結構概述2.2 核心內容解析2.2.1 范圍與適用對象2.2.2 數據安全定級目標與原則2.2.3 數據安全定級要素2.2.4 要素識別2.2.5 數據安全級別劃分 三、定級方法與流程3.1 定級流程3.2 級別變更機…

          vue mixin混入與hook

          mixin混入是 ?選項式 API?&#xff0c;在vue3-Composition API <script setup> 中無法直接使用&#xff0c;需通過 setup() 函數轉換 vue2、vue3選項式API: // mixins/mixin.js export const mixin {methods: {courseType(courseLevel) {const levelMap {1: 初級,…

          Excel如何安裝使用EPM插件并且漢化?

          Excel如何使用EPM插件 Excel如何使用EPM插件一、安裝EPM插件二、啟動EPM插件三、插件漢化設置 Excel如何使用EPM插件 一、安裝EPM插件 在安裝EPM插件時&#xff0c;若運行安裝包后出現報錯提示&#xff0c;通常是因為系統缺少 Visual Studio 2010 組件&#xff0c;需先安裝該…