iOS開發高級分享 - Unread的下拉式選單

来源:https://www.cnblogs.com/Mayday9527/archive/2019/10/31/11771032.html
-Advertisement-
Play Games

解構革命的演變 背景 2013年中期,RSS世界遭受了沉重打擊。谷歌宣佈,他們(*的*)RSS訂閱服務,[谷歌閱讀器],是被關閉了。有了它,數以百萬計的聲音突然驚恐地大叫,並突然保持沉默。 使用量下降是關閉的主要原因,儘管來自[Google Reader]用戶的巨大反應表明,該服務仍在吸引大量用戶。 ...


解構革命的演變

背景

2013年中期,RSS世界遭受了沉重打擊。谷歌宣佈,他們(*的*)RSS訂閱服務,[谷歌閱讀器],是被關閉了。有了它,數以百萬計的聲音突然驚恐地大叫,並突然保持沉默。

使用量下降是關閉的主要原因,儘管來自[Google Reader]用戶的巨大反應表明,該服務仍在吸引大量用戶。網路上充滿了對RSS和整個開放網路的未來的擔憂,儘管也有一種樂觀的感覺,那些沒有像Google這樣的巨人資源的人有機會在曾經的真空中立足一個緊密控制的市場。為[Google Reader]流亡者打造有價值的替代品。

