zoukankan      html  css  js  c++  java
  • UIActivityViewController的相关用法(二)--NSData的发送和接收

    通过AirDrop发送一张图片或者一个文件,需要序列化实现了NSActivityItemSource的容器类实例,以NSData的数据格式传输。app发送/接收自定义的类型实例,还需要创建一个自定义的UTI,需要在Targets的info中添加两个节点:Document Types 和 Exported Type UTIs;

    1、Document Types:

    app注册此字段后可以接受自定义的UTI,同时这个字段也可以用来接收其他标准的UTI文件类型。

    2、Exported Type UTIs:通过此字段向系统注册此app的自定义UTI。

    发送被序列号容器类需要有两个选择:

    1、把对象写入到遵循自定义UTI的文件中,把文件的路径作为url传入到UIActivityVIewController中。

    2、序列化对象为NSData对象,把数据(NSData)对象传到UIActivityViewController,UIActivityViewController 会调用UIActivityItemSource的协议方法activityViewController:dataTypeIdentifierForActivityItemSource来确定自定义的UTI(将要使用的就是这种)。

    当AirDrop接收到一个自定义UTI的文件时,它会寻找在系统中注册过改UTI的app,如果有多个app注册过改UTI,会显示一个选择列表。选中app后,该app的UIApplication的委托方法 application:openURL:sourceApplication:annotation 会被调用,在这个方法中处理接收到的文件,接收到的文件被保存在Document/Inbox文件夹中,app只有读取和删除的权限,建议copy到自定义的路径中,以便做增删改的操作。

    发送:

    - (IBAction)shareAction:(id)sender {
        // 传入的虽然时item的容器类实例,实际UIActivityViewController会调用UIActivityItemSource协议方法把该实例序列化为NSData
        // 可以从容器类 Profile 中看到明细。
        UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:@[self.profile] applicationActivities:nil];
        if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) {
            [self presentViewController:activityViewController animated:YES completion:nil];
        }
        else
        {
            if(self.actionPopoverController.isPopoverVisible)
            {
                [self.actionPopoverController dismissPopoverAnimated:YES];
            }
            else
            {
                self.actionPopoverController = [[UIPopoverController alloc] initWithContentViewController:activityViewController];
                [self.actionPopoverController presentPopoverFromBarButtonItem:self.actionItem permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
            }
        }
    }

    容器类Profile:

    #import <Foundation/Foundation.h>
    
    @interface Profile : NSObject<NSSecureCoding, UIActivityItemSource>
    
    @property (nonatomic, copy) NSString *name;
    @property (nonatomic, strong) UIImage *image;
    @property (nonatomic, strong) UIImage *thumbnailImage;
    @property (nonatomic, copy) NSString *fileName;
    @property (nonatomic, assign) NSInteger imageContentMode;
    
    -(instancetype)initWithName:(NSString*)name image:(UIImage*)image;
    
    @end
    
    #import "Profile.h"
    #import "UIImage+resize.h"
    #import "Utilities.h"
    
    @implementation Profile
    
    // 初始化Profile的name和image
    -(instancetype)initWithName:(NSString *)name image:(UIImage *)image
    {
        self = [super init];
        if(self)
        {
            _name = name;
            // 设置图片的尺寸
            _image = [UIImage imageWithImage:image scaledToFitToSize:CGSizeMake(560, 470)];
        }
        return self;
    }
    
    // 属性fileName如果不存在,构造一个随机的名字
    -(NSString*)fileName
    {
        if (_fileName) {
            return _fileName;
        }
        
        _fileName = [NSString stringWithFormat:@"profile-%@.customprofile", [[[NSUUID UUID] UUIDString] substringWithRange:NSMakeRange(24, 12)]];
        return _fileName;
    }
    
    // 设置image的同时设置thumbnailImage
    -(void)setImage:(UIImage *)image
    {
        _image = [UIImage imageWithImage:image scaledToFitToSize:CGSizeMake(560, 470)];
        _thumbnailImage = [UIImage imageWithImage:image scaledToFitToSize:CGSizeMake(44, 44)];
    }
    
    // thumbnailImage不存在,现场构造
    -(UIImage*)thumbnailImage
    {
        if(_thumbnailImage)
            return _thumbnailImage;
        
        _thumbnailImage = [UIImage imageWithImage:_image scaledToFitToSize:CGSizeMake(44, 44)];
        return _thumbnailImage;
    }
    
    #pragma mark - NSCoding
    // NSSecureCoding 继承自NSCoding,所以必须实现NSCoding,同时该类的实例能够序列化为NSData数据类型以便传输
    -(void)encodeWithCoder:(NSCoder *)aCoder
    {
        [aCoder encodeObject:_name forKey:@"name"];
        [aCoder encodeObject:_image forKey:@"image"];
        [aCoder encodeObject:@(_imageContentMode) forKey:@"imageContentMode"];
    }
    -(instancetype)initWithCoder:(NSCoder *)aDecoder
    {
        Profile *profile = nil;
        NSString *name = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"name"];
        UIImage *image = [aDecoder decodeObjectOfClass:[UIImage class] forKey:@"image"];
        NSNumber *imageContentMode = [aDecoder decodeObjectOfClass:[NSNumber class] forKey:@"imageContentMode"];
        
        if(name && image && imageContentMode)
        {
            profile = [[Profile alloc] initWithName:name image:image];
            profile.imageContentMode = imageContentMode.integerValue;
        }
        return profile;
    }
    
    #pragma mark - NSSecureCoding
    +(BOOL)supportsSecureCoding
    {
        return YES;
    }
    
    #pragma mark - UIActivityItemSource
    -(id)activityViewControllerPlaceholderItem:(UIActivityViewController *)activityViewController
    {
        // 该类作为数据容器,最终是以NSData的数据类型发送的
        return [NSData data];
    }
    -(id)activityViewController:(UIActivityViewController *)activityViewController itemForActivityType:(NSString *)activityType
    {
        // 被序列化后的该对象作为item发送
        return [Utilities securelyArchiveRootObject:self];
    }
    -(NSString*)activityViewController:(UIActivityViewController *)activityViewController dataTypeIdentifierForActivityType:(NSString *)activityType
    {
        return @"com.hsun.customProfileUTI.customProfile";
    }
    
    -(UIImage*)activityViewController:(UIActivityViewController *)activityViewController thumbnailImageForActivityType:(NSString *)activityType suggestedSize:(CGSize)size
    {
        UIImage *scaledImage;
        if (self.imageContentMode == UIViewContentModeScaleToFill) {
            scaledImage = [UIImage imageWithImage:self.image scaledToFillToSize:size];
        }
        else
        {
            scaledImage = [UIImage imageWithImage:self.image scaledToFitToSize:size];
        }
        return scaledImage;
    }
    @end

     当同意接收AirDrop发送的数据后,若设备已经注册了该UTI的app,会用此app打开(多个的话会让选择),调用app的应用委托方法来处理接收的数据:

    // 处理接收的数据
    -(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
    {
        if (url) {
            //当同意接受AirDrop发送的文件后,AirDrop会自动查询注册了UTI的app,找到之后就把文件放到
            // Document/Inbox 文件夹下面(不存在该UTI的app则会自动跳转到ItuneStore搜做符合此UTI的app)
            // 读取接收到的文件,并处理(同接收URL处理的不同之处就是这里,从inbox中读取接收到的文件,这个文件是序列化后的数据文件)
            NSString *path = [url path];
            Profile *profile = [Utilities securelyUnarchiveProfileWithPath:path];
            if(profile)
            {
                //用接收到的数据做想做的事情。。。
            }
            
            // 删除放在 Document/Inbox 下接收到的文件
            [[NSFileManager defaultManager] removeItemAtPath:path error:nil];
        }
        return YES;
    }

     

     

  • 相关阅读:
    SharePoint Framework (SPFx) 开发入门教程
    SharePoint 2013 Designer 入门教程
    SharePoint 2013 开发教程
    SharePoint 2013 入门教程
    SharePoint Online 部署SPFx Web部件
    SharePoint Online SPFx Web部件绑定数据
    SharePoint Online 创建SPFx客户端Web部件
    SharePoint Online 配置框架(SPFx)开发环境
    SharePoint Online 创建应用程序目录
    SharePoint Online 启用 IRM
  • 原文地址:https://www.cnblogs.com/1oo1/p/4186885.html
Copyright © 2011-2022 走看看