阅读更多
科技博客网站MacStories日前发表费德里科•维迪奇(Federico Viticci)撰写的评论文章称,虽然苹果iCloud云存储服务已推出半年,并且正在形成自己的生态系统,但其开发文档与API存在诸多不足之处,使得第三方应用开发商很难在其应用中整合iCloud,同时也给用户带来了一定困扰。


以下是原文主要内容:

2011年10月12日,苹果公司推出了iCloud云存储服务,它能帮助成千上万iOS设备用户实现跨设备数据同步,并被苹果CEO蒂姆•库克(Tim Cook)称为公司未来十年内的一大战略。时至今日,问世六个月的iCloud已经拥有了8500万用户,它为用户同步邮件、联系人、通讯录以及苹果应用所访问的其他数据带来了极大便利,但是对于第三方应用开发商来说,在应用中采用iCloud同步及存储功能却有点“麻烦”。

iCloud的“无缝式”同步

Smile公司推出的PDFpen是一款PDF编辑应用,它在Mac与iOS两大平台上都支持iCloud云同步。Smile创始人菲利普•戈沃德(Philip Goward)表示,iCloud在处理文件、文件夹以及文件冲突上有着非凡表现。PDFpen的一大优势,是其所提供的Mac电脑与iPad平板电脑之间的无缝式编辑体验。Smile在今年一月推出的iPad版PDFpen,是率先利用iCloud将用户文档同步至Mac桌面电脑的iPad版PDF阅读编辑应用之一。

尽管支持iCloud的应用越来越多,但是它们的数量增长并未呈现出“井喷”之势。其他一些利用iCloud实现文档与数据跨设备无缝存储的iPhone及iPad应用,还包括播客订阅应用Instacast和Downcast(通过iCloud同步播客列表与播放进度)、文字编辑工具Byword(支持Dropbox与iCloud这两大云存储服务)与iA Writer(可在Mac桌面电脑上打开iCloud文档,但与Byword不同的是,它没有专门的文件管理窗口界面)等等。

以上是几款知名度较高的应用,不过苹果应用商店中支持iCloud的应用其实并不算少。苹果甚至在Mac应用商店的“Better Together”(合用更佳)一栏中设立了一个子类,用来展示那些可通过iCloud与其iOS版姊妹应用进行通讯的桌面应用。

支持iCloud的应用无需用户进行手动文件传输即可完成跨设备同步,其便利性备受用户喜爱。第三方iOS及Mac应用一旦恰当地整合了iCloud,就能为用户带来更自然、更连贯的使用体验,让他们无需频频拷贝文件,也无需一换设备就重新对应用进行偏好设置。对于游戏开发商而言,iCloud尤其能起到锦上添花的作用。越来越多的游戏开发商将iCloud作为游戏进度跨设备同步的平台。

文档缺乏深入性

尽管对于终端用户而言,iCloud似乎是“无缝的”、“自动的”,但是它背后隐藏了很多复杂的过程。第三方开发商在开发支持iCloud的“Better Together”iOS及OS X应用时,常常要花费大量精力来摸索整合iCloud的最佳方法与技术。

史蒂夫•乔布斯在2011年苹果全球开发者大会(WWDC 2011)上发布iCloud时,曾经说到第三方开发商可以通过苹果稍后推出的一系列API对iCloud大加利用。但是一转眼大半年过去了,开发商们依然很难使其既有应用全面支持iCloud。

“最初的文档在很多方面存在欠缺,但它已经有所改进。苹果可以提供更多适用于Mac和iOS的代码案例,以帮助开发人员进行正确操作,并了解哪些地方可能会出现性能或可靠性问题。”文字编辑工具Byword的开发商如是说。

其他开发者也有类似想法:“现有文档太宽泛,对如何使用iCloud高谈阔论,但没有深挖技术细节。如果能对具体应用以及问题处理进行详细说明,改进后的文档将会更受欢迎。

苹果为iCloud编写的开发者文档,在程序编写与用户体验设计方面都欠缺深入性,并缺乏具体应用案例。开发商称,文档不应只说明iCloud如何从技术上处理以上情况,而是应当告诉开发人员该如何优化自己的界面和工作流程,从而不妨碍用户的体验。

此外,所有MacStories联系到的开发商也都表示,希望iCloud能推出调试工具以及更好的冲突解决办法。他们认为,“出色的调试工具”甚至会比文档更有用,这些工具可以帮助开发人员在其应用中对iCloud进行测试,从而“检测自己的容器,并监测其数据如何被保存至云端”。

