2019-07-25 11:32:09 weixin_42479468 阅读数 213

现象描述:

因某种特殊原因,导致抹去flash,导致默认启动至rommon模式下,效果如下:

解决方法:

1、首先准备一个FAT32格式的U盘。

2、将官方网站下载的iOS拷贝进U盘。

3、使用命令:dir 查看u盘名称,使用boot命令引导从u盘启用ios,(因为U盘iOS使用copy命令失败,所以在U盘引导启动,然后用户模式下ftp上传ios,boot引导即可。)

switch: boot usbflash0:c2960x-universalk9-mz.152-7.E0a.bin

4、交换机启动成功后,在用户模式下创建vlan svi地址,PC连接交换机,设置同一网段地址ping即可。

5、在PC开启ftp server服务,swith作为client,Cisco 2960 需配置ftp相关配置,(tftp传输速率实测太慢)如下:

Cisco# configure terminal
Cisco (config)# ip ftp username username 
Cisco (config)# ip ftp password password 
Cisco (config)# exit

 

6、在swith#模式下使用copy命令,将PC的IOS文件通过ftp传输copy至flash.(25M的IOS大概10分钟-20分钟)举例:

Switch#copy ftp: flash:c2960x-universalk9-mz.152-7.E0a.bin

Switch#Address or name of remote host []?(这里的地址是PC地址)

(ios名称)

(ios名称)

#建议使用dir命令查看一下,ios是否存在。

Switch#dir
Jul 25 11:28:04.050: %SYS-5-CONFIG_I: Configured from console by console
Directory of flash:/

    3  -rwx        3060  Jul 25 2019 10:46:52 +00:00  config.text
    4  -rwx        1918  Jul 25 2019 10:46:52 +00:00  private-config.text
    5  -rwx    26534912  Jul 25 2019 10:02:58 +00:00  c2960x-universalk9-mz.152-7.E0a.bin
    6  -rwx        3096  Jul 25 2019 11:18:55 +00:00  multiple-fs

122185728 bytes total (95425536 bytes free)

7、最后一步,在用户模式下使用boot命令引导即可,然后reload。举例:

Switch(config)#boot system c2960x-universalk9-mz.152-7.E0a.bin 

Switch(config)#exit

Switch#reload

 

 

 

 

 

 

 

2019-10-22 23:16:55 A45824430 阅读数 215

WLM3U 是一个用 Swift 实现的 M3U 工具。

项目地址 https://github.com/WillieWangWei/WLM3U

示例

clone 这个仓库,接着执行 pod install 命令,然后运行示例项目。

要求

iOS Swift
9.0 + 5.0 +

安装

WLM3U 可通过 CocoaPods 安装,只需将以下行添加到 Podfile 即可

pod 'WLM3U'

使用

解析 M3U 文件

let url = URL(string:"http://xxx.com/yyy.m3u8")! // M3U 文件的 URL
let size: Int = <#fileSize#>                     // 所有 ts 文件的总大小

WLM3U
    .attach(url: url, size: size, completion: { (result) in
        switch result {
        case .success(let model):
            model.name  // yyy
            model.tsArr // ts 文件数组
            ...
        case .failure(let error):
            print("attach failure " + error.localizedDescription)
        }
    })

下载 M3U 文件描述的 ts 文件

let url = URL(string:"http://xxx.com/yyy.m3u8")! // M3U 文件的 URL
let size: Int = <#fileSize#>                     // 所有 ts 文件的总大小

WLM3U
    .attach(url: url, size: size)
    .download(progress: { (progress, completedCount) in
        progress       // 当前下载的进度
        completedCount // 下载速度( B/S )
        
    }, completion: { (result) in
        switch result {
        case .success(let url):
            url // ts 文件所在的目录
        case .failure(let error):
            print("download failure " + error.localizedDescription)
        }
    })

将下载的 ts 文件合并成一个文件

let url = URL(string:"http://xxx.com/yyy.m3u8")! // M3U 文件的 URL
let size: Int = <#fileSize#>                     // 所有 ts 文件的总大小

