主頁 > 移動端開發 > Objective-C編程 — 并行編程

Objective-C編程 — 并行編程

2020-09-11 03:16:15 移動端開發

多執行緒

執行緒的基本概念

執行緒 (thread)是行程(process)A 內假想的持有 CPU 使用權的執行單位,一般情況下,一個行程 只有一個執行緒,但也可以創建多個執行緒并在行程中并行執行,應用在執行某一處理的同時,還可以 接收 GUI 的輸入,

使用多執行緒的程式稱為 多執行緒 (multithread)運行,從程式開始執行時就運行的執行緒稱為 主執行緒 , 除此之外,之后生成的執行緒稱為次執行緒(secondary thread)或子執行緒(subthread),

創建執行緒時,創建方的執行緒為父執行緒,被創建方的執行緒為子執行緒,父執行緒和子執行緒并行執行各
自的處理,但父執行緒可以等到子執行緒執行終止后與其會合(join),而另一方面,在執行緒被創建后, 也可以切斷父子關系指定它們不進行會合,該操作稱為 分離 (detach),這里所說的 NSThread 就是在 分離狀態下創建執行緒,

一個開發者,有一個學習的氛圍跟一個交流圈子特別重要,這是一個我的iOS交流群:1012951431, 分享BAT,阿里面試題、面試經驗,討論技術, 大家一起交流學習成長!希望幫助開發者少走彎路,

由于被創建的執行緒共享行程的地址空間,所以能夠自由訪問行程的空間變數,多執行緒訪問的變數稱為 共享變數 (shared variable) ,共享變數大多為全域變數或靜態變數,但因為地址空間是共享的, 所以理論上所有記憶體區域都可以稱為共享變數,