因为正如其中一位开发者所说,iCloud说到底只是一个“装满了文件的文件夹”,当启用iCloud的应用出现问题时,开发人员应当弄清楚“黑盒子”里到底发生了什么。很多时候,客户遇到iCloud云同步方面的问题时,开发人员能给出的建议只是重启设备而已。

文件管理有待改进

云端的文件夹内存储着大量的文件。这些文件有时会被某个应用正常无误地拾取——不过被拾取的文件有时也会过多。

对于iCloud,苹果采用了一种自动解决文件冲突的技术,即:当同一文件的多个副本之间出现冲突时,总是选择“最好”的那个文件版本。和所有不给用户决定权的技术一样,这一技术可能会引发一些问题,如选错文件等。

为了防止应用和用户由于iCloud的“自作主张”而意外丢失文件,开发人员希望苹果能推出更好的可视冲突解决接口,以及用于在iOS设备上管理文档修订的“版本浏览器”。另一大热门云存储服务Dropbox允许开发人员通过API实现修订,而且苹果自己已经在Mac OS X Lion系统上实现了文档版本的轻松查看,那么为何不将其推广到iOS上呢?不过苹果似乎准备在新一代Mac操作系统Mountain Lion中应用新的文件保存界面,以此增强对iCloud的整合,所以今年晚些时候问世的新版iOS系统在iCloud文件管理方面或许会有所改进。

用户总体认可,对其又爱又恨

在当今所有移动平台当中,iOS的用户一直都是最乐于接受更新的,其最好的证据就是iOS推出新系统或开发商公开推出应用升级后的“采用率”数据。苹果推出iOS 5之后,用户们理所当然地留意那些整合了iCloud的新版应用,但是文件丢失、数据库损坏的故事屡见不鲜,让很多人对iCloud暂时持怀疑态度。

开发商普遍认为,当用户“喜爱”iCloud、它也很好用的时候,iCloud整合就在过去几个月内迅速成为头号支持请求来源;但是当iCloud出现问题、无法工作时,用户会感到沮丧、懊恼,而开发商没有恰当的调试工具和详细的报错消息,几乎爱莫能助。

开发商称,在应用中整合iCloud让用户“又爱又恨”:他们既喜欢“神奇的跨设备无缝同步”,又抱怨在同步方面遇到问题(如文件同步用时过长或无法同步等等)时经常需要禁用/启用iCloud或重启设备。虽然用户“总体上认可”iCloud的整合,但是API中存在的一些漏洞,让一些用户无法正常使用。

展望未来:可改进之处太多

当iCloud出现故障时,对其不稳定性深感郁闷的人显然不只是iOS和Mac用户。开发人员也希望苹果能给他们更好的工具来帮助其客户找出iCloud有时无法同步的原因。

对iCloud的未来进行猜测时,我只能说,这一平台还有太多值得改进之处,苹果可以对它做出改进并为用户提供内容与数据跨设备、跨平台无缝同步存储的新途径。我们已经提出了一些苹果应考虑在iOS 6中添加的功能。不过对于iCloud的API,一些非常基本的补充就能派上用场,就能方便开发商创建整合iCloud的应用,以及为购买此类应用的客户提供支持服务。

除了更多文档及代码示例、调试工具以及更好的冲突解决技术之外,简单的报错消息和同步状态指示工具可以简单而有效地让用户确认iCloud的工作状态,以及无法实现同步的原因。以上目的,可由“文件同步至iCloud时显示通知消息”实现,也可由“提供同步状态信息的API”实现。而一位开发者表示,他最希望看到的新功能,是“显示某应用之前是否曾被同步至iCloud”。

苹果还可考虑在未来iCloud API中增加其他一些东西,例如支持“delta”变化可以“避免每次添加、删除或移动文件时都‘折腾’整个iCloud容器”(Dropbox最近在其SDK中增加了“delta”命令);此外,Dropbox式的文件夹(添加的东西自动保存至云端,并加载至使用该容器的所有应用)“可以大大降低编写支持iCloud的应用的入门壁垒”。

终将形成“云生态”

过去六个月中,iCloud作为被苹果寄予厚望的平台以及开发人员可以用于其应用的同步技术,正在形成一个更直观、更连贯的应用生态系统,以保障用户的内容随时随地同步更新。