WLM3U
    .attach(url: url, size: size)
    .download()
    .combine(completion: { (result) in
        switch result {
        case .success(let url):
            url // 合并完成后文件所在的目录
        case .failure(let error):
            print("combine failure " + error.localizedDescription)
        }
    })

自动获取 ts 文件总大小

WLM3U 支持自动获取所有文件的总大小,只需设置 calculateSize 参数即可:

let url = URL(string:"http://xxx.com/yyy.m3u8")! // M3U 文件的 URL

WLM3U
    .attach(url: url, calculateSize: true)
    .download()
    .combine()

获取大小的过程是异步的,可以通过接收 TaskGetFileSizeProgressNotificationTaskGetFileSizeCompletionNotification 来获取大小数据。

暂停与恢复任务

为了简化接口,WLM3U 没有 暂停恢复 的概念,它们和 取消添加 是一样的,所以:

需要暂停一个任务时,调用 cancel(url: URL)

需要取消一个任务时,调用 cancel(url: URL),并通过 folder(for url: URL) 获取到此任务缓存目录,并删除它即可。

需要添加一个任务时,调用 attach(url: URL)

需要恢复一个任务时,调用 attach(url: URL),如果本地存在之前的缓存,会自动继续下载剩余的文件。

监听状态

WLM3U 内置了几个状态的通知,你可以接收这些通知来处理数据:

/// 下载进度发生变化时会发出的通知。
public let TaskProgressNotification: Notification.Name

/// 获取文件总大小的进度发生变化时会发出的通知。
public let TaskGetFileSizeProgressNotification: Notification.Name

/// 获取文件总大小完成时会发出的通知。
public let TaskGetFileSizeCompletionNotification: Notification.Name

/// 任务完成时会发出的通知。
public let TaskCompletionNotification: Notification.Name

/// 任务发生错误时会发出的通知。
public let TaskErrorNotification: Notification.Name

播放下载的文件

AVPlayer 与 WLM3U 暂不支持播放本地 ts 文件,这里提供两个简单可行的替代方案。

使用 GCDWebServer 搭建本地服务

引入 GCDWebServer 库:

pod "GCDWebServer"

创建本地 HTTP 服务来提供下载好的 ts 文件:

let server = GCDWebServer()
let path = <#folderPath#> // ts 文件所在的本地目录
server.addGETHandler(forBasePath: "/",
                     directoryPath: path,
                     indexFilename: "file.m3u8",
                     cacheAge: 3600,
                     allowRangeRequests: true)
server.start()

使用 AVPlayer 来播放本地服务提供的 ts 文件:

let url = URL(string: "http://localhost:\(server.port)/file.m3u8")
let player = AVPlayer(url: url)

使用 FFmpeg 将 ts 文件转码成 mp4 文件

引入 mobile-ffmpeg-full 库:

pod "mobile-ffmpeg-full"

执行转码命令:

let command = "-i 'ts文件所在的路径' 'mp4文件要保存到的路径'"

let result = MobileFFmpeg.execute(command)

if result == RETURN_CODE_SUCCESS {
    // 转码完成
}

接下来直接播放转码得到的 mp4 文件即可。

作者

Willie, willie.wangwei@gmail.com

2016-10-19 11:23:40 CJXBShowZhouyujuan 阅读数 598

最近做了一个项目,需要和U3D的合作,第一次做这种项目,当两边都做完了工程,开始进行合并的时候,蒙 了,各种报错,不知所云。还好广大同行的无私奉献精神,帮我度过了难关。特此写下我的纠结路程,希望也可以帮助到遇到相同困难的你

版本介绍

U3D的版本5.4.1f
Xcode版本是8.0
这两个版本都是这时候最新的版本。

准备工作

我采用的是把U3D导出的iOS 导入到iOS工程中。

(1)一个运行都没有错误的U3DiOS工程
(2)一个运行都没有错误的iOSNative工程。
(3)一个真机,U3DiOS不做特殊处理必须在真机上进行测试,所以在编译的时候要选择设备。不然会报200个不知所云的错误。
(4)参考文档
[1]http://blog.csdn.net/dingxiaowei2013/article/details/52693421
[2]http://blog.csdn.net/dylan_lwb_/article/details/51452470#comments

开始干活了