如果多執行緒胡亂訪問共享變數,那么就不能保證變數值的正確性,所以有時就需要按照一定的 規則使多執行緒可以協調動作,此時就必須執行執行緒間 互斥 (或者排他控制,mutual exclusion)(見 , 各個執行緒都分配有堆疊且獨立進行管理,基本上不能訪問其他執行緒的堆疊內的變數(自動變數),通 過遵守這樣的編程方式,就可以自由訪問方法或函式的自動變數,而且不用擔心互斥,

使用參考計數管理方式時,為了使物件之間解耦合,子執行緒方需要創建與父執行緒不同的自動釋
放池來管理,使用垃圾回收時不需要這樣,

A 任務(task)這一名稱也被用來表示與行程同樣的概念,在蘋果公司的檔案“Multithreading Programming Topics”中, 可以包含多執行緒的程式的執行單元稱為行程,而任務則被用來抽象地表示應該進行的作業,

執行緒安全

多個執行緒同時操作某個實體時,如果沒有得到錯誤結果或實體沒有包含不正確的狀態,那么該 類就稱為 執行緒安全 (thread-safe),結果不能保證時,則稱為非執行緒安全或執行緒不安全(thread-unsafe),

一般情況下,常數物件是執行緒安全的,變數物件不是執行緒安全的,常數物件可以在執行緒間安全
地傳遞,但對變數物件共享時,需要恰當地執行互斥或同步切換,

需要注意的是 C 語言的函式,就現狀來看,BSD 函式的大部分,例如 printf() 等,都不是執行緒安 全的,

注意點

在某些情況下,使用多執行緒可以使處理高速化、實作易于使用的介面、使實作更簡單等,但并 不是說使用多執行緒后就一定會得到這些優點,

要想使多執行緒程式不出錯且高效執行,并行編程的知識必不可少,執行緒間的任務分配和資訊交 換、共享資源的互斥、與 GUI 的互動及影片顯示等,在使用時都要特別小心,

一般情況下,自己實作多執行緒程式是很困難的,而且也容易埋下高隱患,稍有差錯或設計失誤,
多 線 程 便 不 能 發 揮 效 果, 甚 至 還 會 導 致 未 知 原 因 的 釋 放 或 異 常 終 止, 使 用 19.3 節 中 介 紹 的 NSOperation,雖然可以較容易地實作多執行緒程式,但是也必須掌握執行緒動作、互斥等相關知識,不 能適應這些的讀者建議去參考一下并行編程的相關書籍,

而且,很多多執行緒中遇見的問題都可以通過 NSTimer 類或延遲訊息發送(參考 15.1 節)來解決, 大家也不妨嘗試一下用這些方法來解決相關問題,

使用 NSThread創建執行緒

Foundation 框架中提供了 NSThread 類來創建并控制執行緒,該類的介面在 Foundation/NSThread.h 中宣告,

創建新執行緒需要執行下面的類方法,

+?(void)?detachNewThreadSelector:?(SEL)?aSelector

toTarget:?(id)?aTarget

withObject: (id)?anArgument

對 物件 aTarget 呼叫方法創建新執行緒并執行,選擇器 aSelector 必須是僅獲取一個 id 型別引數且回傳值 為 void 的執行方法(參考 8.2 節),

指定的方法執行結束后,執行緒也隨之終止,執行緒從最初就被執行了分離,所以終止時沒有和父 執行緒會合,當主執行緒終止時,包含子執行緒的程式也全部隨之終止,

使用參考計數管理(手動及 ARC)時,有時需要執行的方法自身來管理自動釋放池,此外,參 數 aTarget 和 anArgument 中指定的物件也與執行緒同時存在,即在創建執行緒時被保存,在執行緒終止時 被釋放, 使用下述的 NSApplication 類中的方法也能創建執行緒,該方法使用上面的方法,而且在使用參考 計數管理時還會創建執行緒的自動釋放池,

+?(void)?detachDrawingThread:?(SEL)?selector

toTarget:?(id)?target

withObject:?(id)?argument

創建新執行緒并執行的方法除了上述方法還有很多,本書中不再一一介紹,其他方法請參考 NSThread、NSObject 的參考檔案,

程式可以呼叫 NSThread 類方法來確認是否是多執行緒運行, +?(BOOL)?isMultiThreaded   多個執行緒并行執行時或者只有主執行緒在執行時,只要在此之前已經創建了執行緒,則回傳 YES,

當前執行緒

一個執行緒稱自身為 當前執行緒 (current thread),區別于其他執行緒,

子執行緒將創建時指定的方法執行完后也會隨之終止,但也可以中途終止,為此,可以使用當前 執行緒(執行緒自身)來執行下一個 NSThread 類方法,但是,使用參考計數管理時,終止前一定要釋放 自動釋放池, +?(void)?exit

使用下述方法獲得表示執行緒的 NSThread 實體,

+?(NSThread?*)?currentThread

獲 得表示當前執行緒的 NSThread 實體,

+?(NSThread?*)?mainThread

獲 得表示主執行緒的NSThread實體,查看當前執行緒是否為主執行緒時,可以使用類方法isMainThread?, 每個執行緒都可以持有一個該執行緒固有的 NSMutableDictionary 型別的字典,向 NSThread 實體發 送下面的訊息類就可以取得字典,

-?(NSMutableDictionary?*)?threadDictionary

可以使當前執行緒僅被中斷幾秒,為此,可在當前執行緒中執行下面的類方法,引數為實數, +?(void) sleepForTimeInterval: (NSTimeInterval)?ti

也可以使執行緒在某一時刻前中斷,這時可采用下面的類方法,引數是表示日期的類 NSDate 實體, +?(void)?sleepUntilDate:(NSDate?*)?aDate

如果要使執行緒到某個條件成立前一直保持休眠狀態,則要使用下一章節介紹的鎖,

GUI應用和執行緒

在使用 GUI 的應用中,事件處理和繪圖等大部分處理中執行緒都發揮了重要作用,也可以在子線 程中創建表單,或分擔部分繪圖功能,但要注意避免競爭或記憶體泄漏,詳情請參考相關檔案,

GUI 應用中有較容易的方法來使用執行緒,即將 GUI 相關的時間處理或繪圖集中在主執行緒中進行,
使用下面的方法,就可以從子執行緒依賴主執行緒中的方法處理,該方法為 NSOjbect 的范疇,在頭檔案 Foundation/NSThread.h 中宣告,

-?(void)?performSelectorOnMainThread: (SEL)?aSelector

withObject: (id)?arg

waitUntilDone: (BOOL)?wait

選 擇器 aSelector 和引數 arg 中指定的方法的執行依賴于主執行緒,wait 為 YES 時,當前執行緒會一直等待 至執行結束,主執行緒中必須有事件回圈(運行回路),

互斥

需要互斥的例子

在多執行緒環境中,無論哪個函式或方法都可以在多執行緒中同時執行,但是,在使用共享變數時, 或者在執行檔案輸出或繪圖等的情況下,多執行緒同時執行就可能得到奇怪的結果,

例如,使用整數全域變數 totalNumber 來累加所處理的資料的個數,為了執行下面的加法計算, 

在多執行緒環境中執行該方法會得到什么結果呢?

-?(void)addNumber:(NSIngeger)n

{

totalNumber?+=?n;

} 在 OS 功能支持下,執行緒在運行的程序中會時而得到 CPU 的執行權,時而被掛起執行權,2 個 方法的執行情況如圖 19-1 中所示,在該圖中,執行緒 1 將新計算的值保存在暫存器時掛起 CPU 執行 權,同時執行緒 2 開始執行方法,即使 CPU 的執行權被掛起,暫存器的值也仍然可以被保存,所以各 執行緒都能正常處理,但是,由于執行緒 2 寫入的值消失了,因此整體上看,這偏離了我們期待的結果, 原因是值的讀取、更新、寫入操作被多執行緒同時執行了,

 

在圖 19-1 的例子中,我們將同時只可以由一個執行緒占有并執行的代碼部分稱為臨界區(critical section),或稱為危險區,互斥的目的就是限制可以在臨界區執行的執行緒,

為了使多個執行緒間可以相互排斥地使用全域變數等共享資源,可以使用NSLock?類,該類的實體 也就是可以調整多執行緒行為的 信號量 (semaphore)或者 互斥型信號量 (mutual exclusion semaphore), Cocoa 環境中也稱為 鎖 (lock),

鎖具有每次只允許單個執行緒獲得并使用的性質,獲得鎖稱為“加鎖”,釋放鎖稱為“解鎖”,

鎖和普通的實體一樣,使用類方法alloc?和初始化器init?來創建并初始化,但是,鎖應該在程 序開始在多執行緒執行前創建,

NSLock?*countLock?=?[[NSLock?alloc]?init];

獲得鎖的方法和釋放(unlock)鎖的方法都在協議 NSLocking 中定義,

-?(void)?lock   如果鎖正被使用,則執行緒進入休眠狀態,

如果鎖沒有被使用,則將鎖的狀態變為正被使用,執行緒繼續執行,

-?(void)?unlock   將 鎖置為沒有在被使用,此時如果有等待該鎖資源的正在休眠的執行緒,則將其喚醒,

在上例中,使用鎖后會產生如下效果,但需要預先創建 NSLock 的實體 aLock,在該代碼中,從 某執行緒執行 A 取得鎖到該執行緒執行 B 釋放鎖期間,其他執行緒在執行 A 時將進入休眠狀態,不能執 行臨界區代碼,鎖被釋放后,在執行 A 時休眠的執行緒中選擇一個執行緒,該執行緒在取得鎖后進入臨界 區執行,

-?(void)addNumber:(NSIngeger)n { ????[aLock?lock];? ───────────────────────────────────────── ?A ????totalNumber?+=?n;????//?臨界區 ????[aLock?unlock];?──────────────────────────────────────── ?B }

某個鎖被lock?后,必須執行一次unlock?,而且lock?和unlock?必須在同一個執行緒執行 A,

下面來看另外一個使用鎖的例子,考慮一下全域變數值自增時回傳其結果的方法,多執行緒執行 時,全域變數 theCount 若想正確地自增,就需要使用鎖 countLock 來管理,

可以采用如下定義, 

 

A lock 和 unlock 必須在同一個執行緒中執行,因為 NSLock 是基于 POSIX 執行緒實作的,

死鎖

執行緒和鎖的關系必須在設計之初就經過仔細的考慮,如果錯誤地使用鎖,不但不能按照預期執 行互斥,還可能使多個執行緒陷入到不能執行的狀態,即死鎖(deadlock)狀態,

死鎖就是多執行緒(或行程)永遠在等待一個不可能實作的條件而無法繼續執行,如圖 19-2 所示, 

 

執行緒 1 占有檔案 A 并正在進行處理,途中又需要占有檔案 B,而另一方面,執行緒 2 占有著檔案 B,途中又需要占有檔案 A,大家不妨設想一下,如果執行緒 1 和執行緒 2 同時執行到了圖中的箭頭位置 會怎么樣呢?執行緒 1 為了處理檔案 B 想要獲得鎖 lockForB,但是它已經被執行緒 2 獲得,同樣,執行緒 2 想要獲得的鎖 lockForA 也被執行緒 1 占有著,這種情況下,執行緒 1 和執行緒 2 就會同時進入休眠狀態, 而且雙方都不能跳出該狀態,

像這樣,當多個執行緒互相等待資源的釋放時,就非常容易出現死鎖現象,有時是多個執行緒相干預,有時則是一個執行緒因為自己需要獲得鎖而進入休眠狀態,此外,由于多數情況下各個執行緒本身 并沒有錯誤處理,而且死鎖又隨時可能發生,因此追究原因就非常困難,也不能排除導致程式 bug 的可能,

嘗試獲得鎖

NSLock 類不僅能獲得鎖和釋放鎖,還有檢查是否能獲得鎖的功能,利用這些功能,就可以在不 能獲得鎖時進行其他處理,

-?(BOOL)?tryLock

用 接收器嘗試獲得某個鎖,如果可以取得該鎖則回傳 YES,不能獲得時,與lock?處理不同,執行緒沒 有進入休眠狀態,而是直接回傳 NO 并繼續執行,

該方法十分便利,但要確保只能在可以獲得鎖時才執行 unlock,創建程式時必須注意這一點,

條件鎖

類 NSConditionLock 稱為 條件鎖 (condition lock),該鎖持有整數值,根據該值可以獲得鎖或者 等待,

  • (id) initWithCondition: (NSInteger) condition

NSConditionLock 實體初始化,設定引數 condition 指定的值,

NSCondtionLock 的指定初始化器,

  • (NSInteger) condition

此時回傳鎖中設定的值,

  • (void) lockWhenCondition: (NSInteger) condition

如果鎖正在被使用,則執行緒進入休眠狀態,

鎖不在被使用時,如果鎖值和引數 condition 的值一致,則將鎖狀態修改為正在被使用,然后繼續執 行,如果不一致,則執行緒進入休眠狀態,

  • (void) unlockWithCondition: (NSInteger) condition

在鎖中設定引數 condition 指定的值,將鎖設定為不在被使用,此時如果有等待獲得該鎖且處于休眠 狀態的執行緒,則將其喚醒,

  • (BOOL) tryLockWhenCondition: (NSInteger) condition

尚未使用鎖且鎖值與引數 condition 相同時,獲得鎖并回傳 YES,不能獲得鎖時也不進入休眠狀態, 而是回傳 NO,執行緒繼續執行,

使用方法 lock 、 unlock 或 tryLock 都可以獲得鎖和釋放鎖,而且無需關心鎖的值,

然而,由于 NSConditionLock 實體可以持有的狀態為整數型,所以事先用列舉常數或宏定義就可 以了,如果只使用 0 或 1,不僅不容易理解,也可能造成錯誤,

NSRecursiveLock

某執行緒獲得鎖后,到該執行緒釋放鎖期間,想要獲得該鎖的執行緒就會進入休眠,使用類 NSLock 的 鎖時,如果已經獲得鎖的執行緒在沒有釋放它的情況下還想再次獲得該鎖,該執行緒也會進入休眠狀態, 但是,由于沒有從休眠狀態喚醒的執行緒,所以這就是死鎖,下面是一個簡單的例子,這段代碼不會 執行,

[aLock?lock];

[aLock?lock];??????//?這里發生死鎖

[aLock?unlock];

[aLock?unlock];

解決這種情況可以使用 NSRecursiveLock?類的鎖,擁有鎖的執行緒即使多次獲得同一個鎖也不會 進入死鎖,但是,其他執行緒當然也不能獲得該鎖,獲得次數和釋放次數一致時,鎖就會被釋放,

NSRecursiveLock 類的鎖使用起來十分方便,但排除被重復加鎖的情況,用 NSLock 來重新記述 
的話,性能則會更好,

@synchronized

程式內的塊可以指定為不被多執行緒同時使用,為此可以使用 @synchronized 編譯符,如下所示,

 

通過使用該段代碼,運行時系統就可以創建排斥地執行該代碼塊的鎖(mutex),引數 obj 通常指 定為該互斥鎖要保護的物件,obj 自己不需要是鎖物件,

執行緒如果要執行該代碼塊,首先會嘗試獲得鎖,如果能獲得鎖則可以執行塊內代碼,塊執行結 束時一并釋放鎖,使用 break 或 return 從塊內跳出到塊外時也被視作塊執行終止,而且,在塊內發生 例外時,運行時系統會捕捉例外并釋放塊,

@synchronized 的引數物件決定對應的塊,所以, 同一個物件引數的 @synchronized 塊如果有多 個,則不可以同時執行,

根據引數的選擇方法的不同,@synchronized 會在并行執行的受限物件和可以執行的普通物件之 間動態切換,下面展示 @synchronized 引數的使用示例,

(a) 是指定只能單獨存在的物件時的情景,同一個物件在其他地方也作為 @synchronized 的引數 使用時,所有這些塊不能同時執行,(b) 也是一樣,因為限制了引數的使用范圍,互斥物件顯然只能 是該方法內的塊,

(c) 是各個實體互斥的例子,一個實體一次只能執行一個執行緒,同一類別的其他實體則多個執行緒可以同時存在,(d) 在引數物件可能在多個地方更改的情況下有效,但以同樣方式使用該物件的所有 場所中都需要按照該方式書寫,否則就沒有任何意義,

而且,也可以按照 (e) 的方式書寫,此外還可以指定類物件,或者使用訊息選擇器(隱藏引數的 _cmd)來指定方法等,不過一般情況下,為互斥的物件使用專門的鎖物件是比較可靠的方法,

 

使用 @synchronized 塊時,加鎖和解鎖必須成對進行,因此可以防止加鎖后忘記解鎖這種問題的 發生,和普通的鎖相比,復雜的并行演算法的書寫會較為復雜,但多數情況下都會使互斥更容易理解,
另外,如果你想一起進階,不妨添加一下交流群1012951431,選擇加入一起交流,一起學習,期待你的加入!

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/4164.html

標籤:iOS

上一篇:iOS閃退日志的收集和決議

下一篇:iOS性能優化

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:40:31 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:40:11 more
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:39:36 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:39:13 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:16:23 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:16:15 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:15:46 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:14:53 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:14:08 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:08:34 more