iOS自動佈局框架-Masonry詳解

来源:http://www.cnblogs.com/lurenq/archive/2017/10/19/7693214.html
-Advertisement-
Play Games

首先,在正式使用Masonry之前,我們先來看看在xib中我們是如何使用AutoLayout 從圖中我們可以看出,只要設置相應得局限,控制好父視圖與子視圖之間的關係就應該很ok的拖出你需要的需求。這裡就不詳細講解具體拖拽的方法..... 然後,我們按著上圖的屬性來看看如何簡單得使用Masonry 首 ...


首先,在正式使用Masonry之前,我們先來看看在xib中我們是如何使用AutoLayout


 
 

從圖中我們可以看出,只要設置相應得局限,控制好父視圖與子視圖之間的關係就應該很ok的拖出你需要的需求。這裡就不詳細講解具體拖拽的方法.....

然後,我們按著上圖的屬性來看看如何簡單得使用Masonry

目前iOS開發中大多數頁面都已經開始使用Interface Builder的方式進行UI開發了,但是在一些變化比較複雜的頁面,還是需要通過代碼來進行UI開發的。而且有很多比較老的項目,本身就還在採用純代碼的方式進行開發。

而現在iPhone和iPad屏幕尺寸越來越多,雖然開發者只需要根據屏幕點進行開發,而不需要基於像素點進行UI開發。但如果在項目中根據不同屏幕尺寸進行各種判斷,寫死坐標的話,這樣開發起來是很吃力的。

所以一般用純代碼開發UI的話,一般都是配合一些自動化佈局的框架進行屏幕適配。蘋果為我們提供的適配框架有:VFL、UIViewAutoresizing、Auto Layout、Size Classes等。

其中Auto Layout是使用頻率最高的佈局框架,但是其也有弊端。就是在使用UILayoutConstraint的時候,會發現代碼量很多,而且大多都是重覆性的代碼,以至於好多人都不想用這個框架。

後來Github上的出現了基於UILayoutConstraint封裝的第三方佈局框架Masonry,Masonry使用起來非常方便,本篇文章就詳細講一下Masonry的使用。

Masonry介紹

這篇文章只是簡單介紹Masonry,以及Masonry的使用,並且會舉一些例子出來。但並不會涉及到Masonry的內部實現,以後會專門寫篇文章來介紹其內部實現原理,包括順便講一下鏈式語法。

什麼是Masonry

Masonry是一個對系統NSLayoutConstraint進行封裝的第三方自動佈局框架,採用鏈式編程的方式提供給開發者API。系統AutoLayout支持的操作,Masonry都支持,相比系統API功能來說,Masonry是有過之而無不及。

Masonry採取了鏈式編程的方式,代碼理解起來非常清晰易懂,而且寫完之後代碼量看起來非常少。之前用NSLayoutConstraint寫很多代碼才能實現的佈局,用Masonry最少一行代碼就可以搞定。下麵看到Masonry的代碼就會發現,太簡單易懂了。

Masonry是同時支持Mac和iOS兩個平臺的,在這兩個平臺上都可以使用Masonry進行自動佈局。我們可以從MASUtilities.h文件中,看到下麵的定義,這就是Masonry通過巨集定義的方式,區分兩個平臺獨有的一些關鍵字。

18.png

Github地址:https://github.com/SnapKit/Masonry

集成方式

Masonry支持CocoaPods,可以直接通過podfile文件進行集成,需要在CocoaPods中添加下麵代碼:

1 pod 'Masonry'

Masonry學習建議

在UI開發中,純代碼和Interface Builder我都是用過的,在開發過程中也積累了一些經驗。對於初學者學習純代碼AutoLayout,我建議還是先學會Interface Builder方式的AutoLayout,領悟蘋果對自動佈局的規則和思想,然後再把這套思想嵌套在純代碼上。這樣學習起來更好入手,也可以避免踩好多坑。

在項目中設置的AutoLayout約束,起到對視圖佈局的標記作用。設置好約束之後,程式運行過程中創建視圖時,會根據設置好的約束計算frame,並渲染到視圖上。