过去六个月还表明,如果没有合适的开发者工具以及对后端原理的清晰解释,事情就会变得很麻烦。事实上,一些开发商目前已经彻底放弃了iCloud应用的创建,还有一些开发商则希望新的API能让iCloud更适合他们的需要,而那些已经在应用中整合iCloud的开发商从用户那里得到的反馈,也是喜忧掺半。

尽管如此,苹果无疑正在通过iCloud酝酿一场深刻的变革,让我们的设备和应用成为一个天衣无缝的巨大生态系统。苹果iCloud给广大用户和开发人员带来了系统级的一体化云同步。虽然完全基于iCloud的第三方应用尚且不多,而且苹果应当加大对此类应用的宣传力度,但iCloud无疑是苹果的长远利益之所在。

Via Macstories
  • 大小: 31.8 KB
来自: 搜狐IT
0
0
评论 共 2 条 请登录后发表评论
2 楼 linzcup 2013-09-05 20:11
icloud客户端API官网:http://www.huluwa.org/icloud/index.html
1 楼 linzcup 2013-09-05 20:11
http://www.huluwa.org/icloud/index.html
icloud客户端API,支持C#,JAVA,
本文主要面向使用DateSync的开发者,开发者可通过此文学习如何使用DateSync SDK进行开发。

开发环境
1.安装Microsoft Visual C# 2008/2010
2.安装Microsoft .NET Framework 3.5
3.请将以下DLL文件加入到项目中(以下文件位于DataSyncSDK安装路径下)
DLL文件:
agsXMPP.dll
CE.iPhone.PList.dll
DataSync.dll
log4net.dll
Newtonsoft.Json.dll

主要类介绍
名称
说明
DataSyncObject
DateSync SDK的核心类,通过调用该类中的login,put,get,delete等方法实现在icloud中对联系人,相片流等功能进行操作。
Context
DataSyncObject类中的方法参数都通过该类传入值,传出处理结果。
如何使用DataSync SDK
首先导入DataSync.dll文件到工程中

1.用户登陆

using DataSync;

static void Main()
{

    DataSyncObject ds = new DataSyncObject();//创建DataSyncObject对像
    ds.gIcloud = new Cloud();//生成gIcloud对像

        Context loginctx = new Context();//生成Context对像
    loginctx.loginUsername = "apple id ";//输入icoud 帐号
    loginctx.loginPassword = "password";//输入icoud 帐号密码
    loginctx.modeType = Context.ICLOUD_MODE;//输入Context参数的模块类型,当前设为登陆到icloud服务器上
    bool ret = ds.login(loginctx);//登陆icoud,成功返回true,失败返回false;
    if (ret == false)
     {
         return;
     }
}



2.相片下载

using DataSync;

//进度条回调函数
//参数:transfered已传输字节数, total 表示总字节数
//返回值: true:中断传输,false:继续传输
public static bool TransferProgress(int transfered,int total)
{

return false;
}

static void Main()
{

    DataSyncObject ds = new DataSyncObject();//创建DataSyncObject对像
    ds.gIcloud = new Cloud();//生成gIcloud对像

            Context loginctx = new Context();//生成Context对像
    loginctx.loginUsername = "apple id ";//输入icoud 帐号
    loginctx.loginPassword = "password";//输入icoud 帐号密码
    loginctx.modeType = Context.ICLOUD_MODE;//输入Context参数的模块类型,当前设为登陆到icloud服务器上
    bool ret = ds.login(loginctx);//登陆icoud,成功返回true,失败返回false;
    if (ret == false)
     {
         return;
     }
   
    //登陆后,便可以下载相片

    Context getctx ;
    List<FileNode> files = ds.gIcloud.getPhotoList();//登陆成功后,通过该方法取得需要下载的文件列表
    foreach (FileNode item in files)
    {
        getctx = new Context();
        getctx.transferProgresscallback = new TransferProgressCallBack(TransferProgress);//进度条回调接口
        getctx.modeType = Context.ICLOUD_PS_MODE;//指定要操作的模块为相片流模块
        getctx.inItem = item;//要下载的文件节点
        ds.get(getctx);//下载文件
        if (getctx.outItem != null)
        {
            Console.Write("\n\n file " + getctx.outItem.filename + "down success.");
        }
    }
}

3.上传相片