(1)把U3D中的 Classes、Data、Libraries、MapFileParser.sh 文件先粘贴到iOSNative工程的根目录下
这里写图片描述

(2)注意这里几个文件的添加方式,如果添加方式错误了,会导致整合的彻底失败

Classes、Libraries、MapFileParser.sh 通过Add 添加到项目中,注意(选择Copy items if need 选择 Create groups)
我只有通过add添加是正确的,通过别的方式都是错误的

Data添加到项目中 (选择Copy items if needs,选中 Create folder references)这个不是通过add添加的,我的测试通过add添加是失败的。
这里写图片描述

(3)添加FrameWork

下面的这些都需要添加到iOS 原生工程中去。
注意:libiconv.2.dylib 这个的添加方法
Add other 然后全局搜索 command+shift+G 然后输入/usr/lib 查找就可以了
这里写图片描述

(4)添加runScript,这个在Xcode8的版本上不用写

这里写图片描述

(5)添加 Search Paths

这里写图片描述
这里写图片描述

(6)预处理文件.pch

需要把U3D和iOS的.pch文件整合为一个。可以通过 Prefix Header 查看工程中使用的是哪个.pch文件的路径

(7)other C Flags -> -DINIT_SCRIPTING_BACKEND=1

这里写图片描述

(8)添加User-Defined (UNITY_RUNTIME_VERSION版本号与导出工程的Unity版本号一致)

这里写图片描述

这里写图片描述

(9)将Classes/main.mm全部内容复制到iOS的main.m 并把iOS中的main扩展名改为.mm, 修改如下代码

然后要删除Classes/main.mm文件
在iOS的main.mm中做如下修改
这里写图片描述

(10)AppDelegate的修改

#import <UIKit/UIKit.h>
#import "UnityAppController.h"
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) UIWindow *unityWindow;
@property (strong, nonatomic) UnityAppController *unityController;
- (void)showUnityWindow;
- (void)hideUnityWindow;
@end
.m
- (UIWindow *)unityWindow {
    return UnityGetMainWindow();
}

- (void)showUnityWindow {

    [[UIApplication sharedApplication] setStatusBarHidden:YES];

    [self.unityWindow makeKeyAndVisible];
}

- (void)hideUnityWindow {

    [[UIApplication sharedApplication] setStatusBarHidden:NO];
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent animated:YES];

    [self.window makeKeyAndVisible];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
   //这里关于window的初始化一定要写
    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    self.window.backgroundColor = [UIColor whiteColor];

    SecondHouseTabBarController * second = [[SecondHouseTabBarController alloc]init];
    self.window.rootViewController = second;

    self.unityController = [[UnityAppController alloc] init];
    [self.unityController application:application didFinishLaunchingWithOptions:launchOptions];

    [self.window makeKeyAndVisible];

    return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {
    [self.unityController applicationWillResignActive:application];
}

- (void)applicationDidEnterBackground:(UIApplication *)application {

    [self.unityController applicationDidEnterBackground:application];
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
    [self.unityController applicationWillEnterForeground:application];
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
    [self.unityController applicationDidBecomeActive:application];
}

- (void)applicationWillTerminate:(UIApplication *)application {
    [self.unityController applicationWillTerminate:application];
}

这里写图片描述

(11)UnityAppController中的修改

在我的版本中并不会报错,但是不修改程序会一直在初始化UnityAppController的时候出错,说是rootWindow没有接受到实体

@interface UnityAppController : NSObject<UIApplicationDelegate>
{
    UnityView*          _unityView;
    CADisplayLink*      _displayLink;

    UIWindow*           _window;
    UIView*             _rootView;
    UIViewController*   _rootController;
    UIView*             _snapshotView;

    DisplayConnection*  _mainDisplay;

    // we will cache view controllers for fixed orientation
    // auto-rotation view contoller goes to index=0
    这里修改了。这个在Xcode8中不用修改
//  UnityViewControllerBase* _viewControllerForOrientation[5];
    UIViewController* _viewControllerForOrientation[5];

#if !UNITY_TVOS
    UIInterfaceOrientation  _curOrientation;
#endif

    id<RenderPluginDelegate>    _renderDelegate;
}

在UnityAppController.h文件中要做的修改