所以在純代碼情況下,視圖設置的約束是否正確,要以運行之後顯示的結果和列印的log為準。

Masonry中的坑

在使用Masonry進行約束時,有一些是需要註意的。

  1. 在使用Masonry添加約束之前,需要在addSubview之後才能使用,否則會導致崩潰。

  2. 在添加約束時初學者經常會出現一些錯誤,約束出現問題的原因一般就是兩種:約束衝突和缺少約束。對於這兩種問題,可以通過調試和log排查。

  3. 之前使用Interface Builder添加約束,如果約束有錯誤直接就可以看出來,並且會以紅色或者黃色警告體現出來。而Masonry則不會直觀的體現出來,而是以運行過程中崩潰或者列印異常log體現,所以這也是手寫代碼進行AutoLayout的一個缺點。

這個問題只能通過多敲代碼,積攢純代碼進行AutoLayout的經驗,慢慢就用起來越來越得心應手了。

Masonry基礎使用

Masonry基礎API

1 2 3 4 5 6 7 8 9 mas_makeConstraints()    添加約束 mas_remakeConstraints()  移除之前的約束,重新添加新的約束 mas_updateConstraints()  更新約束   equalTo()       參數是對象類型,一般是視圖對象或者mas_width這樣的坐標系對象 mas_equalTo()   和上面功能相同,參數可以傳遞基礎數據類型對象,可以理解為比上面的API更強大   width()         用來表示寬度,例如代表view的寬度 mas_width()     用來獲取寬度的值。和上面的區別在於,一個代表某個坐標系對象,一個用來獲取坐標系對象的值

Auto Boxing

上面例如equalTo或者width這樣的,有時候需要涉及到使用mas_首碼,這在開發中需要註意作區分。

如果在當前類引入#import "Masonry.h"之前,用下麵兩種巨集定義聲明一下,就不需要區分mas_首碼。

1 2 3 4 // 定義這個常量,就可以不用在開發過程中使用"mas_"首碼。 #define MAS_SHORTHAND // 定義這個常量,就可以讓Masonry幫我們自動把基礎數據類型的數據,自動裝箱為對象類型。 #define MAS_SHORTHAND_GLOBALS

修飾語句

Masonry為了讓代碼使用和閱讀更容易理解,所以直接通過點語法就可以調用,還添加了and和with兩個方法。這兩個方法內部實際上什麼都沒乾,只是在內部將self直接返回,功能就是為了更加方便閱讀,對代碼執行沒有實際作用。

例如下麵的例子:

1 make.top.and.bottom.equalTo(self.containerView).with.offset(padding);

其內部代碼實現,實際上就是直接將self返回。

1 2 3 - (MASConstraint *)with {     return self; }

更新約束和佈局

關於更新約束佈局相關的API,主要用以下四個API:

1 2 3 4 - (void)updateConstraintsIfNeeded  調用此方法,如果有標記為需要重新佈局的約束,則立即進行重新佈局,內部會調用updateConstraints方法 - (void)updateConstraints          重寫此方法,內部實現自定義佈局過程 - (BOOL)needsUpdateConstraints     當前是否需要重新佈局,內部會判斷當前有沒有被標記的約束 - (void)setNeedsUpdateConstraints  標記需要進行重新佈局

關於UIView重新佈局相關的API,主要用以下三個API:

1 2 3 - (void)setNeedsLayout  標記為需要重新佈局 - (void)layoutIfNeeded  查看當前視圖是否被標記需要重新佈局,有則在內部調用layoutSubviews方法進行重新佈局 - (void)layoutSubviews  重寫當前方法,在內部完成重新佈局操作

Masonry示例代碼

Masonry本質上就是對系統AutoLayout進行的封裝,包括裡面很多的API,都是對系統API進行了一次二次包裝。