using DataSync;

//进度条回调函数
//参数:transfered已传输字节数, total 表示总字节数
//返回值: true:中断传输,false:继续传输
public static bool TransferProgress(int transfered,int total)
{

return false;
}

static void Main()
{

    DataSyncObject ds = new DataSyncObject();//创建DataSyncObject对像
    ds.gIcloud = new Cloud();//生成gIcloud对像

                          Context loginctx = new Context();//生成Context对像
    loginctx.loginUsername = "apple id ";//输入icoud 帐号
    loginctx.loginPassword = "password";//输入icoud 帐号密码
    loginctx.modeType = Context.ICLOUD_MODE;//输入Context参数的模块类型,当前设为登陆到icloud服务器上
    bool ret = ds.login(loginctx);//登陆icoud,成功返回true,失败返回false;
    if (ret == false)
     {
         return;
     }
   
    //登陆后,便可以上传相片

    Context putctx = new Context();
    putctx.transferProgresscallback = new TransferProgressCallBack(TransferProgress);
    putctx.srcFileFullName = "e:/ndphoto/IMG_0255.JPG";//指定要上传的文件
    putctx.modeType = Context.ICLOUD_PS_MODE;
    ret = ds.put(putctx); //上传一张相片,最大不能超过50M
    if (ret)
    {
        Console.Write("\n\n file put success. ");
    }

}

4.删除图片

using DataSync;

static void Main()
{

    DataSyncObject ds = new DataSyncObject();//创建DataSyncObject对像
    ds.gIcloud = new Cloud();//生成gIcloud对像

    Context loginctx = new Context();//生成Context对像
    loginctx.loginUsername = "apple id ";//输入icoud 帐号
    loginctx.loginPassword = "password";//输入icoud 帐号密码
    loginctx.modeType = Context.ICLOUD_MODE;//输入Context参数的模块类型,当前设为登陆到icloud服务器上
    bool ret = ds.login(loginctx);//登陆icoud,成功返回true,失败返回false;
    if (ret == false)
     {
         return;
     }

    Context delctx = new Context();
    delctx.srcFileFullName = "e:/ndphoto/IMG_0260.JPG";//要删除的图片
    delctx.modeType = Context.ICLOUD_PS_MODE;
    ret = ds.delete(delctx); //删除图片
    if (ret)
    {
    Console.Write("\n\n file delete success. ");
    }

}

5.获取所有联系人列表

using DataSync;

static void Main()
{

    DataSyncObject ds = new DataSyncObject();//创建DataSyncObject对像
    ds.gIcloud = new Cloud();//生成gIcloud对像

    Context loginctx = new Context();//生成Context对像
    loginctx.loginUsername = "apple id ";//输入icoud 帐号
    loginctx.loginPassword = "password";//输入icoud 帐号密码
    loginctx.modeType = Context.ICLOUD_MODE;//输入Context参数的模块类型,当前设为登陆到icloud服务器上
    bool ret = ds.login(loginctx);//登陆icoud,成功返回true,失败返回false;
    if (ret == false)
     {
         return;
     }

    Context ctx = new Context();
    ctx.modeType = Context.ICLOUD_CONTACT_MODE;
    ds.get(ctx);//结果存在ctx.outContactList中
    List<Contact> contactList = ctx.outContactList;

}



6.删除所有联系人

using DataSync;

static void Main()
{

    DataSyncObject ds = new DataSyncObject();//创建DataSyncObject对像
    ds.gIcloud = new Cloud();//生成gIcloud对像

    Context loginctx = new Context();//生成Context对像
    loginctx.loginUsername = "apple id ";//输入icoud 帐号
    loginctx.loginPassword = "password";//输入icoud 帐号密码
    loginctx.modeType = Context.ICLOUD_MODE;//输入Context参数的模块类型,当前设为登陆到icloud服务器上
    bool ret = ds.login(loginctx);//登陆icoud,成功返回true,失败返回false;
    if (ret == false)
     {
         return;
     }

    ICloudContact iCloudContact = ds.icloud.GetContacts(); 
    Context ctx = new Context();
    ctx.contactList = iCloudContact.contacts;
    ctx.modeType = Context.ICLOUD_CONTACT_MODE;    
    ds.delete(ctx);//删除所有联系人
    List<Contact> contactList = ctx.outContactList;
}

7.增加联系人

using DataSync;

