淺談iOS11新特性:新增拖拽交互體驗
一、引言
在使用PC進行操作時,你一定遇到過這樣的場景,可以將圖片直接拖入聊天軟件進行發(fā)送,可以將文檔、音樂、視頻文件等文件拖入相應應用程序直接進行使用。這種拖拽操作交互極大的方便了電腦的使用。在iOS11中,你可以在iPhone或iPad上構建這種交互體驗!
說在前面的話:
拖拽操作在iPad上是支持跨應用程序的,你可以從一個應用中拖取項目,通過Home鍵回到主界面并且打開另一個應用程序,然后將被拖拽的項目傳遞給這個應用程序中。在iPhone上,拖拽操作只支持當前應用程序內(nèi),你可以將某個元素從一個界面拖拽到另一個,這種維度的操作可以給設計人員更大的靈活性。
拖拽操作被設計成系統(tǒng)管理,開發(fā)者不需要為App申請?zhí)厥獾挠脩魴嘞蕖?nbsp;
二、拖拽源
對于拖拽操作,至少要有兩個組件,一個組件作為拖拽源用來提供數(shù)據(jù),一個組件作為拖拽目的用來接收數(shù)據(jù),當前,同一個組件既可以是拖拽源也可以是拖拽目的。首先我們先來看拖拽源,在UIKit框架中,iOS11默認實現(xiàn)了一些組件可以作為拖拽源, 例如UITextField、UITextView、UITableView和UICollectionView等。文本組件默認支持拖拽操作進行文本的傳遞,對于列表組件則默認支持元素的拖拽。例如,在UITextField選中的文案中進行拖拽,可以將文字拖拽出來,效果如下圖:

任意的UIView組件都可以作為拖拽源,讓其成為拖拽源其實也十分簡單,只需要3步:
1.創(chuàng)建一個UIDragInteraction行為對象。
2.設置UIDragInteraction對象的代理并實現(xiàn)相應方法。
3.將UIDragInteraction對象添加到指定View上。
最簡單的可拖拽組件的創(chuàng)建示例代碼如下:
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:self.dragView];
}
//創(chuàng)建View
-(UIView *)dragView{
if (!_dragView) {
_dragView = [[UIView alloc]initWithFrame:CGRectMake(100, 100, 100, 100)];
_dragView.backgroundColor = [UIColor redColor];
[_dragView addInteraction:self.dragInteraction];
}
return _dragView;
}
//創(chuàng)建拖拽行為對象
-(UIDragInteraction *)dragInteraction{
if (!_dragInteraction) {
_dragInteraction = [[UIDragInteraction alloc]initWithDelegate:self];
//要設置可用 注意?。?!
[_dragInteraction setEnabled:YES];
}
return _dragInteraction;
}
//實現(xiàn)提供數(shù)據(jù)的代理方法
- (NSArray<UIDragItem *> *)dragInteraction:(UIDragInteraction *)interaction itemsForBeginningSession:(id<UIDragSession>)session{
//數(shù)據(jù)提供者
NSItemProvider * provider = [[NSItemProvider alloc]initWithObject:@"Hello World"];
UIDragItem * item = [[UIDragItem alloc]initWithItemProvider:provider];
return @[item];
}
上面的dragInteraction:代理方法用來提供要傳遞的數(shù)據(jù),傳遞的數(shù)據(jù)必須遵守相應的承諾協(xié)議,后面會給大家介紹,這里只是簡單返回了一個字符串數(shù)據(jù)Hello World,運行工程,你可以試驗下,可以直接將我們自定義的視圖拖拽進UITextField并在其中顯示Hello World。
三、關于UIDragInteraction類
所有可以接收拖拽行為的組件都必須通過這個類實現(xiàn),這個類中屬性意義列舉如下:
//初始化方法 - (instancetype)initWithDelegate:(id<UIDragInteractionDelegate>)delegate; //代理 @property (nonatomic, nullable, readonly, weak) id<UIDragInteractionDelegate> delegate; //是否支持多種手勢都接收響應 @property (nonatomic) BOOL allowsSimultaneousRecognitionDuringLift; //設置是否有效 @property (nonatomic, getter=isEnabled) BOOL enabled; //獲取默認是否有效 不同的設備這個值將有所區(qū)別 @property (class, nonatomic, readonly, getter=isEnabledByDefault) BOOL enabledByDefault;
四、UIDragInteractionDelegate協(xié)議
UIDragInteractionDelegate用來處理拖拽源的行為與數(shù)據(jù)。其中定義了一個必須實現(xiàn)的方法和許多可選實現(xiàn)的方法。解析如下:
/* 這個方法是必須實現(xiàn)的用來返回拖拽源提供的數(shù)據(jù) 需要注意,這個函數(shù)需要返回一個數(shù)組,數(shù)組中可以有多個數(shù)據(jù)源 如果返回空數(shù)組,則拖拽行為不會開始 */ - (NSArray<UIDragItem *> *)dragInteraction:(UIDragInteraction *)interaction itemsForBeginningSession:(id<UIDragSession>)session; /* 這個方法用來自定義拖拽效果的預覽視圖 關于預覽視圖,后面會介紹 需要注意,系統(tǒng)默認會提供一個預覽視圖,不實現(xiàn)這個方法即是使用系統(tǒng)默認的 如果返回nil,則會去除預覽動畫 */ - (nullable UITargetedDragPreview *)dragInteraction:(UIDragInteraction *)interaction previewForLiftingItem:(UIDragItem *)item session:(id<UIDragSession>)session; /* 拖拽動畫即將開始時會調(diào)用此函數(shù) */ - (void)dragInteraction:(UIDragInteraction *)interaction willAnimateLiftWithAnimator:(id<UIDragAnimating>)animator session:(id<UIDragSession>)session; //拖拽行為會話即將開始時調(diào)用的方法 - (void)dragInteraction:(UIDragInteraction *)interaction sessionWillBegin:(id<UIDragSession>)session; //這個方法設置數(shù)據(jù)的防止是否允許數(shù)據(jù)的 移動操作,需要注意,這個只有在app內(nèi)有效,跨app的操作會總是復制數(shù)據(jù) - (BOOL)dragInteraction:(UIDragInteraction *)interaction sessionAllowsMoveOperation:(id<UIDragSession>)session; //設置是否允許跨應用程序進行拖拽 ipad - (BOOL)dragInteraction:(UIDragInteraction *)interaction sessionIsRestrictedToDraggingApplication:(id<UIDragSession>)session; //設置預覽視圖是否顯示原始大小 - (BOOL)dragInteraction:(UIDragInteraction *)interaction prefersFullSizePreviewsForSession:(id<UIDragSession>)session; /* 當拖拽源被移動時調(diào)用,可以用如下方法獲取其坐標 NSLog(@"%f,%f",[session locationInView:self.view].x,[session locationInView:self.view].y); */ - (void)dragInteraction:(UIDragInteraction *)interaction sessionDidMove:(id<UIDragSession>)session; //拖拽行為將要結(jié)束時調(diào)用 - (void)dragInteraction:(UIDragInteraction *)interaction session:(id<UIDragSession>)session willEndWithOperation:(UIDropOperation)operation; //拖拽行為已經(jīng)結(jié)束時調(diào)用 - (void)dragInteraction:(UIDragInteraction *)interaction session:(id<UIDragSession>)session didEndWithOperation:(UIDropOperation)operation; //拖拽源進行了放置操作后調(diào)用 - (void)dragInteraction:(UIDragInteraction *)interaction sessionDidTransferItems:(id<UIDragSession>)session; //設置拖拽動作取消的視圖動畫 返回nil則消除動畫 -(nullable UITargetedDragPreview *)dragInteraction:(UIDragInteraction *)interaction previewForCancellingItem:(UIDragItem *)item withDefault:(UITargetedDragPreview *)defaultPreview; //拖拽動作即將取消時調(diào)用的方法 - (void)dragInteraction:(UIDragInteraction *)interaction item:(UIDragItem *)item willAnimateCancelWithAnimator:(id<UIDragAnimating>)animator; //設置是否允許向拖拽中的項目添加數(shù)據(jù) /* 可以返回數(shù)據(jù)載體數(shù)組 當拖拽過程中 點擊可拖拽的組件時會觸發(fā) */ - (NSArray<UIDragItem *> *)dragInteraction:(UIDragInteraction *)interaction itemsForAddingToSession:(id<UIDragSession>)session withTouchAtPoint:(CGPoint)point; //設置允許進行拖拽中追加數(shù)據(jù)的拖拽行為會話 - (nullable id<UIDragSession>)dragInteraction:(UIDragInteraction *)interaction sessionForAddingItems:(NSArray<id<UIDragSession>> *)sessions withTouchAtPoint:(CGPoint)point; //將要向拖拽組件中追加數(shù)據(jù)時調(diào)用 - (void)dragInteraction:(UIDragInteraction *)interaction session:(id<UIDragSession>)session willAddItems:(NSArray<UIDragItem *> *)items forInteraction:(UIDragInteraction *)addingInteraction;
上面列舉的協(xié)議方法中有關聯(lián)到其他許多iOS11中新增的類,后面會一一介紹。其實,完成了以上內(nèi)容的了解,你就已經(jīng)可以完全隨心所欲的定制拖拽源組件了。
五、放置目的地
拖拽源是數(shù)據(jù)的提供者,放置目的地就是數(shù)據(jù)的接收者。前面我們也實驗過,將自定義的拖拽源拖拽進UITextField后,文本框中會自動填充我們提供的文本數(shù)據(jù)。同樣,對于任何自定義的UIView視圖,我們也可以讓其成為放置目的地,需要完成如下3步:
1.創(chuàng)建一個UIDropInteraction行為對象。
2.設置UIDropInteraction對象的代理并實現(xiàn)協(xié)議方法。
3.將其添加到自定義的視圖中。
例如,我們將自定義的UILabel組件用來顯示拖拽的文案:
//添加視圖
- (void)viewDidLoad {
[super viewDidLoad];
//有關拖拽源的代碼 前面已經(jīng)列舉過 這里不再重復
[self.view addSubview:self.dragView];
[self.view addSubview:self.dropLabel];
}
-(UILabel *)dropLabel{
if (!_dropLabel) {
_dropLabel = [[UILabel alloc]initWithFrame:CGRectMake(10, 300, 300, 30)];
_dropLabel.backgroundColor = [UIColor greenColor];
_dropLabel.userInteractionEnabled = YES;
[_dropLabel addInteraction:self.dropInteraction];
}
return _dropLabel;
}
//放置目的地行為對象
-(UIDropInteraction*)dropInteraction{
if (!_dropInteraction) {
_dropInteraction = [[UIDropInteraction alloc]initWithDelegate:self];
}
return _dropInteraction;
}
//這個方法返回是否響應此放置目的地的放置請求
-(BOOL)dropInteraction:(UIDropInteraction *)interaction canHandleSession:(id<UIDropSession>)session{
return YES;
}
//設置以何種方式響應拖放會話行為
-(UIDropProposal *)dropInteraction:(UIDropInteraction *)interaction sessionDidUpdate:(id<UIDropSession>)session{
return [[UIDropProposal alloc]initWithDropOperation:UIDropOperationCopy];
}
//已經(jīng)應用拖放行為后執(zhí)行的操作
-(void)dropInteraction:(UIDropInteraction *)interaction performDrop:(id<UIDropSession>)session{
[session loadObjectsOfClass:[NSString class] completion:^(NSArray<__kindof id<NSItemProviderReading>> * _Nonnull objects) {
self.dropLabel.text = objects.firstObject;
}];
}
上面的代碼將我們自定義的拖拽源提供的Hello World拖放進了UILabel組件中。
六、關于UIDropInteraction類
與UIDragInteraction類類似,這個類的作用是讓組件有相應放置操作的能力。其中屬性如下:
//初始化方法 - (instancetype)initWithDelegate:(id<UIDropInteractionDelegate>)delegate; //代理對象 @property (nonatomic, nullable, readonly, weak) id<UIDropInteractionDelegate> delegate; //是否允許多個交互行為 @property (nonatomic, assign) BOOL allowsSimultaneousDropSessions;
七、UIDropInteractionDelegate協(xié)議
UIDropInteractionDelegate協(xié)議中所定義的方法全部是可選實現(xiàn)的,其用來處理用戶放置交互行為。
//放置行為即將響應時觸發(fā)的方法 返回值確定是否響應此次行為 - (BOOL)dropInteraction:(UIDropInteraction *)interaction canHandleSession:(id<UIDropSession>)session; //當上面的協(xié)議方法返回YES時會接著調(diào)用這個函數(shù) - (void)dropInteraction:(UIDropInteraction *)interaction sessionDidEnter:(id<UIDropSession>)session; //將要處理數(shù)據(jù)時回調(diào)的方法 /* 當數(shù)據(jù)源數(shù)據(jù)添加時,這個方法也會被重新調(diào)用 這個函數(shù)需要返回一個處理行為方式UIDropProposal對象,這個我們后面再說 */ - (UIDropProposal *)dropInteraction:(UIDropInteraction *)interaction sessionDidUpdate:(id<UIDropSession>)session; //放置行為相應結(jié)束的時候會調(diào)用此方法 - (void)dropInteraction:(UIDropInteraction *)interaction sessionDidExit:(id<UIDropSession>)session; //這個方法當用戶進行放置時會調(diào)用,可以從session中獲取被傳遞的數(shù)據(jù) - (void)dropInteraction:(UIDropInteraction *)interaction performDrop:(id<UIDropSession>)session; //放置動畫完成后會調(diào)用這個方法 - (void)dropInteraction:(UIDropInteraction *)interaction concludeDrop:(id<UIDropSession>)session; //整個拖放行為結(jié)束后會調(diào)用 - (void)dropInteraction:(UIDropInteraction *)interaction sessionDidEnd:(id<UIDropSession>)session; //下面這些方法用來自定義放置動畫 //設置放置預覽動畫 - (nullable UITargetedDragPreview *)dropInteraction:(UIDropInteraction *)interaction previewForDroppingItem:(UIDragItem *)item withDefault:(UITargetedDragPreview *)defaultPreview; //這個函數(shù)每當有一個拖拽數(shù)據(jù)項放入時都會調(diào)用一次 可以進行動畫 - (void)dropInteraction:(UIDropInteraction *)interaction item:(UIDragItem *)item willAnimateDropWithAnimator:(id<UIDragAnimating>)animator;
需要注意,UIDropProposal類用來進行處理回執(zhí),屬性方法解析如下:
//初始化方法
/*
typedef NS_ENUM(NSUInteger, UIDropOperation) {
//取消這次行為
UIDropOperationCancel = 0,
//拒絕行為
UIDropOperationForbidden = 1,
//接收拷貝數(shù)據(jù)
UIDropOperationCopy = 2,
//接收移動數(shù)據(jù)
UIDropOperationMove = 3,
}
*/
- (instancetype)initWithDropOperation:(UIDropOperation)operation;
//處理方式
@property (nonatomic, readonly) UIDropOperation operation;
//精準定位
@property (nonatomic, getter=isPrecise) BOOL precise;
//設置是否展示完整的預覽尺寸
@property (nonatomic) BOOL prefersFullSizePreview;
八、拖拽數(shù)據(jù)載體UIDragItem類
UIDragItem類用來承載要傳遞的數(shù)據(jù)。其通過NSItemProvider類來進行構建,傳遞的數(shù)據(jù)類型是有嚴格規(guī)定的,必須遵守一定的協(xié)議,系統(tǒng)的NSString,NSAttributeString,NSURL,UIColor和UIImage是默認支持的,你可以直接傳遞這些數(shù)據(jù)。
UIDragItem中提供的屬性方法:
//初始化方法 - (instancetype)initWithItemProvider:(NSItemProvider *)itemProvider; //數(shù)據(jù)提供者實例 @property (nonatomic, readonly) __kindof NSItemProvider *itemProvider; //用來傳遞一些額外的關聯(lián)信息 @property (nonatomic, strong, nullable) id localObject; //用來自定義每個item添加時的預覽動畫 @property (nonatomic, copy, nullable) UIDragPreview * _Nullable (^previewProvider)(void);
九、UIDropSession與UIDragSession
在與拖拽交互相關的接口中,這兩個是面向協(xié)議編程的絕佳范例,首先在UIKit框架中只定義了這兩個協(xié)議,而并沒有相關的實現(xiàn)類,在拖拽行為的相關回調(diào)接口中,很多id類型的參數(shù)都遵守了這個協(xié)議,我們無需知道是哪個類實現(xiàn)的,直接進行使用即可:
UIDropSession:
//繼承于UIDragDropSession(提供基礎數(shù)據(jù)), NSProgressReporting(提供數(shù)據(jù)讀取進度)
@protocol UIDropSession <UIDragDropSession, NSProgressReporting>
//原始的dragSesstion會話 如果是跨應用的 則為nil
@property (nonatomic, readonly, nullable) id<UIDragSession> localDragSession;
//設置進度風格
/*
typedef NS_ENUM(NSUInteger, UIDropSessionProgressIndicatorStyle) {
UIDropSessionProgressIndicatorStyleNone, // 無
UIDropSessionProgressIndicatorStyleDefault, // 默認的
} API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(watchos, tvos);
*/
@property (nonatomic) UIDropSessionProgressIndicatorStyle progressIndicatorStyle;
//進行數(shù)據(jù)的加載
- (NSProgress *)loadObjectsOfClass:(Class<NSItemProviderReading>)aClass completion:(void(^)(NSArray<__kindof id<NSItemProviderReading>> *objects))completion;
@end
UIDragSession:
API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(watchos, tvos) @protocol UIDragSession <UIDragDropSession> //設置要傳遞的額外信息 只有在同個APP內(nèi)可見 @property (nonatomic, strong, nullable) id localContext; @end
UIDragDropSession:
//傳遞的數(shù)據(jù)數(shù)組 @property (nonatomic, readonly) NSArray<UIDragItem *> *items; //當前操作行為的坐標 - (CGPoint)locationInView:(UIView *)view; //此次行為是否允許移動操作 @property (nonatomic, readonly) BOOL allowsMoveOperation; //是否支持應用程序?qū)用娴耐献? @property (nonatomic, readonly, getter=isRestrictedToDraggingApplication) BOOL restrictedToDraggingApplication; //驗證傳遞的數(shù)據(jù)是否支持某個數(shù)據(jù)類型協(xié)議 - (BOOL)hasItemsConformingToTypeIdentifiers:(NSArray<NSString *> *)typeIdentifiers; //驗證傳遞的數(shù)據(jù)是否可以加載某個類 - (BOOL)canLoadObjectsOfClass:(Class<NSItemProviderReading>)aClass;
十、交互預覽類UITargetedDragPreview
UITargetedDragPreview專門用來處理拖放交互過程中的動畫與預覽視圖。方法解析如下:
//創(chuàng)建一個預覽對象 /* view:要創(chuàng)建的預覽視圖 需要注意,這個視圖必須在window上 param:配置參數(shù) target:容器視圖,用來展示預覽,一般設置為view的父視圖 */ - (instancetype)initWithView:(UIView *)view parameters:(UIDragPreviewParameters *)parameters target:(UIDragPreviewTarget *)target; //同上 -(instancetype)initWithView:(UIView *)view parameters:(UIDragPreviewParameters *)parameters; //同上 - (instancetype)initWithView:(UIView *)view; //動畫承載者 @property (nonatomic, readonly) UIDragPreviewTarget* target; //動畫視圖 @property (nonatomic, readonly) UIView *view; //配置參數(shù) @property (nonatomic, readonly, copy) UIDragPreviewParameters *parameters; //尺寸 @property (nonatomic, readonly) CGSize size; //返回新的對象 - (UITargetedDragPreview *)retargetedPreviewWithTarget:(UIDragPreviewTarget *)newTarget;
UIDragPreviewTarget主要用來設置動畫的起始視圖與結(jié)束時回歸的視圖,其中屬性方法如下:
/* 初始化方法 container:必須是在window上的view center:動畫起點與終點 transform:進行變換 */ - (instancetype)initWithContainer:(UIView *)container center:(CGPoint)center transform:(CGAffineTransform)transform; //同上 - (instancetype)initWithContainer:(UIView *)container center:(CGPoint)center; //對應屬性 @property (nonatomic, readonly) UIView *container; @property (nonatomic, readonly) CGPoint center; @property (nonatomic, readonly) CGAffineTransform transform;
UIDragPreviewParameters用來進行拖拽動畫的配置,解析如下:
//構造方法并設置路徑矩形 - (instancetype)initWithTextLineRects:(NSArray<NSValue /* CGRect */ *> *)textLineRects; //顯示的路徑 @property (nonatomic, copy, nullable) UIBezierPath *visiblePath; //背景色 @property (nonatomic, copy, null_resettable) UIColor *backgroundColor;
我們可以使用任意自定義的視圖來展現(xiàn)這個預覽動畫,如下圖所示:

十一、使用拖拽操作進行自定義數(shù)據(jù)的傳遞
本篇文章到這里,其實基本的內(nèi)容都已經(jīng)說完了,雖然比較詳細,也可能難免冗余,如果你耐著性子看到了這里,那么我首先欽佩你的毅力并且感謝你的耐心。其實,拖拽交互如果進行只能對系統(tǒng)的提供的數(shù)據(jù)類型進行操作則應用就局限太多。試想一下,如果我們可以通過拖拽商品來進行購買,拖拽聯(lián)系人來進行發(fā)送,或者在游戲中,拖拽進行卡片的融合,裝備的提煉等等這種交互操作是不是會很暢快。最后,我們就來看看如何讓自定義的數(shù)據(jù)類型支持拖拽操作。
首先你需要關注兩個協(xié)議,NSItemProviderWriting與NSItemProviderReading。Writing協(xié)議用來讓數(shù)據(jù)支持提供給數(shù)據(jù)源,Reading協(xié)議讓數(shù)據(jù)支持從數(shù)據(jù)源讀出,用自定義的Person類為例:
#import <Foundation/Foundation.h> //遵守協(xié)議 @interface Person : NSObject<NSItemProviderWriting,NSItemProviderReading> //自定義內(nèi)容 @property(nonatomic,strong)NSString * name; @property(nonatomic,assign)NSUInteger age; @end
//.m文件
@implementation Person
//數(shù)據(jù)歸檔
- (nullable NSProgress *)loadDataWithTypeIdentifier:(NSString *)typeIdentifier
forItemProviderCompletionHandler:(void (^)(NSData * _Nullable data, NSError * _Nullable error))completionHandler{
NSProgress * pro = [NSProgress new];
NSData * data = [NSKeyedArchiver archivedDataWithRootObject:self];
completionHandler(data,nil);
return pro;
}
+(NSItemProviderRepresentationVisibility)itemProviderVisibilityForRepresentationWithTypeIdentifier:(NSString *)typeIdentifier{
return NSItemProviderRepresentationVisibilityAll;
}
- (NSItemProviderRepresentationVisibility)itemProviderVisibilityForRepresentationWithTypeIdentifier:(NSString *)typeIdentifier{
return NSItemProviderRepresentationVisibilityAll;
}
//提供一個標識符
+(NSArray<NSString *> *)writableTypeIdentifiersForItemProvider{
return @[@"object"];
}
-(NSArray<NSString *> *)writableTypeIdentifiersForItemProvider{
return @[@"object"];
}
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super init];
if (self) {
self.name = [coder decodeObjectForKey:@"name"];
self.age = [coder decodeIntegerForKey:@"age"];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeObject:self.name forKey:@"name"];
[aCoder encodeInteger:self.age forKey:@"age"];
}
//這兩個是讀協(xié)議
+(NSArray<NSString *> *)readableTypeIdentifiersForItemProvider{
return @[@"object"];
}
//解歸檔返回
+ (nullable instancetype)objectWithItemProviderData:(NSData *)data
typeIdentifier:(NSString *)typeIdentifier
error:(NSError **)outError{
Person * p = [NSKeyedUnarchiver unarchiveObjectWithData:data];
return p;
}
@end
需要注意,在拖放行為讀取數(shù)據(jù)時的類型要對應,如下:
-(void)dropInteraction:(UIDropInteraction *)interaction performDrop:(id<UIDropSession>)session{
NSLog(@"%@",session.items.lastObject.localObject);
[session loadObjectsOfClass:[Person class] completion:^(NSArray<__kindof id<NSItemProviderReading>> * _Nonnull objects) {
self.dropLabel.text = ((Person*)objects.firstObject).name;
}];
}
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
詳解iOS中多個網(wǎng)絡請求的同步問題總結(jié)
這篇文章主要介紹了詳解iOS中多個網(wǎng)絡請求的同步問題總結(jié),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-05-05
ios開發(fā)Flutter之數(shù)據(jù)存儲
這篇文章主要為大家介紹了ios開發(fā)Flutter之數(shù)據(jù)存儲的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-07-07
iOS應用開發(fā)中UITableView的分割線的一些設置技巧
這篇文章主要介紹了iOS應用開發(fā)中UITableView分割線的一些設置技巧,包括消除分割線的方法,示例代碼為傳統(tǒng)的Objective-C語言,需要的朋友可以參考下2016-03-03
總結(jié)iOS App開發(fā)中控制屏幕旋轉(zhuǎn)的幾種方式
這篇文章主要介紹了iOS app開發(fā)中控制屏幕旋轉(zhuǎn)的方法總結(jié),分為自動旋轉(zhuǎn)和手動旋轉(zhuǎn)以及強制旋轉(zhuǎn)三種情況,代碼為Objective-C語言,需要的朋友可以參考下2016-02-02
iOS開發(fā)使用GDataXML框架解析網(wǎng)絡數(shù)據(jù)
GDataXML是Google開發(fā)的一個XML解析庫,輕便,特點使用非常簡單,支持XPath。今天把前兩天弄的IOS XML解析記錄下來,也供大家參考。2016-02-02