1 2 3 4 5 6 7 8 9 10 11 12 13 typedef NS_OPTIONS(NSInteger, MASAttribute) {     MASAttributeLeft = 1 << NSLayoutAttributeLeft,     MASAttributeRight = 1 << NSLayoutAttributeRight,     MASAttributeTop = 1 << NSLayoutAttributeTop,     MASAttributeBottom = 1 << NSLayoutAttributeBottom,     MASAttributeLeading = 1 << NSLayoutAttributeLeading,     MASAttributeTrailing = 1 << NSLayoutAttributeTrailing,     MASAttributeWidth = 1 << NSLayoutAttributeWidth,     MASAttributeHeight = 1 << NSLayoutAttributeHeight,     MASAttributeCenterX = 1 << NSLayoutAttributeCenterX,     MASAttributeCenterY = 1 << NSLayoutAttributeCenterY,     MASAttributeBaseline = 1 << NSLayoutAttributeBaseline, };

常用方法

設置內邊距

1 2 3 4 5 6 7 8 9 10 11 12 13 /**   設置yellow視圖和self.view等大,並且有10的內邊距。  註意根據UIView的坐標系,下麵right和bottom進行了取反。所以不能寫成下麵這樣,否則right、bottom這兩個方向會出現問題。  make.edges.equalTo(self.view).with.offset(10);    除了下麵例子中的offset()方法,還有針對不同坐標系的centerOffset()、sizeOffset()、valueOffset()之類的方法。  */ [self.yellowView mas_makeConstraints:^(MASConstraintMaker *make) {     make.left.equalTo(self.view).with.offset(10);     make.top.equalTo(self.view).with.offset(10);     make.right.equalTo(self.view).with.offset(-10);     make.bottom.equalTo(self.view).with.offset(-10); }];

通過insets簡化設置內邊距的方式

1 2 3 4 5 // 下麵的方法和上面例子等價,區別在於使用insets()方法。 [self.blueView mas_makeConstraints:^(MASConstraintMaker *make) {     // 下、右不需要寫負號,insets方法中已經為我們做了取反的操作了。     make.edges.equalTo(self.view).with.insets(UIEdgeInsetsMake(10, 10, 10, 10)); }];

更新約束

1 2 3 4 5 6 7 8 9 10 11 12 13 14 // 設置greenView的center和size,這樣就可以達到簡單進行約束的目的 [self.greenView mas_makeConstraints:^(MASConstraintMaker *make) {     make.center.equalTo(self.view);     // 這裡通過mas_equalTo給size設置了基礎數據類型的參數,參數為CGSize的結構體     make.size.mas_equalTo(CGSizeMake(300, 300)); }];   // 為了更清楚的看出約束變化的效果,在顯示兩秒後更新約束。 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{     [self.greenView mas_updateConstraints:^(MASConstraintMaker *make) {         make.centerX.equalTo(self.view).offset(100);         make.size.mas_equalTo(CGSizeMake(100, 100));     }]; });

大於等於和小於等於某個值的約束