static void Main()
{

    DataSyncObject ds = new DataSyncObject();//创建DataSyncObject对像
    ds.gIcloud = new Cloud();//生成gIcloud对像

    Context loginctx = new Context();//生成Context对像
    loginctx.loginUsername = "apple id ";//输入icoud 帐号
    loginctx.loginPassword = "password";//输入icoud 帐号密码
    loginctx.modeType = Context.ICLOUD_MODE;//输入Context参数的模块类型,当前设为登陆到icloud服务器上
    bool ret = ds.login(loginctx);//登陆icoud,成功返回true,失败返回false;
    if (ret == false)
     {
         return;
     }

     //增加联系人
    List<Contact> contacts = new List<Contact>();
    Contact contact = new Contact { prefix = "pre", firstName = "aaa",
    lastName = "bbb", middleName = "ccc",phoneticLastName = "",
    phoneticFirstName = "Nicolas",suffix = "suff",nickName = "nickname",
    jobTitle = "jobTitle", department = "systemSport", companyName = "nd",
    birthday = "1999-01-01",notes = "测试添加一个完整的联系人"
    };
    ////电话
    contact.phones = new List<Phone>();
    Phone phone1 = new Phone { label = "WORK", field = "13635260966" };
    Phone phone2 = new Phone { label = "HOME", field = "059122321966" };
    Phone phone3 = new Phone { label = "custum", field = "15918726583" };
    contact.phones.Add(phone1);
    contact.phones.Add(phone2);
    contact.phones.Add(phone3);

    ////邮件
    contact.emailAddresses = new List<EmailAdr>();
    EmailAdr emailAdr1 = new EmailAdr { label = "WORK", field = "test_1@yahoo.com.cn" };   
    EmailAdr emailAdr2 = new EmailAdr { label = "HOME", field = "test_2@gmail.com" };
    EmailAdr emailAdr3 = new EmailAdr { label = "custum", field = "test_3@me.com" };
    contact.emailAddresses.Add(emailAdr1);
    contact.emailAddresses.Add(emailAdr2);
    contact.emailAddresses.Add(emailAdr3);

    ////地址
    contact.streetAddresses = new List<StreetAdr>();
   
    StreetField streetField1 = new StreetField();
    streetField1.city = "city";
    streetField1.country = "country";
    streetField1.state = "state";
    streetField1.street = "street";
    streetField1.countryCode = "countryCode";
    StreetAdr streetAdr1 = new StreetAdr { label = "HOME", field = streetField1 };

    StreetField streetField2 = new StreetField();
    streetField1.city = "city";
    streetField1.country = "country";
    streetField1.state = "state";
    streetField1.street = "street";
    streetField1.countryCode = "countryCode";
    StreetAdr streetAdr2 = new StreetAdr { label = "WORK", field = streetField2 };

    StreetField streetField3 = new StreetField();
    streetField1.city = "city";
    streetField1.country = "country";
    streetField1.state = "state";
    streetField1.street = "street";
    streetField1.countryCode = "countryCode";
    StreetAdr streetAdr3 = new StreetAdr { label = "custum", field = streetField3 };
    contact.streetAddresses.Add(streetAdr1);
    contact.streetAddresses.Add(streetAdr2);
    contact.streetAddresses.Add(streetAdr3);

    ////主页
    contact.urls = new List<Url>();
    Url url1 = new Url { label = "WORK", field = "www.sina.com" };
    Url url2 = new Url { label = "HOME", field = "www.apple.com" };
    Url url3 = new Url { label = "custum", field = "www.google.com" };
    contact.urls.Add(url1);
    contact.urls.Add(url2);
    contact.urls.Add(url3);

    ////概况
    contact.profiles = new List<Profile>();
    Profile profile1 = new Profile { label = "Facebook", field = "http://twitter.com",user = "sdfdf" };
    Profile profile2 = new Profile { label = "custum", field = "http://facebook.com",user = "jjjjjj" };
    contact.profiles.Add(profile1);
    contact.profiles.Add(profile2);

    ////日期
    contact.dates = new List<Date>();
    Date date1 = new Date { label = "other", field = "2011-01-01" };
    Date date2 = new Date { label = "custum", field = "2012-01-01" };
    contact.dates.Add(date1);
    contact.dates.Add(date2);

    ////相关人
    contact.relatedNames = new List<RelatedName>();
    RelatedName relatedName1 = new RelatedName { label = "other", field = "father" };
    RelatedName relatedName2 = new RelatedName { label = "custum", field = "brother" };
    contact.relatedNames.Add(relatedName1);
    contact.relatedNames.Add(relatedName2);

    ////通讯
    contact.IMs = new List<IM>();

    IMsfield iMsfield1 = new IMsfield();
    iMsfield1.IMService = "QQ";
    iMsfield1.userName = "qqusername";
    IMsfield iMsfield2 = new IMsfield();
    iMsfield2.IMService = "Facebook";
    iMsfield2.userName = "testname";

    IM iMs1 = new IM { label = "QQ", field = iMsfield1 };
    IM iMs2 = new IM { label = "weibo", field = iMsfield2 };
    contact.IMs.Add(iMs1);
    contact.IMs.Add(iMs2);

    contacts.Add(contact);
    Context ctx = new Context();
    ctx.modeType = Context.ICLOUD_CONTACT_MODE;
    ctx.contactList = contacts;
    ds.put(ctx);
}

