• UIActivityViewController的相关用法(一)--URL的发送和接收


    UIActivityViewController 是一个能为应用程序提供服务的试图控制器。操作系统已经提供了一些标准服务,诸如 复制内容到剪切板,提交内容到社交网站,通过 email 或 短信发送内容等。应用程序也可以自定义服务。在ios8中系统的一些应用可以直接通过action分享给qq好友和微信好友,是因为腾讯增加了Extension,第三方的app不注册腾讯的开发者是无法使用的。

     UIActivityViewController 的Action分为两类,在UIAction的定义中可以查看到:

    UIKIT_EXTERN NSString *const UIActivityTypePostToFacebook     NS_AVAILABLE_IOS(6_0);
    UIKIT_EXTERN NSString *const UIActivityTypePostToTwitter      NS_AVAILABLE_IOS(6_0);
    UIKIT_EXTERN NSString *const UIActivityTypePostToWeibo        NS_AVAILABLE_IOS(6_0);    // SinaWeibo
    UIKIT_EXTERN NSString *const UIActivityTypeMessage            NS_AVAILABLE_IOS(6_0);
    UIKIT_EXTERN NSString *const UIActivityTypeMail               NS_AVAILABLE_IOS(6_0);
    UIKIT_EXTERN NSString *const UIActivityTypePrint              NS_AVAILABLE_IOS(6_0);
    UIKIT_EXTERN NSString *const UIActivityTypeCopyToPasteboard   NS_AVAILABLE_IOS(6_0);
    UIKIT_EXTERN NSString *const UIActivityTypeAssignToContact    NS_AVAILABLE_IOS(6_0);
    UIKIT_EXTERN NSString *const UIActivityTypeSaveToCameraRoll   NS_AVAILABLE_IOS(6_0);
    UIKIT_EXTERN NSString *const UIActivityTypeAddToReadingList   NS_AVAILABLE_IOS(7_0);
    UIKIT_EXTERN NSString *const UIActivityTypePostToFlickr       NS_AVAILABLE_IOS(7_0);
    UIKIT_EXTERN NSString *const UIActivityTypePostToVimeo        NS_AVAILABLE_IOS(7_0);
    UIKIT_EXTERN NSString *const UIActivityTypePostToTencentWeibo NS_AVAILABLE_IOS(7_0);
    UIKIT_EXTERN NSString *const UIActivityTypeAirDrop            NS_AVAILABLE_IOS(7_0);
    
    typedef NS_ENUM(NSInteger, UIActivityCategory) {
        UIActivityCategoryAction,
        UIActivityCategoryShare,
    } NS_ENUM_AVAILABLE_IOS(7_0);

    应用程序要复制配置、呈现和消除 UIActivityViewController。UIActivityViewContoller 的配置需要明确指出控制器要表现出的数据对象。

    下面的代码源自于苹果官方提供的AirDropSample项目,按照本人理解的顺序解析,每个人理解的角度不一样,有偏差请以官方代码和释义为准。

    一:通过UIActivityViewController发送/接收URL(文本等同之)

    发送:用一个URLViewController来管理(

    如果app用URL发送元数据,应该创建一个包含该url的容器类,此类必须要实现 UIActivityItemSource 协议。

    )

    #import <UIKit/UIKit.h>
    
    @interface UrlViewController : UIViewController
    @end
    
    #import "UrlViewController.h"
    #import "Utilities.h"
    #import "UrlContainer.h"
    
    @interface UrlViewController ()<UITextFieldDelegate>
    @property (weak, nonatomic) IBOutlet UITextField *textField;
    @property (strong, nonatomic) UrlContainer *urlContainer;
    
    @property (strong, nonatomic) UIPopoverController *popOverController;
    
    @end
    
    @implementation UrlViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        // 加载收到的url, 如果没有收到的url返回nil
        NSURL *url = [Utilities loadUrl];
        if (!url) {
            url = [NSURL URLWithString:@"hsun://test/one/two?key1=value1"];
        }
    //    NSLog(@"host:%@, user:%@, path:%@, fragment:%@, parameterString:%@, query:%@, relativePath:%@", url.host, url.user, url.path, url.fragment, url.parameterString, url.query, url.relativePath);
        // 初始化item容器
        self.urlContainer = [[UrlContainer alloc] initWithUrl:url];
        // 显示容器中的URL内容
        self.textField.text = [self stringWithoutURLScheme:self.urlContainer.url];
    }
    
    -(void)viewWillAppear:(BOOL)animated
    {
        [super viewWillAppear:animated];
        // 为控制器注册通知,接收到URL, 保存窗口将要呈现
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reloadUrl) name:@"ReceiveURLViewController" object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(saveWindowWillAppear) name:@"SaveWindowWillAppear" object:nil];
    }
    
    -(void)viewWillDisappear:(BOOL)animated
    {
        [super viewWillDisappear:animated];
        // view 消失时移除通知
        [[NSNotificationCenter defaultCenter] removeObserver:self name:@"ReceiveURLViewController" object:nil];
        [[NSNotificationCenter defaultCenter] removeObserver:self name:@"SaveWindowWillAppear" object:nil];
    }
    
    - (IBAction)share:(id)sender {
        // 用实现了 UIActivityItemSource协议的item容器初始化,容器类的定义在下面
        UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:@[self.urlContainer] applicationActivities:nil];
        
        /***
         action 分为两种 :
         UIActivityCategoryAction,
         UIActivityCategoryShare
         如果有不想展示的Share 或者 Action,可以通过如下实现
         activityViewController.excludedActivityTypes = @[UIActivityTypePrint];
       选择Action即可发送容器内的URL了,至此发送URL(文本)完成 **
    */ // iphone 直接呈现 if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) { [self presentViewController:activityViewController animated:YES completion:nil]; } else // ipad 需要用PopOver { if([self.popOverController isPopoverVisible]) { [self.popOverController dismissPopoverAnimated:YES]; } else { self.popOverController = [[UIPopoverController alloc] initWithContentViewController:activityViewController]; [self.popOverController presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; } } } #pragma mark - UITextFieldDelegate -(BOOL)textFieldShouldReturn:(UITextField *)textField { [self.textField resignFirstResponder]; return YES; } -(void)textFieldDidEndEditing:(UITextField *)textField { // 输入的如果不同于url容器中的内容,重新为其赋值 if(![self.textField.text isEqualToString:[self stringWithoutURLScheme:self.urlContainer.url]]) { NSString *urlString = [NSString stringWithFormat:@"hsun://%@", self.textField.text]; self.urlContainer.url = [NSURL URLWithString:urlString]; } } #pragma mark - String of url without scheme -(NSString *)stringWithoutURLScheme:(NSURL*)url { NSString *scheme = [[url scheme] stringByAppendingString:@"://"]; // 从scheme之后截取 return [[url absoluteString] substringFromIndex:scheme.length]; } #pragma mark - Handle received notifications -(void)reloadUrl { // 收到通知后加载收到的url NSURL *receivedUrl = [Utilities loadUrl]; if(receivedUrl) { self.urlContainer.url = receivedUrl; self.textField.text = [self stringWithoutURLScheme:receivedUrl]; } } -(void)saveWindowWillAppear { // 处理窗口将要呈现的通知 [self.textField resignFirstResponder]; } @end

    关于实现UIActivityItemSource的URL(文本)容器类,

    #import <Foundation/Foundation.h>
    
    @interface UrlContainer : NSObject<UIActivityItemSource>
    
    @property (nonatomic, strong) NSURL *url;
    -(instancetype)initWithUrl:(NSURL*)url;
    
    @end
    
    #import "UrlContainer.h"
    #import "UIImage+resize.h"
    
    @implementation UrlContainer
    
    -(instancetype)initWithUrl:(NSURL *)url
    {
        self = [super init];
        if(self)
        {
            self.url = url;
        }
        return self;
    }
    
    #pragma mark - UIActivityItemSource
    -(id)activityViewControllerPlaceholderItem:(UIActivityViewController *)activityViewController
    {
        // 占位,将要返回的类型
        return self.url;
    }
    
    -(id)activityViewController:(UIActivityViewController *)activityViewController itemForActivityType:(NSString *)activityType
    {
        // 直接返回容器的url
        return self.url;
    }
    -(UIImage*)activityViewController:(UIActivityViewController *)activityViewController thumbnailImageForActivityType:(NSString *)activityType suggestedSize:(CGSize)size
    {
        // 为item提供缩略图,大小为建议的大小
        // 用自定义的UIImage的Category resize 类方法处理图片为缩略图
        return [UIImage imageWithImage:[UIImage imageNamed:@"Beads.png"] scaledToFitToSize:size];
    }
    @end

    自定义的UIImage+resize

    #import <UIKit/UIKit.h>
    
    @interface UIImage (resize)
    
    +(UIImage*)imageWithImage:(UIImage*)image scaledToFitToSize:(CGSize)size;
    +(UIImage*)imageWithImage:(UIImage*)image scaledToFillToSize:(CGSize)size;
    
    @end
    
    #import "UIImage+resize.h"
    
    @implementation UIImage (resize)
    
    // 根据尺寸和矩形重绘图片
    +(UIImage*)imageWithImage:(UIImage*)image scaledToSize:(CGSize)size inRect:(CGRect)rect
    {
        if ([UIScreen mainScreen].scale == 2.0) {
            UIGraphicsBeginImageContextWithOptions(size, YES, 2.0);
        }
        else
        {
            UIGraphicsBeginImageContext(size);
        }
        [image drawInRect:rect];
        UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        
        return newImage;
    }
    
    +(UIImage*)imageWithImage:(UIImage *)image scaledToFitToSize:(CGSize)size
    {
        // 如果图片原尺寸已经小于要Scaled尺寸,不作处理
        if(image.size.height < size.height && image.size.width < size.width)
        {
            return [image copy];
        }
        
        // 根据缩放后的宽高,得到缩放比例
        CGFloat widthScaled = size.width / image.size.width;
        CGFloat heigtScaled = size.height / image.size.height;
        CGFloat scaledFactor = widthScaled > heigtScaled ? heigtScaled : widthScaled;
        
        // 缩放图片的尺寸
        CGSize scaledSize = CGSizeMake(image.size.width * scaledFactor, image.size.height * scaledFactor);
        return [UIImage imageWithImage:image scaledToSize:scaledSize inRect:CGRectMake(0.0, 0.0, scaledSize.width, scaledSize.height)];
    }
    
    +(UIImage*)imageWithImage:(UIImage *)image scaledToFillToSize:(CGSize)size
    {
        // 如果图片原尺寸已经小于要Scaled尺寸,不作处理
        if(image.size.height < size.height && image.size.width < size.width)
        {
            return [image copy];
        }
        
        // 根据缩放后的宽高,得到缩放比例
        CGFloat widthScaled = size.width / image.size.width;
        CGFloat heigtScaled = size.height / image.size.height;
        CGFloat scaledFactor = widthScaled > heigtScaled ? heigtScaled : widthScaled;
        // 缩放图片的尺寸
        CGSize scaledSize = CGSizeMake(image.size.width * scaledFactor, image.size.height * scaledFactor);
        
        CGPoint scaledPoint;
        widthScaled > heigtScaled ? (scaledPoint.y = (size.height - scaledSize.height)/2) : (scaledPoint.x = (size.width - scaledSize.height)/2);
        
        return [UIImage imageWithImage:image scaledToSize:size inRect:CGRectMake(scaledPoint.x, scaledPoint.y, scaledSize.width, scaledSize.height)];
    }
    
    @end

     接收:通过AirDrop接收URL(

    要想接收一个自定义了scheme的URL,app需要注册为能接收这个scheme。在项目的Target下的Info节点,有URL Types,在此注册, 或者用代码注册,详细可参考此链接http://www.cocoachina.com/industry/20140522/8514.html

    AirDrop接收到内容后会调用 UIApplication 的委托方法 application:openURL:sourceApplication:annotation,关于此方法的详细可以查看文档;

    #import "AppDelegate.h"
    #import "RootTableViewController.h"
    #import "Utilities.h"
    
    @interface AppDelegate ()
    
    @property (nonatomic, strong) UINavigationController *navController;
    @property (nonatomic, strong) RootTableViewController *rootTableViewController;
    @property (nonatomic, strong) UIWindow *saveReceivedWindow;
    
    @end
    
    @implementation AppDelegate
    
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        
        self.navController = [[UIStoryboard storyboardWithName:@"Main.stroyboard" bundle:nil] instantiateInitialViewController];
        if(self.navController)
        {
            self.rootTableViewController = [[self.navController viewControllers] firstObject];
        }
        
        return YES;
    }
    
    -(void)applicationDidBecomeActive:(UIApplication *)application
    {
        NSLog(@"%@", NSStringFromSelector(_cmd));
    }
    
    -(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
    {
        if (url) {
            //在此处理接收到的url
            // 需要校验收到的是否是app需要的。saveReceivedWindow是为了接收数据类型而设的变量
            if ([url.scheme isEqualToString:@"hsun"]) {
                // 保存url到文档中
                [Utilities saveUrl:url];
                // 广播收到URL的通知,如果UrlViewController处于显示状态则会收到此通知,然后重新从文档中加载新保存的url内容
                [[NSNotificationCenter defaultCenter] postNotificationName:@"ReceiveURLViewController" object:nil];
                
                //如果UrlViewController没有显示,调用根控制器显示
                if ([self.navController.visibleViewController isEqual:self.rootTableViewController] && !self.saveReceivedWindow) {
                    [self.rootTableViewController showUrlViewController];
                }
            }
        }
        return YES;
    }
  • 相关阅读:
    视觉里程计VO-直接法
    Linux安装libcholmod-dev找不到的解决方法
    Levenberg-Marquadt Method
    Gauss-Newton Method
    CMake
    方差 标准差 协方差
    SFM
    矩阵分解
    kvm学习笔记
    python学习笔记
  • 原文地址:https://www.cnblogs.com/1oo1/p/4184707.html
Copyright © 2020-2023  润新知