1 2 3 4 5 6 7 [self.textLabel mas_makeConstraints:^(MASConstraintMaker *make) {     make.center.equalTo(self.view);     // 設置寬度小於等於200     make.width.lessThanOrEqualTo(@200);     // 設置高度大於等於10     make.height.greaterThanOrEqualTo(@(10)); }];

self.textLabel.text = @"這是測試的字元串。能看到1、2、3個步驟,第一步當然是上傳照片了,要上傳正面近照哦。上傳後,網站會自動識別你的面部,如果覺得識別的不准,你還可以手動修改一下。左邊可以看到16項修改參數,最上面是整體修改,你也可以根據自己的意願單獨修改某項,將滑鼠放到選項上面,右邊的預覽圖會顯示相應的位置。";

textLabel只需要設置一個屬性即可

1 self.textLabel.numberOfLines = 0;

使用基礎數據類型當做參數

1 2 3 4 5 6 7 8 9 10 11 12 /**   如果想使用基礎數據類型當做參數,Masonry為我們提供了"mas_xx"格式的巨集定義。  這些巨集定義會將傳入的基礎數據類型轉換為NSNumber類型,這個過程叫做封箱(Auto Boxing)。     "mas_xx"開頭的巨集定義,內部都是通過MASBoxValue()函數實現的。  這樣的巨集定義主要有四個,分別是mas_equalTo()、mas_offset()和大於等於、小於等於四個。  */ [self.redView mas_makeConstraints:^(MASConstraintMaker *make) {     make.center.equalTo(self.view);     make.width.mas_equalTo(100);     make.height.mas_equalTo(100); }];

設置約束優先順序

1 2 3 4 5 6 7 8 9 10 11 /**   Masonry為我們提供了三個預設的方法,priorityLow()、priorityMedium()、priorityHigh(),這三個方法內部對應著不同的預設優先順序。  除了這三個方法,我們也可以自己設置優先順序的值,可以通過priority()方法來設置。  */ [self.redView mas_makeConstraints:^(MASConstraintMaker *make) {     make.center.equalTo(self.view);     make.width.equalTo(self.view).priorityLow();     make.width.mas_equalTo(20).priorityHigh();     make.height.equalTo(self.view).priority(200);     make.height.mas_equalTo(100).priority(1000); }];
1 2 3 4 5 6 Masonry也幫我們定義好了一些預設的優先順序常量,分別對應著不同的數值,優先順序最大數值是1000。 static const MASLayoutPriority MASLayoutPriorityRequired = UILayoutPriorityRequired; static const MASLayoutPriority MASLayoutPriorityDefaultHigh = UILayoutPriorityDefaultHigh; static const MASLayoutPriority MASLayoutPriorityDefaultMedium = 500; static const MASLayoutPriority MASLayoutPriorityDefaultLow = UILayoutPriorityDefaultLow; static const MASLayoutPriority MASLayoutPriorityFittingSizeLevel = UILayoutPriorityFittingSizeLevel;

設置約束比例

1 2 3 4 5 6 // 設置當前約束值乘以多少,例如這個例子是redView的寬度是self.view寬度的0.2倍。 [self.redView mas_makeConstraints:^(MASConstraintMaker *make) {     make.center.equalTo(self.view);     make.height.mas_equalTo(30);     make.width.equalTo(self.view).multipliedBy(0.2); }];

小練習

子視圖等高練習

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 /**   下麵的例子是通過給equalTo()方法傳入一個數組,設置數組中子視圖及當前make對應的視圖之間等高。    需要註意的是,下麵block中設置邊距的時候,應該用insets來設置,而不是用offset。  因為用offset設置right和bottom的邊距時,這兩個值應該是負數,所以如果通過offset來統一設置值會有問題。  */ CGFloat padding = LXZViewPadding; [self.redView mas_makeConstraints:^(MASConstraintMaker *make) {     make.left.right.top.equalTo(self.view).insets(UIEdgeInsetsMake(padding, padding, 0, padding));     make.bottom.equalTo(self.blueView.mas_top).offset(-padding); }];   [self.blueView mas_makeConstraints:^(MASConstraintMaker *make) {     make.left.right.equalTo(self.view).insets(UIEdgeInsetsMake(0, padding, 0, padding));     make.bottom.equalTo(self.yellowView.mas_top).offset(-padding); }];   /**   下麵設置make.height的數組是關鍵,通過這個數組可以設置這三個視圖高度相等。其他例如寬度之類的,也是類似的方式。  */ [self.yellowView mas_makeConstraints:^(MASConstraintMaker *make) {     make.left.right.bottom.equalTo(self.view).insets(UIEdgeInsetsMake(0, padding, padding, padding));     make.height.equalTo(@[self.blueView, self.redView]); }];

子視圖垂直居中練習

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 /**   要求:(這個例子是在其他人博客里看到的,然後按照要求自己寫了下麵這段代碼)  兩個視圖相對於父視圖垂直居中,並且兩個視圖以及父視圖之間的邊距均為10,高度為150,兩個視圖寬度相等。  */ CGFloat padding = 10.f; [self.blueView mas_makeConstraints:^(MASConstraintMaker *make) {     make.centerY.equalTo(self.view);     make.left.equalTo(self.view).mas_offset(padding);     make.right.equalTo(self.redView.mas_left).mas_offset(-padding);     make.width.equalTo(self.redView);     make.height.mas_equalTo(150); }];   [self.redView mas_makeConstraints:^(MASConstraintMaker *make) {     make.centerY.equalTo(self.view);     make.right.equalTo(self.view).mas_offset(-padding);     make.width.equalTo(self.blueView);     make.height.mas_equalTo(150); }];

UITableView動態Cell高度

在iOS UI開發過程中,UITableView的動態Cell高度一直都是個問題。實現這樣的需求,實現方式有很多種,只是實現起來複雜程度和性能的區別。

在不考慮性能的情況下,tableView動態Cell高度,可以採取估算高度的方式。如果通過估算高度的方式實現的話,無論是純代碼還是Interface Builder,都只需要兩行代碼就可以完成Cell自動高度適配。

實現方式:

需要設置tableView的rowHeight屬性,這裡設置為自動高度,告訴系統Cell的高度是不固定的,需要系統幫我們進行計算。然後設置tableView的estimatedRowHeight屬性,設置一個估計的高度。(我這裡用的代理方法,實際上都一樣)

原理:

這樣的話,在tableView被創建之後,系統會根據estimatedRowHeight屬性設置的值,為tableView設置一個估計的值。然後在Cell顯示的時候再獲取Cell的高度,並刷新tableView的contentSize。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 - (void)tableViewConstraints {     [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {         make.edges.equalTo(self.view);     }]; }   - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {     return self.dataList.count; }   - (MasonryTableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {     MasonryTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:LXZTableViewCellIdentifier];     [cell reloadViewWithText:self.dataList[indexPath.row]];     return cell; }   // 需要註意的是,這個代理方法和直接返回當前Cell高度的代理方法並不一樣。 // 這個代理方法會將當前所有Cell的高度都預估出來,而不是只計算顯示的Cell,所以這種方式對性能消耗還是很大的。 // 所以通過設置estimatedRowHeight屬性的方式,和這種代理方法的方式,最後性能消耗都是一樣的。 - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {     return 50.f; }   - (UITableView *)tableView {     if (!_tableView) {         _tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];         _tableView.delegate = self;         _tableView.dataSource = self;         // 設置tableView自動高度         _tableView.rowHeight = UITableViewAutomaticDimension;         [_tableView registerClass:[MasonryTableViewCell class] forCellReuseIdentifier:LXZTableViewCellIdentifier];         [self.view addSubview:_tableView];     }     return _tableView; }

UIScrollView自動佈局

之前聽很多人說過UIScrollView很麻煩,然而我並沒有感覺到有多麻煩(並非裝逼)。我感覺說麻煩的人可能根本就沒試過吧,只是覺得很麻煩而已。

我這裡就講一下兩種進行UIScrollView自動佈局的方案,並且會講一下自動佈局的技巧,只要掌握技巧,佈局其實很簡單。

佈局小技巧:

給UIScrollView添加的約束是定義其frame,設置contentSize是定義其內部大小。UIScrollView進行addSubview操作,都是將其子視圖添加到contentView上。

所以,添加到UIScrollView上的子視圖,對UIScrollView添加的約束都是作用於contentView上的。只需要按照這樣的思路給UIScrollView設置約束,就可以掌握設置約束的技巧了。

提前設置contentSize

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 // 提前設置好UIScrollView的contentSize,並設置UIScrollView自身的約束 self.scrollView.contentSize = CGSizeMake(1000, 1000); [self.scrollView mas_makeConstraints:^(MASConstraintMaker *make) {     make.edges.equalTo(self.view); }];   // 雖然redView的get方法內部已經執行過addSubview操作,但是UIView始終以最後一次添加的父視圖為準,也就是redView始終是在最後一次添加的父視圖上。 [self.scrollView addSubview:self.redView]; [self.redView mas_makeConstraints:^(MASConstraintMaker *make) {     make.left.top.equalTo(self.scrollView);     make.width.height.mas_equalTo(200); }];   [self.scrollView addSubview:self.blueView]; [self.blueView mas_makeConstraints:^(MASConstraintMaker *make) {     make.left.equalTo(self.redView.mas_right);     make.top.equalTo(self.scrollView);     make.width.height.equalTo(self.redView); }];   [self.scrollView addSubview:self.greenView]; [self.greenView mas_makeConstraints:^(MASConstraintMaker *make) {     make.left.equalTo(self.scrollView);     make.top.equalTo(self.redView.mas_bottom);     make.width.height.equalTo(self.redView); }];

自動contentSize

上面的例子是提前設置好UIScrollView的contentSize的內部size,然後直接向裡面addSubview。但是這有個要求就是,需要提前知道contentSize的大小,不然沒法設置。

這個例子中將會展示動態改變contentSize的大小,內部視圖有多少contentSize就自動擴充到多大。

這種方式的實現,主要是依賴於創建一個containerView內容視圖,並添加到UIScrollView上作為子視圖。UIScrollView原來的子視圖都添加到containerView上,並且和這個視圖設置約束。

因為對UIScrollView進行addSubview操作的時候,本質上是往其contentView上添加。也就是containerView的父視圖是contentView,通過containerView撐起contentView視圖的大小,以此來實現動態改變contentSize。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 // 在進行約束的時候,要對containerView的上下左右都添加和子視圖的約束,以便確認containerView的邊界區域。 [self.scrollView mas_makeConstraints:^(MASConstraintMaker *make) {     make.edges.equalTo(self.view); }];   CGFloat padding = LXZViewPadding; [self.containerView mas_makeConstraints:^(MASConstraintMaker *make) {     make.edges.equalTo(self.scrollView).insets(UIEdgeInsetsMake(padding, padding, padding, padding)); }];   [self.containerView addSubview:self.greenView]; [self.greenView mas_makeConstraints:^(MASConstraintMaker *make) {     make.top.left.equalTo(self.containerView).offset(padding);     make.size.mas_equalTo(CGSizeMake(250, 250)); }];  
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 品牌:超凡魔術師h5案例地址:http://www.199case.com/caseview.aspx?id=2668 1、內容:一個以”超凡魔術師“為主題的視頻+回答類的推文,用戶可以通過觀看一段一個人物在表演魔術的視頻,在其間用戶可以選擇兩個選項中的一項與之進行互動。 2、亮點:這篇推文最大的亮 ...
  • 1、java堆得Young區由哪些組成: Java堆由Perm區和Heap區組成,Heap區由Old區和New區(也叫Young區)組成,New區由Eden區、From區和To區(Survivor)組成。 2、實現ContentProvider需要實現哪些方法: insert、delete、quer ...
  • #菜單 pod 'LGSideMenuController' # 刷新 pod 'MJRefresh' # 網路請求 pod 'AFNetworking', '~> 3.0' # 圖片緩存 pod 'SDWebImage', '~> 4.0' # 數據解析 pod 'MJExtension' # 網 ...
  • CVPixelBufferRef YUV NV12 pixelFormatType 創建 數據填充 數據讀取 CGImageRef to CVPixelBufferRef ...
  • 2017.10.20 之前參加一個大三學長的創業項目,做一個智能的車鎖App,用到嵌入式等技術,App需要藍牙、實時位置等技術,故查了幾篇相關技術文章,以此參考! //先說說如何開啟藍牙設備和設置可見時間: private void search() { BluetoothAdapter adapt ...
  • 實現目標 先來一張微信功能截圖看看要做什麼 其實就是有一個目的地,點擊目的地的時候彈出可選擇的應用進行導航。 大腦動一下,要實現這個功能應該大體分成兩步: 底部菜單這裡用PopupWindow來做。 實現 1、菜單顯示 PopupWindow支持傳入view進行彈出展示,所有我們直接寫一個菜單佈局, ...
  • 直奔主題 第一步:為AndroidStudio安裝Kotlin插件 線上安裝步驟:File—>Settings—>Plugins—>Install JetBrains plugin…出現以下界面,選中Kotlin 點擊右邊的Install(因為我的已經安裝了所以顯示的是Update升級) 然後就是漫 ...
  • 枚舉增強程式的可讀性,用法上還是需要註意的 1.C語言的寫法 enum XMPPReconnectFlags { kShouldReconnect = 1 << 0, // If set, disconnection was accidental, and autoReconnect may be ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...