8.修改联系人

using DataSync;

static void Main()
{

    DataSyncObject ds = new DataSyncObject();//创建DataSyncObject对像
    ds.gIcloud = new Cloud();//生成gIcloud对像

    Context loginctx = new Context();//生成Context对像
    loginctx.loginUsername = "apple id ";//输入icoud 帐号
    loginctx.loginPassword = "password";//输入icoud 帐号密码
    loginctx.modeType = Context.ICLOUD_MODE;//输入Context参数的模块类型,当前设为登陆到icloud服务器上
    bool ret = ds.login(loginctx);//登陆icoud,成功返回true,失败返回false;
    if (ret == false)
     {
         return;
     }

    //修改联系人
    Context ctx = new Context();
    ctx.modeType = Context.ICLOUD_CONTACT_MODE;
    ds.get(ctx);
    List<Contact> contactList = ctx.outContactList;
    List<Contact> contacts = new List<Contact>();
    Contact contact = contactList[0];
    contact.firstName = "aaa";
    contact.lastName = "bbb";
    contact.phones = new List<Phone>();
    Phone phone = new Phone { label = "WORK", field = "987654321" };
    contact.phones.Add(phone);
    contacts.Add(contact);
    Context ctx = new Context();
    ctx.modeType = Context.ICLOUD_CONTACT_MODE;
    ctx.contactList = contacts;
    ds.updata(ctx);

}

9.删除指定联系人

using DataSync;