inline UnityAppController*  GetAppController()
{
    return [(UnityAppController*)[UIApplication sharedApplication]valueForKeyPath:@"delegate.unityController"];
}

(12)文件重复的错误

这里写图片描述

(13)升级到Xcode8的时候,出现了问题 .o文件的冲突(重复)

是因为 other link flage 中 写了 -all-load 这个去掉就可以 了

(14)删除Main.storyboard
移除Main interface中的默认Main

到此我的程序可以了,如果你的还有错误,就可以参考我的给出的参考文档。
并且其中一个参考文档是有Demo的。
后续再遇到什么问题,在更新这篇文字吧。

补充内容关于蓝色文件和黄色文件夹的区别

蓝色的是folder 黄色的是group。 那么它们有什么区别呢?

  1. group 和 folder的区别
    group 一般只在你的工程中是文件夹的形式,但是在本地的目录中还是以散乱的形式放在一起的,除非你是从外部以group的形式引用进来的。参与编译

folder 只能作为资源,整个引用进项目,不能编译代码,也就是说,以folder形式引用进来的文件,不能被放在complie sources列表里面。不参与编译

http://www.cnblogs.com/ygm900/p/3627501.html

2016-03-19 17:07:54 niuhailei 阅读数 9422

     之前做一个项目时,需要一个界面展示3D模型并进行交互。所以针对这个问题研究了很久,并总结了一些经验。在论坛中总遇到相同需求的人,也有很多人问我,所以写出这篇博客供大家参考。网上资料很少,即时有也比较模糊,所以接下来我尽量说的详细些,看完之后还有不懂得可以继续问我,QQ:1414819100.

   一、如果项目紧紧是展示3d模型,并进行简单的手势交互,这个时候,最好不要选择使用U3D和iOS混编,这个样做起来会比较麻烦,逻辑关系复杂,安全隐患严重。Opengl能很好的解决这个问题,iOS封装成GLView,用起来很简单实用(可以进行交互,缩放,旋转,增删,调整透视等)。附上Demo,弄懂里面的一些主要参数,变量,实现你要的效果不难。有参数不明白可以继续联系我,这个就不多说了,接下来讲解比较棘手的。

  

   二、项目要求3D效果比较绚丽,交互复杂,GLView已经不能满足我们的需求,这个时候我们可以考虑一下U3D和iOS混编。我把自己在这个过程中遇到的问题的感悟分享给大家。

         首先,Unity3d会导出一个工程文件,这个工程文件和我们的iOS项目结构很相似。拿到之后,用打开,并运行。如果遇到报错,

         ld: warning: path '/Users/MAC/Desktop/ZiTest/Libraries/libiPhone-lib.a' following -L not a directory
         ld: library not found for -liPhone-lib
         clang: error: linker command failed with exit code 1 (use -v to see invocation)

        不要紧张,虽然错很多,但只是一个问题。U3D导出的xcode工程文件不支持模拟器运行,换成真机运行,问题就没有了。如果真机感觉每次都是真机测试很麻烦,你可以让u3d导出一份可以模拟器运行的工程文件。

        也有可能你会不能选择模拟器,找到TARGETS---Build Settings---  Supported Platforms   改成iOS。

       解决混编的方法有很多种,总结起来就两大类,一个是u3d导入iOS,一个是iOS导入u3d中。这个可以看看我之前看的一些文章,试过好多,没有成功,大家可以参考下,即时不行,了解一下原理。版本不同,方法可能有些不同,但是原理是一样的。(目前自己找到资料仅仅只有这些,大家好好参考一下)

                          http://blog.sina.com.cn/s/blog_48a8af640102vh2q.html

                          http://segmentfault.com/q/1010000000392448
                         http://www.cnblogs.com/shawn-zp/p/3225477.html

                         原文:http://alexanderwong.me/post/29949258838/building-a-ios-unity-uiview-uiviewcontroller
                          翻译:http://blog.163.com/savage_cui/blog/static/64335507201332834915876/
                         补充:http://user.qzone.qq.com/1523511691/infocenter#!app=2&via=QZ.HashRefresh&pos=1375185802
                         其他参考:http://www.scio.de/en/blog-a-news/scio-development-blog-en/entry/iphone-a-unity3d-integrating-3rd-party-static-libraries-in-unity3d-generated-    

                                         xcode-projects


       u3d导入iOS中会比较麻烦一些,u3d产生的文件很大,setting的参数也要详细设置。

       iOS导入u3d中相对简单,下面介绍这个方法。

       打开u3d导出的xcode工程文件,运行一下。

   

                                                    文件是这个样子。

   运行的时候提示(报错200+个)

