Writing in the front
Some time ago, I set up chevereto-free, a map bed website, with my friends. Suddenly, I found that there is an API to provide, and it is very simple, just need a KEY
Feel very suitable for practice when the project, not a few pages, do very fast, is 2.1 gift package made for a long time before the online. Mimi tobed AppStore
Small blog with friends interested can see, this article will also be synchronized in the past, also contains some server related content. Personal blog
This article mainly code using RAC+MVVM and some other third-party libraries, do more urgent, although it is MVVM+RAC but the use of the relatively poor, do not like spray. Code structure is not paid special attention to
The preparatory work
- You have to have a VPS
- Install the relevant environment, visual pagoda set is good, or directly install the LNMP environment
- Build chevereto-free front and back
Install the front and back of the map bed can use a normal Web site to upload pictures. Go in the background and open the API and get the API KEY
This is the mimitu bed after it’s built
Manage third parties using cocoaPods. Turn on iCloud’s simplest key-value storage feature
Interface design
After all the preparation work is done, we can start to design the App. Don’t get too complicated. Just a few pages
- Home page: main function entrance, upload pictures. After uploading, you can choose the content of copy and add a share
- History: Uploaded history, directly using iCloud to save data. There are also home copy and share functions
- About: some disclaimer, for example prohibit upload small yellow map and so on.
Lazy direct screenshots
Home page
Home page is a upload image to the background, stole a lazy, did not use RAC+MVVM, directly a pile of written in VC
- (void)viewDidLoad { [super viewDidLoad]; Self. customnavbar. title = @" "; Reachability *reach = [Reachability reachabilityWithHostName:@"https://www.baidu.com"]; reach.reachableBlock = ^(Reachability *reachability) { NSLog(@"REACHABLE!" ); }; UIView *uploadView = [UIView new]; [self.view addSubview:uploadView]; [uploadView mas_makeConstraints:^(MASConstraintMaker *make) { make.center.equalTo(uploadView.superview); make.size.equalTo(CGSizeMake(scaleHeight(200), scaleHeight(250))); }]; uploadView.userInteractionEnabled = YES; @weakify(self); [uploadView bk_whenTapped:^{ NSLog(@"click upload btn"); @strongify(self); TZImagePickerController *imagePickerVc = [[TZImagePickerController alloc] initWithMaxImagesCount:1 delegate:self]; imagePickerVc.allowPickingVideo = NO; [self presentViewController:imagePickerVc animated:YES completion:nil]; }]; UIImageView *uploadImg = [UIImageView new]; uploadImg.image = [UIImage imageNamed:@"hui"]; [uploadView addSubview:uploadImg]; [uploadImg mas_makeConstraints:^(MASConstraintMaker *make) { make.top.left.right.equalTo(uploadImg.superview); make.height.equalTo(scaleHeight(200)); }]; UILabel *titleLabel = [UILabel new]; titleLabel.font = FontHeiti(14); titleLabel.textColor = [UIColor redColor]; Titlelabel. text = @" Select image to upload "; [uploadView addSubview:titleLabel]; [titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.centerX.equalTo(titleLabel.superview); make.top.equalTo(uploadImg.mas_bottom); }]; } - (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingPhotos:(NSArray<UIImage *> *)photos sourceAssets:(NSArray *)assets isSelectOriginalPhoto:(BOOL)isSelectOriginalPhoto { NSLog(@"photos=%@",photos); [SVProgressHUD showWithStatus:@" "] ; [self prepareUploadWithImage:photos.firstObject]; } - (void)prepareUploadWithImage:(UIImage*)image { NSDictionary *sendParams = @{ @"uploadfile":@[image], }; @weakify(self); [[GApiManger sendApi:GApiTypeUpload withParam:sendParams] subscribeNext:^(id x) { NSLog(@"GApiManger result = %@",x); [SVProgressHUD showSuccessWithStatus:@" Upload successful! "]; HomeModel *homeModel = [HomeModel new]; [homeModel mts_setValuesForKeysWithDictionary:x]; @strongify(self); [self showSuccessViewWithData:homeModel image:image]; } error:^(NSError *error) { NSLog(@"GApiManger error = %@",error); }]; }Copy the code
After the upload is successful, write to iCloud, and share and other content will pop up
- (void)showSuccessViewWithData:(HomeModel*)homeModel image:(UIImage*)image{ NSDictionary *homeDict= homeModel.yy_modelToJSONObject; NSLog(@"homeDict=%@",homeDict); / / up to store NSUbiquitousKeyValueStore * myKeyValue = [NSUbiquitousKeyValueStore defaultStore]; NSArray *iCloudData = [myKeyValue objectForKey:@"iCloudData"]; NSMutableArray *newData = @[].mutableCopy; if (iCloudData) { newData = iCloudData.mutableCopy; } [newData addObject:homeDict]; [myKeyValue setObject:newData forKey:@"iCloudData"]; [myKeyValue synchronize]; UIView *successView = [UIView new]; successView.backgroundColor = HexColor(0xf3f3f3); [self.view addSubview:successView]; [successView mas_makeConstraints:^(MASConstraintMaker *make) { Make. Size. EqualTo (successView. Superview.) multipliedBy (0.8), and make the centerX. EqualTo (successView. Superview); make.top.equalTo(self.customNavBar.mas_bottom).offset(scaleHeight(20)); }]; UIImageView *imageView = [UIImageView new]; imageView.image = image; imageView.backgroundColor = HexColor(0xffffff); imageView.contentMode = UIViewContentModeScaleAspectFit; [successView addSubview:imageView]; [imageView mas_makeConstraints:^(MASConstraintMaker *make) {make.width. EqualTo (successView). Make. Height. EqualTo (successView). MultipliedBy (0.6), and make the centerX. EqualTo (imageView. Superview); make.top.equalTo(scaleHeight(20)); }]; successView.hidden = YES; [UIView animateWithDuration:0.5 animations:^{successView.hidden = NO;}]; UIButton *copyBtn = [UIButton buttonWithType:UIButtonTypeSystem]; [copyBtn setTitle: @ "select image address style" forState: UIControlStateNormal]; // [copyBtn setTitleColor:HexColor(0x000000) forState:UIControlStateNormal]; [successView addSubview:copyBtn]; [copyBtn mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(imageView.mas_bottom).offset(scaleHeight(20)); make.centerX.equalTo(copyBtn.superview); }]; @weakify(self); [copyBtn bk_addEventHandler:^(id sender) { @strongify(self); UIActionSheet *sheet = [UIActionSheet bk_actionSheetWithTitle:@" Please select the style you want to copy "]; [sheet bk_addButtonWithTitle:@" copy address "handler:^{NSString *url = homemodel.url; UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; [pasteboard setString:url]; }]; [sheet bk_addButtonWithTitle:@" Copy Markdown" handler:^{NSString * Markdown = [NSString stringWithFormat:@"! [image](%@)",homeModel.url]; UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; [pasteboard setString: markdown];}] [sheet bk_setCancelButtonWithTitle: @ "cancel" handler: ^ {}]. [sheet showInView:self.view]; } forControlEvents:UIControlEventTouchUpInside]; UIButton *uploadBtn = [UIButton buttonWithType:UIButtonTypeSystem]; [uploadBtn setTitle: @ "continue to upload" forState: UIControlStateNormal]; // [uploadBtn setTitleColor:HexColor(0x000000) forState:UIControlStateNormal]; [successView addSubview:uploadBtn]; [uploadBtn mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(copyBtn.mas_bottom).offset(scaleHeight(20)); make.centerX.equalTo(uploadBtn.superview); }]; [uploadBtn bk_addEventHandler:^(id Sender) {[UIView animateWithDuration:0.5 animations:^{successView. Alpha = 0; } completion:^(BOOL finished) { [successView removeFromSuperview]; }]; } forControlEvents:UIControlEventTouchUpInside]; UIButton *shareBtn = [UIButton buttonWithType:UIButtonTypeSystem]; [shareBtn setTitle: @ "share" forState: UIControlStateNormal]; // [shareBtn setTitleColor:HexColor(0x000000) forState:UIControlStateNormal]; [successView addSubview:shareBtn]; [shareBtn mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(uploadBtn.mas_bottom).offset(scaleHeight(20)); make.centerX.equalTo(shareBtn.superview); }]; [shareBtn bk_addEventHandler:^(id sender) { @strongify(self); [self SystemShareWithTitle:@"" withText:@"" withImageUrl:homeModel.url withSiteUrl:homeModel.url withVC:self]; } forControlEvents:UIControlEventTouchUpInside]; }Copy the code
//ios share -(void)SystemShareWithTitle:(NSString*)title withText:(NSString*)text withImageUrl:(NSString*)url withSiteUrl:(NSString*)siteurl withVC:(UIViewController*)VC { NSString *titleText = title; NSString *shareText = text; NSURL *URL = [NSURL URLWithString:siteurl]; UIImage *image =[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:url]]]; UIActivityViewController *a = [[UIActivityViewController alloc] initWithActivityItems:[NSArray arrayWithObjects:titleText,shareText,URL,image, nil] applicationActivities:nil]; [VC presentViewController:a animated:true completion:nil]; }Copy the code
The first page is basically over… One VC. Post it just for space.
history
The basic functions are as follows
- Load iCloud data
- Delete records
- share
MVVM+RAC is used here
- ViewModel Creates two commands, retrieves data, and deletes data
@interface MMHistoryViewModel : GBaseViewModel
@property (nonatomic, strong, readonly) RACCommand *getMainData;
@property (nonatomic, strong, readonly) RACCommand *deleteCommand;
@end
Copy the code
- Write a function
- (RACCommand *)getMainData {
if(! _getMainData) { @weakify(self); _getMainData = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {return[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [subscriber sendNext:nil]; [subscriber sendCompleted];return nil;
}] doNext:^(NSDictionary *json) {
@strongify(self);
[self processListData:json];
}] takeUntil:[self rac_signalForSelector:@selector(cancelData)]] ;
}];
}
return_getMainData; } - (void) processListData dataModel: (NSDictionary *) {/ / to get data from ripped NSUbiquitousKeyValueStore * myKeyValue = [NSUbiquitousKeyValueStore defaultStore]; NSArray *iCloudData = [myKeyValue objectForKey:@"iCloudData"];
if(! iCloudData) { [self.errorSignal sendNext:[NSError errorWithDomain:@"No upload history" code:999 userInfo:nil]];
}else {
NSMutableArray *res = iCloudData.mutableCopy;
iCloudData = [[res reverseObjectEnumerator] allObjects];
NSMutableArray *sendArray = @[].mutableCopy;
GBaseViewModelSection *section = [GBaseViewModelSection new];
[iCloudData enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
GBaseViewModelItem *item = [[GBaseViewModelItem alloc] initWithType:GCellTypeHistory modelData:obj];
[section.arrayItems addObject:item];
}];
[sendArray addObject:section];
[self.dataSignal sendNext:sendArray];
}
}
- (RACCommand *)deleteCommand {
if(! _deleteCommand) { @weakify(self); _deleteCommand = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {return[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [subscriber sendNext:input]; [subscriber sendCompleted];return nil;
}]doNext:^(id x) { @strongify(self); [self deleteData:x]; }]; }]; }return_deleteCommand; } - (void) data deleteData (NSDictionary *) {/ / to get data from up to NSUbiquitousKeyValueStore * myKeyValue = [NSUbiquitousKeyValueStore defaultStore]; NSArray *iCloudData = [myKeyValue objectForKey:@"iCloudData"];
NSMutableArray *res = iCloudData.mutableCopy;
[res removeObject:data];
iCloudData = res;
[myKeyValue setObject:iCloudData forKey:@"iCloudData"];
res = [[res reverseObjectEnumerator] allObjects].mutableCopy;
iCloudData = res;
NSMutableArray *sendArray = @[].mutableCopy;
GBaseViewModelSection *section = [GBaseViewModelSection new];
[iCloudData enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
GBaseViewModelItem *item = [[GBaseViewModelItem alloc] initWithType:GCellTypeHistory modelData:obj];
[section.arrayItems addObject:item];
}];
[sendArray addObject:section];
[self.dataSignal sendNext:sendArray];
}
Copy the code
VC is a wave of code, showing the collectionView function is the same as the home page
- (void)viewDidLoad {
[super viewDidLoad];
self.customNavBar.title = @"Upload history";
[self setupStyle];
[self bindData]; } - (void)setupStyle { // self.view.backgroundColor = [UIColor greenColor]; UICollectionView* collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:[[UICollectionViewFlowLayout alloc] init]]; collectionView.backgroundColor = HexColor(0xffffff); [self.view addSubview:collectionView]; collectionView.alwaysBounceVertical = YES; [collectionView mas_makeConstraints:^(MASConstraintMaker *make) { make.left.right.equalTo(self.view); make.bottom.equalTo(self.mas_bottomLayoutGuide); make.top.equalTo(self.customNavBar.mas_bottom); }]; //MARK: register cell [collectionView registerClass:[MMHistoryCell class]forCellWithReuseIdentifier:[MMHistoryCell cellReuseIdentifier]]; // block style toolbox ... @weakify(self); //MARK: Getmodel NSArray<GBaseViewModelSection *>* (^listSectionFromNow)(void) = ^NSArray<GBaseViewModelSection *>* { @strongify(self);returnself.listSection; }; //MARK: Get the section model GBaseViewModelSection * (^ oneSectionFromSectionIndexBlock) (NSInteger) = ^ GBaseViewModelSection * (NSInteger sectionIndex) { NSArray<GBaseViewModelSection *>* listSection = listSectionFromNow(); GBaseViewModelSection* oneSection = nil;if (sectionIndex < listSection.count) {
oneSection = listSection[sectionIndex];
}
returnoneSection; }; //MARK: For each item of the model GBaseViewModelItem * (^ rowModelFromIndexPathBlock) (NSIndexPath *) = ^ GBaseViewModelItem * (NSIndexPath *indexPath) { GBaseViewModelSection * oneSection = oneSectionFromSectionIndexBlock(indexPath.section); NSArray<GBaseViewModelItem*>* modelList = oneSection.arrayItems; GBaseViewModelItem* rowModel = nil;if (indexPath.row < modelList.count) {
rowModel = modelList[indexPath.row];
}
returnrowModel; }; NSDictionary *dictCellType = @{ @(GCellTypeHistory):[MMHistoryCell class], }; //MARK: To obtain the cell class class (^ cellClassFromIndexPathBlock) (NSIndexPath * indexPath) = ^ class (NSIndexPath * indexPath) { GBaseViewModelItem* rowModel = rowModelFromIndexPathBlock(indexPath);returndictCellType[@(rowModel.cellType)]; }; A2DynamicDelegate *dataSource = collectionView.bk_dynamicDataSource; A2DynamicDelegate *delegate = collectionView.bk_dynamicDelegate; //MARK: The item number [dataSource implementMethod: @ the selector (collectionView: numberOfItemsInSection:) withBlock:^NSInteger(UICollectionView *collectionView, NSInteger section) { GBaseViewModelSection* oneSection= oneSectionFromSectionIndexBlock(section);returnoneSection.arrayItems.count; }]; //MARK: Section number [dataSource implementMethod: @ the selector (numberOfSectionsInCollectionView:) withBlock: ^ NSInteger (UICollectionView *collectionView) { NSArray<GBaseViewModelSection *>* listSection = listSectionFromNow();returnlistSection.count; }]; //MARK: The item configuration [dataSource implementMethod: @ the selector (collectionView: cellForItemAtIndexPath:) withBlock:^UICollectionViewCell*(UICollectionView *collectionView,NSIndexPath *indexPath) { id<GCellSetModelProtocol> cell = nil; Class cellClass = cellClassFromIndexPathBlock(indexPath);if (cellClass) {
cell = [collectionView dequeueReusableCellWithReuseIdentifier:[cellClass cellReuseIdentifier] forIndexPath:indexPath];
// TJULLog(@"----%@",cell);
if ([cell respondsToSelector:@selector(renderWithModel:)]) {
[cell renderWithModel:rowModelFromIndexPathBlock(indexPath)];
}
// action block
NSString* stringProperty = NSStringFromSelector(@selector(actionBlockWithDataModel));
NSString* setterStr = [NSString stringWithFormat:@"set%@%@:",
[[stringProperty substringToIndex:1] capitalizedString],
[stringProperty substringFromIndex:1]];
@weakify(self);
if([cell respondsToSelector:NSSelectorFromString(setterStr)]) { cell.actionBlockWithDataModel = ^(id dataModel){ // action @strongify(self); [selfdoAction:dataModel];
};
}
}
[UIView performWithoutAnimation:^{
[((UICollectionViewCell*)cell) layoutIfNeeded];
}];
return (UICollectionViewCell *)cell;
}];
//MARK: item size
[delegate implementMethod:@selector(collectionView:layout:sizeForItemAtIndexPath:) withBlock:^CGSize(UICollectionView *collectionView, UICollectionViewLayout *layout, NSIndexPath *indexPath){
returnCGSizeMake(scaleHeight(100), scaleHeight(100)); }]; //MARK: Section line spacing [delegate implementMethod: @ the selector (collectionView: layout: minimumLineSpacingForSectionAtIndex:) withBlock:^CGFloat(UICollectionView *collectionView, UICollectionViewLayout *layout, NSInteger section){ GBaseViewModelSection* oneSection = oneSectionFromSectionIndexBlock(section); GCellType cellType = oneSection.arrayItems.firstObject.cellType; CGFloat sectionGap = 1; switch (cellType) {case GCellTypeHistory:
sectionGap = scaleHeight(10);
break;
default:
break;
}
returnsectionGap; }]; // //MARK: Section column spacing / / / the delegate implementMethod: @ the selector (collectionView: layout: minimumInteritemSpacingForSectionAtIndex:) withBlock:^CGFloat(UICollectionView *collectionView, UICollectionViewLayout *layout, NSInteger section){ // GBaseViewModelSection* oneSection = oneSectionFromSectionIndexBlock(section); // GCellType cellType = oneSection.arrayItems.firstObject.cellType; // // CGFloat sectionGap = 1; // switch (cellType) { //case GCellTypeHistory:
// sectionGap = scaleHeight(10);
// break;
// default:
// break; / / / /}returnsectionGap; / /}]; //MARL: Margins [delegate implementMethod: @ the selector (collectionView: layout: insetForSectionAtIndex:) withBlock:^UIEdgeInsets(UICollectionView *collectionView, UICollectionViewLayout *layout, NSInteger section){returnUIEdgeInsetsMake(scaleHeight(10), scaleHeight(10), 0, scaleHeight(10)); }]; //MARK: Click event [delegate implementMethod: @ the selector (collectionView: didSelectItemAtIndexPath withBlock) : ^ (UICollectionView *collectionView, NSIndexPath *indexPath){ @strongify(self); GBaseViewModelItem *item = rowModelFromIndexPathBlock(indexPath); [selfdoAction:item];
}];
collectionView.delegate = (id)delegate;
collectionView.dataSource = (id)dataSource;
self.collectionView = collectionView;
}
- (MMHistoryViewModel *)viewModel {
if(! _viewModel) { _viewModel = [[MMHistoryViewModel alloc] init]; }return _viewModel;
}
- (void)bindData { // self.viewModel = [[MMHistoryViewModel alloc] init]; @weakify(self); [self.viewModel.dataSignal subscribeNext:^(id x) { @strongify(self); self.listSection = x; [self.collectionView.mj_header endRefreshing]; [self.collectionView reloadData]; }]; [self.viewModel.errorSignal subscribeNext:^(NSError *error) { @strongify(self); [self.collectionView.mj_header endRefreshing]; NSLog(@"% @",error.domain);
if(! [error.domain isEqualToString:@"There is no more data."]) {
[SVProgressHUD showErrorWithStatus:error.domain];
}
}];
self.collectionView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{
@strongify(self);
[self.viewModel.getMainData execute:nil];
}];
[self.viewModel.getMainData execute:nil];
}
- (void)doAction:(id)model {
NSLog(@"doAction=%@",model);
if ([model isKindOfClass:[GBaseViewModelItem class]]){
[self doCellAction:model];
}
}
- (void)doCellAction:(GBaseViewModelItem*)model {
NSLog(@"doCellAction=%lu",(unsigned long)model.cellType); HomeModel *homeModel = [HomeModel new]; [homeModel yy_modelSetWithDictionary:model.modelData]; UIView *backgroundView = [UIView new]; BackgroundView. BackgroundColor = HexColorA (0 x000000, 0.2); [self.view addSubview:backgroundView]; [backgroundView mas_makeConstraints:^(MASConstraintMaker *make) { make.left.right.equalTo(backgroundView.superview); make.top.equalTo(self.mas_topLayoutGuideTop); make.bottom.equalTo(self.mas_bottomLayoutGuideTop); }]; backgroundView.userInteractionEnabled = YES; self.backgroundView = backgroundView; UIView *successView = [self showSuccessViewWithData:homeModel ]; self.successView = successView; [backgroundView addSubview:successView]; [successView mas_makeConstraints:^(MASConstraintMaker *make) { Make. Size. EqualTo (successView. Superview.) multipliedBy (0.8), and make the centerX. EqualTo (successView. Superview); make.top.equalTo(self.customNavBar.mas_bottom).offset(scaleHeight(20)); }]; // Step 1: Wide view high shrinkage to infinitesimal (point) successView. Transform = CGAffineTransformScale (CGAffineTransformIdentity CGFLOAT_MIN, CGFLOAT_MIN); [UIView animateWithDuration:0.3 animations:^{// Second step: In the form of animation will slowly enlarge to 1.2 times the size of the original view successView. Transform = CGAffineTransformScale (CGAffineTransformIdentity, 1.2, 1.2); } completion:^(BOOL finished) {[UIView animateWithDuration:0.2 animations:^{ Will be in the form of animation view back to original size successView. Transform = CGAffineTransformIdentity;}];}]; [backgroundView bk_whenTapped:^{[UIView animateWithDuration:0.1 animations:^{successView.transform = CGAffineTransformScale (CGAffineTransformIdentity, 1.2, 1.2); } completion:^(BOOL finished) {[UIView animateWithDuration:0.2 animations:^{successView.transform = CGAffineTransformScale (CGAffineTransformIdentity, 0.001, 0.001); the; } completion:^(BOOL finished) { [successView removeFromSuperview]; [backgroundView removeFromSuperview]; }]; }]; }]; } - (UIView*)showSuccessViewWithData:(HomeModel*)homeModel{ NSDictionary *homeDict= homeModel.yy_modelToJSONObject; NSLog(@"homeDict=%@",homeDict);
UIView *successView = [UIView new];
successView.backgroundColor = HexColor(0xf3f3f3);
UIImageView *imageView = [UIImageView new];
[imageView sd_setImageWithURL:[NSURL URLWithString:homeModel.url]];
imageView.backgroundColor = HexColor(0xffffff);
imageView.contentMode = UIViewContentModeScaleAspectFit;
[successView addSubview:imageView];
[imageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.equalTo(successView).multipliedBy(0.8);
make.height.equalTo(successView).multipliedBy(0.6);
make.centerX.equalTo(imageView.superview);
make.top.equalTo(scaleHeight(20));
}];
UIActivityIndicatorView *activity = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[imageView addSubview:activity];
[activity mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(activity.superview);
}];
[activity startAnimating];
[imageView sd_setImageWithURL:[NSURL URLWithString:homeModel.url] placeholderImage:nil completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
[activity removeFromSuperview];
}];
UIButton *copyBtn = [UIButton buttonWithType:UIButtonTypeSystem];
[copyBtn setTitle:@"Select image Address Style" forState:UIControlStateNormal];
// [copyBtn setTitleColor:HexColor(0x000000) forState:UIControlStateNormal]; [successView addSubview:copyBtn]; [copyBtn mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(imageView.mas_bottom).offset(scaleHeight(20)); make.centerX.equalTo(copyBtn.superview); }]; @weakify(self); [copyBtn bk_addEventHandler:^(id sender) { @strongify(self); UIActionSheet *sheet = [UIActionSheet bk_actionSheetWithTitle:@"Please select the style you want to copy"];
[sheet bk_addButtonWithTitle:@"Copy address" handler:^{
NSString *url = homeModel.url;
UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
[pasteboard setString:url];
}];
[sheet bk_addButtonWithTitle:@"Copying the Markdown" handler:^{
NSString *markdown = [NSString stringWithFormat:@! "" [image](%@)",homeModel.url];
UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
[pasteboard setString:markdown];
}];
[sheet bk_setCancelButtonWithTitle:@"Cancel" handler:^{
}];
[sheet showInView:self.view];
} forControlEvents:UIControlEventTouchUpInside];
UIButton *shareBtn = [UIButton buttonWithType:UIButtonTypeSystem];
[shareBtn setTitle:@"Share address" forState:UIControlStateNormal];
// [shareBtn setTitleColor:HexColor(0x000000) forState:UIControlStateNormal];
[successView addSubview:shareBtn];
[shareBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(copyBtn.mas_bottom).offset(scaleHeight(10));
make.centerX.equalTo(shareBtn.superview);
}];
[shareBtn bk_addEventHandler:^(id sender) {
@strongify(self);
[self SystemShareWithTitle:@"" withText:@"" withImageUrl:homeModel.url withSiteUrl:homeModel.url withVC:self];
} forControlEvents:UIControlEventTouchUpInside];
self.shareBtn = shareBtn;
UIButton *deleteBtn = [UIButton buttonWithType:UIButtonTypeSystem];
[deleteBtn setTitle:@"Delete record" forState:UIControlStateNormal];
[deleteBtn setTitleColor:[UIColor redColor] forState:UIControlStateNormal]; [successView addSubview:deleteBtn]; [deleteBtn mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(shareBtn.mas_bottom).offset(scaleHeight(10)); make.centerX.equalTo(deleteBtn.superview); }]; [deleteBtn bk_addEventHandler:^(id sender) { @strongify(self); [self.viewModel.deleteCommand execute:homeDict]; [UIView animateWithDuration: 0.1 animations: ^ {self. SuccessView. Transform = CGAffineTransformScale (CGAffineTransformIdentity, 1.2, 1.2); {} completion: ^ (BOOL finished) [UIView animateWithDuration: 0.2 animations: ^ {self. SuccessView. Transform = CGAffineTransformScale (CGAffineTransformIdentity, 0.001, 0.001); the; } completion:^(BOOL finished) { [self.successView removeFromSuperview]; [self.backgroundView removeFromSuperview]; }]; }];}forControlEvents:UIControlEventTouchUpInside];
UIImageView *closeImg = [UIImageView new];
closeImg.image = [UIImage imageNamed:@"close"];
[successView addSubview:closeImg];
[closeImg mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(deleteBtn.mas_bottom).offset(scaleHeight(10));
make.centerX.equalTo(closeImg.superview);
}];
returnsuccessView; } //ios share -(void)SystemShareWithTitle:(NSString*)title withText:(NSString*)text withImageUrl:(NSString*)url withSiteUrl:(NSString*)siteurl withVC:(UIViewController*)VC { NSString *titleText = title; NSString *shareText = text; NSURL *URL = [NSURL URLWithString:siteurl]; UIImage *image =[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:url]]]; UIActivityViewController *a = [[UIActivityViewController alloc] initWithActivityItems:[NSArray arrayWithObjects:titleText,shareText,URL,image, nil] applicationActivities:nil]; a.modalPresentationStyle = UIModalPresentationPopover;if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
a.popoverPresentationController.sourceView = self.shareBtn;
[self presentViewController:a animated:YES completion:nil];
}else {
[self presentViewController:a animated:YES completion:nil];
}
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.collectionView.mj_header beginRefreshing];
}
Copy the code
about
There is nothing more to say about this page… For what it’s worth, write the disclaimer.
Afterword.
In fact, the need to use the map bed tool on the phone is not much. After all, still more trouble, just a backup option, or browser comfortable, a direct drag to the browser is OK.
This kind of project can only practice, or be familiar with the business process and so on ~
The code has been uploaded to Gayhub
Notice The API_KEY needs to be modified