static void Main()
{

    DataSyncObject ds = new DataSyncObject();//创建DataSyncObject对像
    ds.gIcloud = new Cloud();//生成gIcloud对像

    Context loginctx = new Context();//生成Context对像
    loginctx.loginUsername = "apple id ";//输入icoud 帐号
    loginctx.loginPassword = "password";//输入icoud 帐号密码
    loginctx.modeType = Context.ICLOUD_MODE;//输入Context参数的模块类型,当前设为登陆到icloud服务器上
    bool ret = ds.login(loginctx);//登陆icoud,成功返回true,失败返回false;
    if (ret == false)
     {
         return;
     }

    //删除联系人
    Context ctx = new Context();
    ctx.modeType = Context.ICLOUD_CONTACT_MODE;
    ds.get(ctx);
    List<Contact> contactList = ctx.outContactList;
    List<Contact> delContacts = new List<Contact>();
    Phone phone = new Phone { label = "WORK", field = "15935260966" };
    Contact contact = contactList[0];
    delContacts.Add(contact);
    Context ctx = new Context();
    ctx.modeType = Context.ICLOUD_CONTACT_MODE;
    ctx.contactList = delContacts;
    ds.delete(ctx);
}

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • 苹果开发者计划许可协议(2017年5月2日)

    在下载或使用苹果软件或苹果服务之前,请仔细阅读以下APPLE开发者计划许可协议条款和条件。这些条款和条件构成了您与苹果之间的法律协议。    苹果开发者计划许可协议 目的 您希望使用Apple Software(如下所...

  • iCloud和Core Data

    本文转自Di Wu's blog,原文:iCloud ...当乔布斯第一次在苹果全球开发大会上介绍iCloud的时候,他将无缝同步的功能描述的太过完美,以至于让人怀疑其是否真的能实现。但当你在iOS 5和iOS 6系统中尝试

  • iOS开发工具,ios开发类库

    ,iosUI组件介绍,iOS开发常用工具整理,ios开发总结 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SDWebImage多个缩略图缓存组件 UICKeyChainStore存放用户账号密码组件 ...

  • iOS开发之swift资料大全

    目录(?)[+] 版本:Swift ...1. 将Swift从Objective-C混合的md文件中抽出(正在进行…) 使用方法:根据目录关键字搜索,记得包含@,以保证搜索目录关键字的唯一性。 问题反馈:请广大网

  • iOS开发 非常全的三方库、插件、大牛博客等等

    - FXLabel是一个功能强大使用简单的类库,通过提供一个子类改进了标准的UILabel组件,为字体增加了阴影、内阴影和渐变色等,可以被用在任何标准的UILabel中。FXLabel还提供了更多控件,可以对字体行距、字体间距等...

  • iOS开发第三方库汇总

    - FXLabel是一个功能强大使用简单的类库,通过提供一个子类改进了标准的UILabel组件,为字体增加了阴影、内阴影和渐变色等,可以被用在任何标准的UILabel中。FXLabel还提供了更多控件,可以对字体行距、字体间距等...

  • iOS 2015年3月苹果新的审核标准(中文)

    iOS开发者计划许可协议目的你想用苹果软件(定义见下文)制定的一个或多个应用程序(定义见​​下文),运行iOS和OS关注的苹果品牌产品。苹果愿意给你一个有限的许可使用苹果软件开发和对本协议规定的条款和条件,...

  • 2015年3月苹果新的审核标准(中文)

    请阅读以下许可协议的条款和条件之前仔细下载或使用Apple软件。这些条款和条件构成了您与苹果的法律协议。 的iOS开发者计划许可协议 ...本协议项下开发的应用程序可以分布在四个方面:(1)通过Ap

  • iOS:iOS开发非常全的三方库、插件等等

    iOS开发非常全的三方库、插件等等 github排名:https://github.com/trending, github搜索:https://github.com/search. 此文章转自github:https://github.com/Tim9Liu9/TimLiu-iOS 一、UI 下拉刷新 ...

  • iOS开发最常用三方库集合Swift版(三方库、插件、博客等等)

    Swift学习资料@ SwiftGuide很赞 的Swift...Swift 30 Projects- 最新 Swift 3.0 的30个小App,更注重代码规范和架构设计(故胤道长) V2ex-Swift- 用 Swift 写的 V2EX 客户端。 iBBS-Swift- “新手开源一个用Swift...

  • iOS开发指南:从零基础到App Store上架(第2版 )

    第一部分 基础篇  第1章 开篇综述 2 ... 1.2 开发环境及开发工具 3  1.3 本书中的约定 4  1.3.1 案例代码约定 4  1.3.2 图示的约定 5  第2章 第一个iOS应用程序 7  2.1 创建基于nib的HelloWorld工程

  • 在互联网上,没有人知道你是一条狗?

    这则漫画中有两只狗:一只黑狗站在电脑椅上,爪子扶着键盘。它望向站在地上、表情迷茫的另一只狗,兴奋地说:「在互联网上,没人知道你是一条狗。 (On the Internet, nobody knows you’re a dog.)画中那只狗的...

  • iOS开发之资料收集

    - FXLabel是一个功能强大使用简单的类库,通过提供一个子类改进了标准的UILabel组件,为字体增加了阴影、内阴影和渐变色等,可以被用在任何标准的UILabel中。FXLabel还提供了更多控件,可以对字体行距、字体间距等...

  • Java毕业设计-ssm-jsp-校园自助洗衣系统(源码+sql脚本+32页零基础部署图文详解+33页论文+环境工具+教程+视频+模板).zip

    资源说明: 1:csdn平台资源详情页的文档预览若发现'异常',属平台多文档切片混合解析和叠加展示风格,请放心使用。 2:32页图文详解文档(从零开始项目全套环境工具安装搭建调试运行部署,保姆级图文详解),旨在为更多的人甚至零基础的人也能运行、使用和学习。 3:配套毕业论文,万字长文,word文档,支持二次编辑。 4:范例参考答辩ppt,pptx格式,支持二次编辑。 5:工具环境、ppt参考模板、相关电子教程、视频教学资源分享。 6:资源项目源码均已通过严格测试验证,保证能够正常运行,本项目仅用作交流学习参考,请切勿用于商业用途。 7:项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通。 内容概要: 本系统基于B/S网络结构,在IDEA中开发。服务端用Java并借ssm框架(Spring+SpringMVC+MyBatis)搭建后台。用MySQL存储数据,可靠性强。 能学到什么: 使用ssm搭建后台。学习使用jsp、html构建交互界面、前后端数据交互、MySQL管理数据、从零开始环境搭建、调试、运行、打包、部署流程。

  • Java毕业设计-ssm-vue-小型企业办公自动化系统(源码+sql脚本+32页零基础部署图文详解+42页论文+环境工具+教程+视频+模板).zip

    资源说明: 1:csdn平台资源详情页的文档预览若发现'异常',属平台多文档切片混合解析和叠加展示风格,请放心使用。 2:32页图文详解文档(从零开始项目全套环境工具安装搭建调试运行部署,保姆级图文详解),旨在为更多的人甚至零基础的人也能运行、使用和学习。 3:配套毕业论文,万字长文,word文档,支持二次编辑。 4:范例参考答辩ppt,pptx格式,支持二次编辑。 5:工具环境、ppt参考模板、相关电子教程、视频教学资源分享。 6:资源项目源码均已通过严格测试验证,保证能够正常运行,本项目仅用作交流学习参考,请切勿用于商业用途。 7:项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通。 内容概要: 本系统基于B/S网络结构,在IDEA中开发。服务端用Java并借ssm框架(Spring+SpringMVC+MyBatis)搭建后台。用MySQL存储数据,可靠性强。 能学到什么: 使用ssm搭建后台。VUE框架构建前端交互界面、前后端数据交互、MySQL管理数据、从零开始环境搭建、调试、运行、打包、部署流程。

  • rsyslog-kafka-8.24.0-57.el7-9.3.x64-86.rpm.tar.gz

    1、文件内容:rsyslog-kafka-8.24.0-57.el7_9.3.rpm以及相关依赖 2、文件形式:tar.gz压缩包 3、安装指令: #Step1、解压 tar -zxvf /mnt/data/output/rsyslog-kafka-8.24.0-57.el7_9.3.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm 4、安装指导:私信博主,全程指导安装

  • Java毕业设计-ssm-jsp-助学贷款(源码+sql脚本+32页零基础部署图文详解+29页论文+环境工具+教程+视频+模板).zip

    资源说明: 1:csdn平台资源详情页的文档预览若发现'异常',属平台多文档切片混合解析和叠加展示风格,请放心使用。 2:32页图文详解文档(从零开始项目全套环境工具安装搭建调试运行部署,保姆级图文详解),旨在为更多的人甚至零基础的人也能运行、使用和学习。 3:配套毕业论文,万字长文,word文档,支持二次编辑。 4:范例参考答辩ppt,pptx格式,支持二次编辑。 5:工具环境、ppt参考模板、相关电子教程、视频教学资源分享。 6:资源项目源码均已通过严格测试验证,保证能够正常运行,本项目仅用作交流学习参考,请切勿用于商业用途。 7:项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通。 内容概要: 本系统基于B/S网络结构,在IDEA中开发。服务端用Java并借ssm框架(Spring+SpringMVC+MyBatis)搭建后台。用MySQL存储数据,可靠性强。 能学到什么: 使用ssm搭建后台。学习使用jsp、html构建交互界面、前后端数据交互、MySQL管理数据、从零开始环境搭建、调试、运行、打包、部署流程。

  • qt5-qtcanvas3d-5.9.7-1.el7.x64-86.rpm.tar.gz

    1、文件内容:qt5-qtcanvas3d-5.9.7-1.el7.rpm以及相关依赖 2、文件形式:tar.gz压缩包 3、安装指令: #Step1、解压 tar -zxvf /mnt/data/output/qt5-qtcanvas3d-5.9.7-1.el7.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm 4、安装指导:私信博主,全程指导安装

  • KVM 虚拟化win10PE 带virtio 驱动

    KVM 虚拟化win10PE 带virtio 驱动

  • 使用python和js逆向破解的某药城商品价格密文参数的源代码,具体步骤可查看文章:https://blog.csdn.net/weixin-42108731/article/details/1454

    使用python和js逆向破解的某药城商品价格密文参数的源代码,具体步骤可查看文章:https://blog.csdn.net/weixin_42108731/article/details/1454

Global site tag (gtag.js) - Google Analytics