儘管可能是喪鐘之聲,但RSS仍然活躍並且今天很好,諸如[Feedly],[Feedwrangler]和[Feedbin之類的服務]填補了[Google Reader]滅亡所留下的空白。隨之而來的是新型的現代iOS RSS閱讀器。其中之一是[Unread],這是由[Jared Sinclair]建立的,提供上述服務的令人愉快的乾凈易用客戶端。在應用商店中花費的時間很短,它已經吸引了相當多的關註者,以至於有很大的機會讓您閱讀[Unread的](http://jaredsinclair.com/unread/)這些話。

本文介紹的是[Unread]的菜單交互功能,但也涉及歷史,我們走了多遠以及如何到達這裡。

景觀

如果要在iOS上繪製新聞和內容聚合應用程式的格局,則可以在比例尺的一端繪製[Flipboard]和[Pulse](現在為LinkedIn Pulse)之類的應用程式,其中體驗不僅會推動內容消費,還會推動內容發現。這些是您想象中的應用程式,當您在周日的早晨坐下來喝咖啡(對付那些茶的人)而迷失在雜誌體驗中時,便會使用這些應用程式。

相反,我們擁有[Reeder之類的]應用程式,這些應用程式將以最有效的方式消費內容,而您用來逃避日常通勤單調或擺脫[FOMO的應用程式]。這是可能繪製[未讀的地方]。

[未讀]繼續我們討論的剋制主題[之前]。它本身的計費方式很簡單:您登錄到所選的RSS聚合帳戶並閱讀。而已。在這種斯巴達精神中,“ [未讀”]提供了為單手使用而設計和製造的體驗。

要真正瞭解[Unread](http://jaredsinclair.com/unread/)菜單交互的來源,讓我們瞭解一下Darwinistic。

演化

如果我們回顧一下被視為iOS開發圖標的應用程式[Tweetie](http://en.wikipedia.org/wiki/Tweetie),它就向我們介紹了現在司空見慣的“按需刷新”模式。Pull-to-refresh變得如此被接受,甚至可以預期,它已被Apple驗證,並被用作刷新Mail.app收件箱的預設機制。

然後是[Facebook iOS應用程式](https://itunes.apple.com/au/app/facebook/id284882215?mt=8%E2%80%8E),該[應用程式](https://itunes.apple.com/au/app/facebook/id284882215?mt=8%E2%80%8E)使導航抽屜(又名“上帝漢堡”,“漢堡地下室”和許多其他上流社會)得到了普及。自從他們在導航中刪除了它(對於聯繫人仍然保留)之後,它在整個iOS設計環境中的傳播程度使其成為一種常規的可接受模式。

快進到今天,我們有了[Unread](http://jaredsinclair.com/unread/)的菜單,這是兩種公認的傳統模式的混合物。這是兩次革命性互動的發展,為我們如何與設備互動開創了先例。

[Unread](http://jaredsinclair.com/unread/)提供了有關首次啟動的教程,該教程說明瞭如何顯示菜單,儘管有人可能會認為不需要菜單。它是其血統的產物,因此,可以依靠該血統已經建立的一定程度的期望和理解。

 解構


今年的WWDC 為開發人員帶來了許多*新的亮點*:UIKit Dynamics,T​​ext Kit,Sprite Kit和UIViewController過渡僅舉幾例。我們將使用其中的兩個來重新創建[Unread](http://jaredsinclair.com/unread/)的菜單,即UIViewController過渡和UIKit Dynamics,儘管後者我們將不直接處理。

拉動內容以顯示菜單時,我們註意到的第一件事是拉動指示器中的彈簧。強烈對比的重點,低調的閱讀界面[未讀](http://jaredsinclair.com/unread/)很難錯過。這讓人想起了(短暫的)iOS 6短暫刷新動畫<sup>[1](http://subjc.com/unread-overlay-menu#fn:1)</sup>,令人愉悅地描述了交互過程。

[過去](http://subjc.com/castro-playback-scrubber/),我們已經介紹過類似的動態行為[,](http://subjc.com/castro-playback-scrubber/)並使用UIKit Dynamics對其進行了實現,這一次,我們將加強一個抽象層。

那7參數法

Objective-C的一大功能就是命名參數。加上語言的冗長性,它提供了一種自然的方式來描述和記錄方法的意圖,儘管某些方法的長度可能會嚇到一些新開發人員。一種這樣的方法是新添加的基於UIView塊的動畫方法,`animateWithDuration:delay:usingSpringWithDamping:initialSpringVelocity:options:animations:completion:`該方法雖然不是Cocoa Touch中最長的方法,但肯定在[記分板上](https://github.com/Quotation/LongestCocoa)。

儘管存在強大的功能,但是它是一種非常簡單易用但功能強大的方法,用於向界面添加動態動畫行為,而無需提取完整的UIKit Dynamics堆棧。一些[細心的](http://iosdevweekly.com/issues/136) [讀者](https://twitter.com/followben/status/442224305657483264)註意到,[以前的帖子](http://subjc.com/castro-playback-scrubber/)中的動態行為可能已使用此方法實現,因此,將其用於按菜單換行的彈簧行為似乎是一個很好的機會。

Stretttch

如果您想將橡皮筋拉長,則橡皮筋伸展得越深,橡皮筋就會變得越薄。這種物理行為反映在[Unread](http://jaredsinclair.com/unread/)的拉動交互中,雖然它是一個很小的細節,但除非您正在尋找,否則您可能不會註意到,它增強了一種感覺,即當我們將滾動視圖拖動到其上方時`contentSize`,我們遭到抵抗。

為了在我們的實現中模仿這種行為,我們將提供一個view(`SCSpringExpandingView`),以在兩個不同的幀之間進行動畫處理。摺疊,未展開狀態的視圖框架將占據其父視圖的整個寬度,並且高度匹配,從而為我們提供一個小的正方形視圖。

- (CGRect)frameForCollapsedState
{
return CGRectMake(0.f, CGRectGetMidY(self.bounds) - (CGRectGetWidth(self.bounds) / 2.f),
CGRectGetWidth(self.bounds), CGRectGetWidth(self.bounds));
}

 

當我們將視圖拉伸到展開狀態時,我們將使用一個框架,該框架是超級視圖的高度,但只有寬度的一半。我們還將移動水平原點,以使我們的視圖保持在超級視圖的中心內。

- (CGRect)frameForExpandedState
{
return CGRectMake(CGRectGetWidth(self.bounds) / 4.f, 0.f,
CGRectGetWidth(self.bounds) / 2.f, CGRectGetHeight(self.bounds));
}

 

為了使視圖的角變圓,我們將`cornerRadius`拉伸視圖的圖層的層設置為視圖寬度的一半,使其在摺疊時呈現圓形外觀,在擴展時呈現圓形邊緣。在修改框架的寬度時,我們需要在摺疊狀態和展開狀態之間轉換時更新此值,否則其中一種情況的邊緣將變成圓角,這與視圖的寬度相反。

- (void)layoutSubviews
{
[super layoutSubviews];
self.stretchingView.layer.cornerRadius = CGRectGetMidX(self.stretchingView.bounds);
}

 

現在剩下要做的就是使用我們的新朋友長名來在兩個州之間建立動畫`animateWithDuration:delay:usingSpringWithDamping:initialSpringVelocity:options:animations:completion:`。

我們已經看到了最前,這種方法使用的參數,但讓我們快速瀏覽一下這兩個事關對我們來說,`usingSpringWithDamping`和`initialSpringVelocity`。

`usingSpringWithDamping``CGFloat`從0.0到1.0之間取一個值,並從物理意義上確定彈簧的強度。接近1.0的值將增加彈簧的強度並導致低振動。接近0.0的值會削弱彈簧的強度並導致高振動。

`initialSpringVelocity`也要接受,`CGFloat`但是傳遞的值將相對於動畫過程中經過的距離。值1.0表示在1秒鐘內遍歷的動畫距離,而值0.5表示在1秒鐘內遍歷的動畫距離的一半。

儘管這些參數與物理屬性相對應,但在大多數情況下*還是感覺良好,請這樣做*。

[UIView animateWithDuration:0.5f
delay:0.0f
usingSpringWithDamping:0.4f
initialSpringVelocity:0.5f
options:UIViewAnimationOptionBeginFromCurrentState
animations:^{
self.stretchingView.frame = [self frameForExpandedState];
} completion:NULL];

 

就是這樣。只需一個方法調用和一些波動的魔術數字,我們就可以利用iOS 7中UIKit的動態基礎。

三人一族

現在,我們已經創建了`SCSpringExpandingView`,我們需要創建一個包含三個`SCSpringExpandingView`s 的視圖。叫它`SCDragAffordanceView`。

的基本工作`SCDragAffordanceView`是佈局三個`SCSpringExpandingView`,並提供一個介面,我們可以通過該介面進行下拉菜單交互。

要佈局`SCSpringExpandingView`,我們將覆蓋`layoutSubviews`並對齊每個視圖框架,使其在邊界上等距分佈。

- (void)layoutSubviews
{
[super layoutSubviews];

CGFloat interItemSpace = CGRectGetWidth(self.bounds) / self.springExpandViews.count;

NSInteger index = 0;
for (SCSpringExpandView *springExpandView in self.springExpandViews)
{
springExpandView.frame = CGRectMake(interItemSpace * index, 0.f, 4.f,
CGRectGetHeight(self.bounds));
index++;
}
}

 

現在我們已經佈局了視圖,當有人調用該`setProgress:`方法時,我們將需要更新它們。如果回頭看[未讀](http://jaredsinclair.com/unread/),我們可以看到每個彈簧視圖的三個不同狀態:摺疊,展開和完成。我們已經提到了前兩個,但最後一個是指示“菜單拉動”交互已經達到釋放點將觸發顯示菜單的點。

為了實現這一點,我們將遍歷三個`SCSpringExpandingView`s並主要基於`progress`傳入的是大於還是等於1.0來更新每個s的顏色,然後基於s 是否`progress`足夠大以使視圖可以擴展。

- (void)setProgress:(CGFloat)progress
{
_progress = progress;

CGFloat progressInterval = 1.0f / self.springExpandViews.count;

NSInteger index = 0;
for (SCSpringExpandView *springExpandView in self.springExpandViews)
{
BOOL expanded = ((index * progressInterval) + progressInterval < progress);

if (progress >= 1.f)
{
[springExpandView setColor:[UIColor redColor]];
}
else if (expanded)
{
[springExpandView setColor:[UIColor blackColor]];
}
else
{
[springExpandView setColor:[UIColor grayColor]];
}

[springExpandView setExpanded:expanded animated:YES];
index++;
}
}

 

現在,我們已經涵蓋了一些新的熱點,讓我們繞過一條人跡罕至的道路。

嵌套的UIScrollView

問任何iOS開發者,他們會告訴你,嵌套的滾動視圖*的*用戶界面元素,以至於蘋果已經[專門有一章](https://developer.apple.com/library/ios/documentation/windowsviews/conceptual/UIScrollView_pg/NestedScrollViews/NestedScrollViews.html)他們的`UIScrollView`節目指南的話題。我們一起研究了這麼多創新的iOS界面而沒有提及它們是犯罪行為。

對於我們的示例內容,我們將通過展示一些`UITextView`吸引人的Lorem Ipsum ,該類在iOS 7的全新改版中獲得了一些TextKit的喜愛。儘管我們不會在此條目中涵蓋任何新的API,但有興趣的人應該查看[objc.io上](http://www.objc.io/issue-5/getting-to-know-textkit.html)的[精彩文章](http://www.objc.io/issue-5/getting-to-know-textkit.html)。相反,我們只需要記住那`UITextView`是強大的子類`UIScrollView`。

我們希望我們`SCDragAffordanceView`始終在您身邊,準備展示我們的菜單。要考慮的一個選擇是將其添加為我們的子視圖`UITextView`基礎上,並修改其垂直原點`contentOffset`我們的`UITextView`,但這種重載我們的責任`UITextView`不僅僅是顯示文本,只是*感覺*有點不對勁。

相反,讓我們創建一個單獨的實例`UIScrollView`,我們的`UITextView`和`SCDragAffordanceView`將被添加為的子視圖。

self.enclosingScrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
self.enclosingScrollView.alwaysBounceHorizontal = YES;
self.enclosingScrollView.delegate = self;
[self.view addSubview:self.enclosingScrollView];

 

此處的關鍵行設置`alwaysBounceHorizontal`為`YES`。現在,無論`contentSize`滾動視圖如何,水平拖動始終將以預期的阻力繼續超出界限。

如果我們嵌套`UITextView`的水平內容大小沒有超出其範圍,那麼我們將獲得僅一個的效果`UIScrollView`,同時在代碼中分離關註點。

我們還希望成為滾動視圖的委托,以便我們檢測到滾動視圖被拖動並相應地更新`SCDragAffordanceView`的進度。

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (scrollView.isDragging)
{
self.menuDragAffordanceView.progress = scrollView.contentOffset.x /
CGRectGetWidth(self.menuDragAffordanceView.bounds);
}
}

 

最後,當我們收到`scrollViewDidEndDragging:willDecelerate:`委托回調時,我們將使用在`scrollViewDidScroll:`回調中計算出的相同進度來確定是否顯示菜單視圖控制器。如果沒有,我們將進度設置回0.0。

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
if (self.menuDragAffordanceView.progress >= 1.f)
{
[self presentViewController:self.menuViewController
animated:YES
completion:NULL];
}
else
{
self.menuDragAffordanceView.progress = 0.f;
}
}

 

有了塵土飛揚的道路,讓我們陷入下一個iOS 7熱點問題。

UIViewControllerTransitioningDelegate

版本有什麼不同。如果這篇文章是在iOS 7之前編寫的,那將是一件漫長而需要註意的事情。以前,如果您希望使用“ [未讀](http://jaredsinclair.com/unread/) ”的下拉菜單等行為,則必須將視圖插入當前視圖控制器,視窗或其他類似臭味的行為之上。雖然這將為您帶來理想的效果,但總感覺好像您違反了框架的要求。

值得慶幸的是,在iOS 7中,Apple註意到了這種模式的出現,並從開發人員社區得到了另一個提示,它提供了一種乾凈,經過批准的方法,可以使用一組最少的協議來實現這一目標。現在,您可以通過實現`UIViewControllerTransitioningDelegate`協議來定義自定義動畫和視圖控制器之間的互動式過渡。

該`UIViewControllerTransitioningDelegate`協議聲明瞭一些方法,這些方法使您可以返回動畫師對象,這些對象定義了視圖過渡的三個階段之一:呈現,關閉和交互。我們的自定義過渡將定義展示和發佈階段。

在我們的視圖控制器中,我們將聲明我們遵守`UIViewControllerTransitioningDelegate`協議並實現我們關心的兩種方法`animationControllerForPresentedController:presentingController:sourceController:`和`animationControllerForDismissedController:`。

現在,我們為自定義視圖控制器過渡提供了回調,我們需要一個視圖控制器來呈現。[未讀](http://jaredsinclair.com/unread/)的整潔菜單項動畫不在本文討論範圍之內,因此對於我們而言,我們只需要創建一個視圖控制器(`SCMenuViewController`),即可在觸髮菜單交互時顯示該視圖控制器。

self.menuViewController = [[SCMenuViewController alloc] initWithNibName:nil bundle:nil];

 

創建此類的實例後,我們需要將其`transitionDelegate`設置為我們的視圖控制器,並將其設置為`modalPresentationStyle`,`UIModalPresentationCustom`以便`transitioningDelegate`在出現時可以回調它。

self.menuViewController.modalPresentationStyle = UIModalPresentationCustom;
self.menuViewController.transitioningDelegate = self;

 

現在,當我們展示菜單視圖控制器時,它將回調到其`transitioningDelegate`(我們的視圖控制器)以請求展示`UIViewControllerAnimatedTransitioning`動畫器對象。

## UIViewControllerAnimatedTransitioning

為了向菜單視圖控制器提供動畫對象,我們將從創建一個普通的舊NSObject子類開始`SCOverlayPresentTransition`,並聲明其符合`UIViewControllerAnimatedTransitioning`協議。在`animationControllerForPresentedController:presentingController:sourceController:`委托回調中,我們將創建`SCOverlayPresentTransition`對象的實例並返回它。

- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
{
return [[SCOverlayPresentTransition alloc] init];
}

對於解雇動畫,我們將創建另一個名為NSObject的子類`SCOverlayDismissTransition`,併在收到`animationControllerForDismissedController:`委托回調時提供其實例。

- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed
{
return [[SCOverlayDismissTransition alloc] init];
}

我們現在和罷免過渡對象的實現包括兩種方法,`transitionDuration:`和`animateTransition:`。`transitionDuration:`您可能已經猜到的方法只是請求`NSTimeInterval`來指定動畫的持續時間。該`animateTransition:`是在過渡的實質性工作。

該`animateTransition:`方法的唯一參數是符合`UIViewControllerContextTransitioning`協議的對象。從該對象中,我們可以提取驅動動畫所需的對象和信息,包括過渡中涉及的視圖控制器。它還提供了一些方法,用於通知框架我們已完成過渡。

UIViewController *presentingViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *overlayViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

一旦有了呈現和呈現的視圖控制器,就需要將它們的視圖添加為過渡的容器視圖的子視圖,以便它們都在動畫期間出現。

UIView *containerView = [transitionContext containerView];
[containerView addSubview:presentingViewController.view];
[containerView addSubview:overlayViewController.view];

當前過渡的最後一部分是簡單地為視圖設置動畫,但是我們願意,然後通知`transitionContext`對象我們是否已成功完成過渡。

overlayViewController.view.alpha = 0.f;
NSTimeInterval transitionDuration = [self transitionDuration:transitionContext];
[UIView animateWithDuration:transitionDuration
animations:^{
overlayViewController.view.alpha = 0.9f;
} completion:^(BOOL finished) {
BOOL transitionWasCancelled = [transitionContext transitionWasCancelled];
[transitionContext completeTransition:transitionWasCancelled == NO];
}];

在`SCOverlayDismissTransition`將遵循基本上相同的過程,儘管是在相反的方向。

現在,當我們顯示菜單視圖控制器時,它將使用我們的自定義過渡,將呈現視圖控制器的視圖保持在視圖層次結構中。

 閉幕


當我們即將迎來iOS App Store成立6周年之際,其應用前景已令人嘆為觀止。我們已經可以將應用視為經典的想法表明瞭它的移動速度。每年,開發人員都會獲得一系列新的玩具,以用來構建出色的應用程式,但仍然有可觀的空間`UIScrollView`。

您可以[在GitHub上簽出該項目](https://github.com/subjc/SubjectiveCUnreadMenu)。

1. 如果你感到懷舊的令人心醉的iOS 6天,還有的iOS 6中拉來刷新控制的一大克隆[GitHub上](https://github.com/Sephiroth87/ODRefreshControl) [↩](http://subjc.com/unread-overlay-menu#fnref:1)

另外,如果你想一起進階,不妨添加一下交流群[1012951431],選擇加入一起交流,一起學習。期待你的加入!(進群可領取學習禮包)

翻譯地址:[http://subjc.com/unread-overlay-menu#article]

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在redhat6.5上安裝Oracle時,最後使用oracle用戶執行runInstaller 報錯如下,無法連接到安裝有xmanager的windows伺服器,也就無法圖形化安裝oracle 經過百度找到一個靠譜的解決方法,實驗成功。如下首先檢查伺服器是否安裝了xdpyinfo 切換到root用戶 ...
  • 範式是具有最小冗餘的表結構。 三範式具體如下: 1.第一範式(1NF):欄位都是不可再分的; 第一範式的目標是確保每列的原子性:如果每列都是不可再分的最小數據單元,則滿足第一範式(1NF); 2.第二範式(2NF):每個表只描述一件事情; 首先滿足第一範式,並且表中非主鍵屬性必須完全要依賴於主鍵屬性 ...
  • 前置操作 創建maven工程,修改pom.xml文件: 在resources添加一個file:log4j.properties: API操作 HDFS的命令和linux極其相似,可以類比記憶,在這裡列出一些java api操作: I/O流操作 上面的API操作 HDFS系統都是框架封裝好的,如果我們 ...
  • ORA-12154:tns:could not resolve the connect identifier specified ...
  • [TOC] 單表操作 分組 group by 分組指的是:將所有記錄按照某個相同欄位進行歸類,比如針對員工信息表的職位分組,或者按照性別進行分組 用法 having having是對group by後的數據進行二次篩選 order by 升序 降序 limit 限制查詢記錄的個數 offset 表示 ...
  • elasticsearch外網訪問9200埠失敗,bootstrap checks failed,the default discovery settings are unsuitable for production use; at least one of [discovery.seed_ho ...
  • 什麼時候調用imageRectForContentRect,titleRectForContentRect,contentRectForBounds,imageRectForContentRect,也是調用時機。首先梳理清楚幾個佈局順序: ...
  • 第三部分:iOS開發底層原理 1、Objective C對象模型 1.1 isa指針 NSObject.h部分代碼: objc.h部分代碼: 每個對象都有一個名為isa的指針,指向該對象的類 isa指針指向流程圖如下: 如果把類看成一個C語言的結構體(struct),isa指針就是這個結構體的第一個 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...