说明不支持模拟器运行,这个时候改用真机运行就可以了。最方便的办法就是让u3d导出可以真机运行的工程文件。

好了,能运行之后,拖入或者创建我们自己的ViewController。


打开Classes文件,找到UnityAppController(这个文件相当于我们认知的Appdelegate文件),找到这个方法,改变程序初始视图,由unityView改成我们自己的View。

改成这个样子:

- (void)applicationDidBecomeActive:(UIApplication*)application
{
    ::printf("-> applicationDidBecomeActive()\n");
    
    
    static dispatch_once_t disOnce;
    dispatch_once(&disOnce,  ^ {
    [self performSelector:@selector(startViewC:) withObject:application afterDelay:0];    
    });
    
    NSLog(@"_window22222222%@",_window.rootViewController);
//        [_snapshotView removeFromSuperview];
//        _snapshotView = nil;
    

    if(_unityAppReady)
    {
        if(UnityIsPaused())
        {
            UnityPause(0);
            UnityWillResume();
        }
        UnitySetPlayerFocus(1);
    }
    else if(!_startUnityScheduled)
    {
//        _startUnityScheduled = true;
//        [self performSelector:@selector(startUnity:) withObject:application afterDelay:0];
           }

    _didResignActive = false;
}

-(void)startViewC:(UIApplication *)application{

 //我们自己需要进入的视图

    MyViewController *root = [[MyViewController alloc] init];
    _window.rootViewController = root;
    //[UnityGetMainWindow() makeKeyAndVisible];
}

现在程序启动之后,首先进入的就是我们的视图了,接下来就是怎么在我们的视图中进入到u3d界面视图。[self.UnityAC startUnity:[UIApplication sharedApplication]];方法只能调用一次,所以我们需要设置全局变量观察是第几次启动u3d界面。



//第一次启动
-(void)firstStarUnity{
   [self.UnityAC startUnity:[UIApplication sharedApplication]];
}
//再次启动
-(void)againStarUnity{
    
    
    [self.UnityAC againStartUnity];
}

在UnityAppController里面实现再次启动打方法

//再次启动
-(void)againStartUnity{
    
   
    
    _window            = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    _window.rootViewController = _rootController;
    _unityView        = [self createUnityView];
    
    //[DisplayManager Initialize];
    _mainDisplay    = [DisplayManager Instance].mainDisplay;
    [_mainDisplay createWithWindow:_window andView:_unityView];
    
    [self createUI];
    [self preStartUnity];
    
    UnityPause(true);
    _didResignActive = YES;
    Profiler_UninitProfiler();
    
    NSLog(@"22222%@",_window.rootViewController);
    [self showGameUI];
    [self createDisplayLink];

    
    [[[UnityGetMainWindow() rootViewController] view] setHidden:NO];
//

    
        if (_didResignActive) {
        UnityPause(false);
        _didResignActive = NO;
    }
}



在UnityAppController---- (void)startUnity:(UIApplication*)application方法改成:

- (void)startUnity:(UIApplication*)application
{
    NSAssert(_unityAppReady == NO, @"[UnityAppController startUnity:] called after Unity has been initialized");

    _window            = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    _unityView        = [self createUnityView];
    
    //[DisplayManager Initialize];
    _mainDisplay    = [DisplayManager Instance].mainDisplay;
    [_mainDisplay createWithWindow:_window andView:_unityView];
    
    [self createUI];
    [self preStartUnity];
    
    
    UnityInitApplicationGraphics();

    // we make sure that first level gets correct display list and orientation
    [[DisplayManager Instance] updateDisplayListInUnity];

    UnityLoadApplication();
    Profiler_InitProfiler();

    [self showGameUI];
    [self createDisplayLink];

    UnitySetPlayerFocus(1);
}

现在我们就可从我们的界面进入u3d界面了,现在写在u3d退出后回到我们的界面中。

找到u3d预留的返回按钮的方法,在里面实现如何返回。在这里我没有用按钮,写在了UnityView.mm的touch的方法里。

在UnityAppController里实现:

//退出的方法
-(void)exitUnity{
    _window            = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    _unityView        = [self createUnityView];
    
    //[DisplayManager Initialize];
    _mainDisplay    = [DisplayManager Instance].mainDisplay;
    [_mainDisplay createWithWindow:_window andView:_unityView];
    
    [self createUI];
    [self preStartUnity];
    
    UnityPause(true);
    _didResignActive = YES;
    Profiler_UninitProfiler();
    NSLog(@"1111%@",_window.rootViewController);
    [[UnityGetMainWindow() rootViewController] view].hidden = YES;
//    _window            = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    self.myViewC = [[MyViewController alloc] init];
    _window.rootViewController = self.myViewC;
    NSLog(@"%@",self.window);
    NSLog(@"33333%@",_window.rootViewController);
    NSLog(@"%@",self.myViewC);
    
    //[UnityGetMainWindow() makeKeyAndVisible];
    
}


好了,现在就可以都实现了。本人目前还不是很精通,但经过好几天日夜的研究,基本的已经没有问题。欢迎各位优化,并通知我QQ:1414819100,谢谢!


GLview Demo下载地址:http://download.csdn.net/detail/niuhailei/9463994。

iOS,u3d混编Demo下载地址:https://yunpan.cn/cYX7fTFQXLeSc (提取码:ed6b)






2018-09-19 15:03:39 XZZ_2018 阅读数 891

在这里插入图片描述
大家好,才是真好的。前几天,苹果公司开始大面积推送IOS 12。不少人安利IOS 12的速度快,于是很多朋友忍不住点了升级。虽然电池的寿命还没人写评测,但IOS 12真的快啊,用得爽啊。

不过,问题也随之而来。有人在问升级了IOS 12之后,如采用IBM Notes Traveler描述文件配置的邮箱(即采用IOS上内置的邮箱App收发邮件),发现无法同步邮件,有报错发生。

这是怎么回事?好吧,一句话概括:因为Domino服务器上的HTTP基本验证没有正确地进行配置。具体来说,在Apple iOS 12以前版本,IOS设备在第一次请求时,会将用户凭证的方式发送HTTP认证到服务器上,以后只要凭证是正确的,无论服务器是采用HTTP 401响应还是采用表单的HTTP 200响应,都没有问题。

不过,从Apple iOS 12以后,设备不止会在第一次请求时发送HTTP认证头信息到服务器上——也就说,以后每次都要发送凭证到服务器上,如果服务器采用的是基本验证,设备会正常工作;但如果服务器采用表单验证,设备则不会正常工作了。

总而言之,现在我们得把Traveler服务器上验证方式改为基本验证来适应这种情况。如下图:
在这里插入图片描述
有人说,不行啊,我Traveler服务器上还有其他Web应用服务,变成基本认证后,其他应用会受影响。——完全没关系,现在可以创建一个Internet站点了,里面启动一下会话验证选项,而后创建一个重定向规则,凡是到/traveler*地址的,都覆盖会话验证即可,如下图:
在这里插入图片描述
大家有兴趣可参见:
https://www-01.ibm.com/support/docview.wss?uid=ibm10731987&myns=swglotus&mynp=OCSSYRPW&mync=R&cm_sp=swglotus--OCSSYRPW--R

当然,如果您采用的是IBM Verse App方式来访问邮件应该不会受到太大影响。

最后,还有童鞋问,IBM Traveler服务器什么版本支持IOS 12啊?答案是,官方支持的标准是IBM Traveler 9.0.1.18版本或更新版本都支持(需要Domino服务器版本为R9.0.1FP8或以上),如下图:
在这里插入图片描述
今天就写到这里,谢谢大家。

更多精彩内容可关注微信公众号:“协作者”
在这里插入图片描述

IOS U-Share SDK

阅读数 53

区分 ios与安卓

阅读数 53

没有更多推荐了,返回首页