GoogleMobileAds.framework血战到底游戏机玩法怎么玩

AF3.0 去掉了 AFURLRequestOperation(用的是苹果iOS8之后不提倡使用的函数封装的) 之类的方法。只保留了AFSession(新的session相关函数封装的)相关的。
以下是使用实例:
#import &HLNetworkManager.h&
#import &arpa/inet.h&
#import &unistd.h&
#import &AFNetworking.h&
#import &HLConstants.h&
#import &HLFileManager.h&
#import &MJExtension.h&
#import &NSData+HLDataAES256.h&
#define KAesKey @&*****&//加密
@interface HLNetworkManager ()
& & dispatch_queue_t _requestQ
& & NSMutableDictionary *_deviceD
@implementation HLNetworkManager
+ (HLNetworkManager *)sharedManager
& & static HLNetworkManager *sharedI
& & static dispatch_once_t onceT
& & dispatch_once(&onceToken, ^{
& & & & sharedInstance = [[HLNetworkManager alloc] init];
& & return sharedI & &
- (instancetype)init
& & if (self = [super init])&
&& & & & _requestQueue = dispatch_queue_create(&com.pindou.HiLove.serial.requestQueue&, DISPATCH_QUEUE_CONCURRENT);
& & & & _deviceDic = [[NSMutableDictionary alloc] init];
& & & & [_deviceDic setValue:OS_Type forKey:@&os_type&];
& & & & [_deviceDic setValue:Channel forKey:@&channel&];
& & & & [_deviceDic setValue:OS_Version forKey:@&os_version&];
& & & & [_deviceDic setValue:App_Version forKey:@&app_version&];
& & & & [_deviceDic setValue:[[HLFileManager sharedManager] getConfigStringWithKey:DeviceIdentifier] forKey:@&identifier&];
& & & & [_deviceDic setValue:[[HLFileManager sharedManager] getConfigStringWithKey:DeviceUUID] forKey:@&uuid&];
+ (BOOL)checkNetWork
& & return [AFNetworkReachabilityManager sharedManager].isR
- (void)httpRequest:(NSString *)cmd withData:(id)postData completionBlock:(HLNetworkCompletionBlock)completionBlock
& & NSMutableDictionary *requsetDic = [[NSMutableDictionary alloc] init];
& & [requsetDic setObject:_deviceDic forKey:@&device&];
& & if (postData)
& & & & [requsetDic setObject:postData forKey:@&data&];
& & NSError *
& & NSData *jsonData = [NSJSONSerialization dataWithJSONObject:requsetDic options:0 error:&error];
& & NSData *requestData = [jsonData aes256_encrypt:KAesKey];
& & NSString *url = [NSString stringWithFormat:@&%@%@&, kServerUrl, cmd];
& & AFHTTPSessionManager *manager = [AFHTTPSessionManager new];
& & manager.responseSerializer = [AFHTTPResponseSerializer new];
& & [manager.requestSerializer setValue: @&application/octet-stream& forHTTPHeaderField:@&Content-Type&];
& & [manager.requestSerializer setQueryStringSerializationWithBlock:^NSString * _Nonnull(NSURLRequest * _Nonnull request, id& _Nonnull parameters, NSError * _Nullable __autoreleasing * _Nullable error)&
& & & & return [[NSString alloc] initWithData:requestData encoding:NSUTF8StringEncoding];
& & [manager POST:url parameters:requestData success:^(NSURLSessionDataTask * _Nonnull task, id& _Nonnull responseObject)
& & & & NSLog(@&responseObject %@&,responseObject);
& & & & NSString *string = [[NSString alloc] initWithData:[responseObject aes256_decrypt:KAesKey] encoding:NSUTF8StringEncoding];
& & & & NSLog(@&string %@&,string);
& & } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
& & & & NSLog(@&%@&, error);
在应用程序开发过程中,很重要的一部分工作就是如何进行源码的版本控制。当代码出现问题时,我们就需要将代码恢复到原先正常的版本。如果是多个人共同开发一个项目,那么代码的控制就会非常复杂。幸运的是,开发者不需要自己控制这些,因为有专门的软件来负责,叫做版本控制系统。
版本控制系统,或者说修改控制系统,实际上是一种检测源文件的改变并将其保存留作以后参考使用的机制(软件)。此外,它还能记录其他有用信息,比如是哪个开发者修改了代码,何时修改的,修改了哪一部分,以及其他历史信息。版本控制系统可以比较不同版本代码的不同,有必要时能恢复整个项目到以前的版本,追踪有害代码从而减少产品的错误。
通过版本控制系统,开发者可以在一个项目的不同分支上工作,当项目的各个部分开发完备时,将它们放到一起形成最终的版本,这个过程被称为合并。事实上,这种做法再团队和软件公司中相当常见:每个人负责项目的一部分,最终所有部分被整合到一起形成最终产品。
对于个人开发者来说,版本控制系统并不是必需的,但是我们仍然强烈推荐开发者使用它,因为它可以使代码方便的在有错误的版本和可以工作的版本之间转换。事实上,很多开发者从来不使用类似的工具,他们会在项目添加新的功能时手动保存原先的项目。这其实是一个很不好的习惯,因为版本控制软件可以更好更高效地完成这项任务。
Git是一个常见的版本控制系统,它最开始是由Liunx之父Linus Torvalds开发的,Git使用虚拟目录,又称为repositories,来管理一切事物。Git可以通过命令行调用,也有专门为它设计的桌面应用软件。如果Git对你来说很陌生,我建议你在网上查看一些它的相关信息。关于Git更深层次的内容都不在本文的讨论范围之内。
从Xcode5开始引入了使用git的一些新特性。它将git的各项功能整合到一个菜单中,并提供子菜单来进行软件合并的控制。在接下来的阅读中你会发现,使用git来进行版本控制相当的简单快捷。
我们接下来的任务就是学习如何在Xcode中使用git,以及Xcode是如何整合Git的各项功能。如果你觉得对这些很陌生,我建议你先上网搜索一下相关的内容。在接下来的教程中,我会假定你已经了解了版本控制系统和git是什么,并将注意力集中在Xcode如何管理它上。
GIT Demo概述(GIT Demo Overview)
与其他教程中的demo app不同,这次我们不会去实现一个应用来演示某一项iOS SDK特性,最终我们也不会产生一个示例产品。实际上,我们会新建一个demo工程,写几行代码,然后利用这个工程来演示Xcode提供的版本管理功能。换句话说,我们会集中注意里于IDE上,而不是iOS本身。
我建议你跟着我一起一步一步实现这个实例项目,在相应的地方手动添加代码,不用担心,代码量不是很多。跟着教程的步骤,我们将执行多种重复的版本控制相关的操作,并且我们必须实时看到结果。如果我只是提供了一个具备所有操作的的应用,那么你无法体会到这些改变。
好了,废话不多说了,让我们仔细看看使用Xcode进行版本控制的要点吧。
创建一个Git源(Creating a Git repository)
每次在Xcode中创建新工程的时候,都会提示开发者是否将项目作为一个本地的git源。在创建工程的最后一步Xcode会有一个复选框,如果选择了它,git源就会被添加到工程目录中。通常这个选项会被忽视,或是被认为是Xcode的另外一个没用的功能,尤其是从未用过git的开发者,或是编程新手。
打开Xcode,创建一个新的工程。选择iOS区的“Application”,在应用模板页选择“Single View Application”。
选择下一步,在项目名中输入GitDemo,确保下面的Devices菜单选择iPhone,无需iPad或者universal app。
点击下一步,也就是最后一个步骤,在这里先选择一个要保持工程的目录,然后在窗口底部选上Create git repository on (My Mac ):
默认情况下,这个选项是被选上的,如果你不想使用git,你可以取消它,但是我不建议这么做。本教程中,你需要将它勾选上,然后点击创建按钮。
创建完项目之后,打开Finder,找到项目存储的目录,在目录中,有一个.git的子目录,时Xcode为存储git源相关数据自动创建的。
如果你看不到.git目录,你需要让隐藏的文件可见。具体做法就是打开一个Terminal窗口,输入以下命令:
对于OS X Mavericks 10.9:
defaults&write&com.apple.finder&AppleShowAllFiles&TRUE&&
对于以前的OS X版本,
efaults&write&com.apple.Finder&AppleShowAllFiles&TRUE& &
为了重启Finder应用,输入
killall&Finder&&
这就是本项目在本地git源保存的位置。实际上,如果你选上了相应的选项,这个目录就会被创建。相应地,在你创建新应用时,.git子目录也会一同被创建。
显然使用Xcode创建一个git源毫不费力,然而,如果你在项目创建时未创建git源,之后又想加上这个功能怎么办呢?好吧,其实你可以在任何时候为你的项目创建源,但是不是使用Xcode。尽管这种情况很少发生,我还是会告诉你该怎么做。
如果你愿意的话,你可以直接跳到本教程的下一部分。我建议你接着读下去,因为接下来这些信息还是很有用的。
在进行演示前,你需要首先通过Xcode下载Command Line Tools,因为我们要在Terminal下操作,并且需要一些额外的工具。如果你还没有下载,那就去Xcode&Preferences…菜单,选择Download选项卡,展开Components区,点击Commond Line Tools右边下载按钮。下载完成后,一个对勾符号会取代下载按钮。
现在,为这个例子再创建一个工程,完事后可以删了它。在创建时取消那个创建git源的选项。这次我们不想让Xcode为我们准备一个源。把这个工程命名为NoGitExample,保存到桌面,然后你可以跟我接下来输入的命令一样。
一切准备妥当后,打开Terminal窗口(如果你之前打开了一个,那就先关掉它再重启,从而使我们安装的命令行工具生效)。下面切换到新项目的目录:
cd&/Users/YOUR-USERNAME/Desktop/NoGitExample&&
别忘了在上边命令中设置Mac的用户名,接下来,输入:
git&init&&
&这会初始化一个空的源,如果你在Finder里面查看或是输入ls命令,你会看到.git子目录已经被创建,很好,接下来输入:
git&add&.&&
这样,当前目录所有的内容就被添加到源里面去了,最后,输入以下命令:
git&commit&-m&'Initial&commit'&&
接下来会出现一个本地git源所执行的改变列表,如下图所示:
现在git源就建好了,但是如果你回到Xcode,打开Source Control菜单,你会发现一切仍然是被禁用。
这是因为当我们使用命令行工具创建git源时,Xcode并未被通知,下面点击Xcode&Quit Xcode,然后重新启动它,在NoGitExample项目中,如果你再次打开Source Control菜单,你会发现所有的选项已经被使能了,就像一开始勾选上创建git源一样。
现在这个项目的使命已经结束,你可以在桌面上删除它。
现在你知道如何为你所有的项目添加git源了,即使你在创建时没有添加,你也可以在以后任何时候为它手动添加源。
提交更改(Committing Changes)提交更改指的是储存一个包含所有更改的新版本。一般来说,当我们做了一些有意义的工作,并且项目处于某一个稳定状态时,就可以提交一次更改。然而具体什么时候提交更改并没有硬性的规定。我的建议是:从上次提交更改之后,如果你怕花费大量时间和精力做的新工作被误删很难恢复,你就需要提交更改了。
默认情况下,Xcode在项目创建之初会提交一次更改,这是为了保存项目初始状态。这项工作会在后台完成,不会打扰你或者要求你进行确认。如果你在项目创建时没有添加git源,但是之后你手动添加了,你可以通过我们先前使用过的命令来进行提交:git commit -m ‘Initial commit’
实际上,你如果去Source Control&History…菜单,你就会看到初次提交更改的记录,以后每次提交更改,都会在这里有所记录。
接下来让我们小幅修改一下我们的工程,在ViewController.m文件中,添加以下属性声明:
@interface&ViewController&() &
@property&(nonatomic)&int& &
接下来,像下面这样修改viewDidLoad方法:
-&(void)didReceiveMemoryWarning &
&&&&[super&didReceiveMemoryWarning]; &
&&&&//&Dispose&of&any&resources&that&can&be&recreated. &
&&&&int&a&=&5; &
&&&&int&b&=&10; &
&&&&self.sum&=&a&+&b; &
&&&&NSLog(&The&result&is:&%d&,&self.sum); &
看一下Project navigator面板,你会发现在ViewController.m文件旁边,添加了一个M字母,像下面这样:
这意味着那个文件已经被修改,相比上一次提交更改,文件有所改变。一般来说,你每次改变文件,都会出现这个M字母,提醒你有未提交的更改。
下面看看如何提交更改,其实非常简单,只需要打开Source Control&Commit菜单,下面窗口就会出现:
让我们一步步看看它告诉我们了什么。在左边(标1的区域),列出了所有被更改的文件,在这个例子中,只有ViewController.m这个文件被改变,因此列表中只有它被显示。如果你仔细观察,你会发现文件左边有一个选择框,默认情况下是被选中的,如果你取消它,这个文件的更改就不会被提交。
在窗口的中间区域,有两个预览窗口,左边那个是文件当前版本,右边是文件上一次提交更改的版本。因为我们目前只是创建时提交过一次更改,因此右边显示的是文件的初始状态。
左边窗口蓝色区域标出的就是更改的内容,这样的表示让我们可以清楚地看出所有的修改。如果你仔细看,会发现在两个窗口之间还有一个带数字的小标签,这个数字一一表示了各项更改。在数字旁边,默认情况下有一个小对勾,表示本更改会被提交,如果你点击右边的小箭头,会弹出一个选项菜单,你可以选择不提交这个更改或是忽略它。
如果你选择了Don’t Commit这个选项,小对勾就会被一个停止标志取代,这项更改就不会被保存到源中。
如果你选择了Discard Change这个选项,会弹出一个确认窗口,提示你所做的更改会被恢复,并且无法取消这个操作。
如果你点击了OK按钮,所选区域的改变就会消失,就像他们从未出现过一样。
如果你仔细观察上面这个提交窗口,你会看到你所做的所有修改都会被Xcode看做改变,即使是一个空行。实际上空行相当于回车,在屏幕上是不可见的,因此作为改变也是理所当然的。
在本例子中,你不用忽略任何修改,而是允许提交所有更改,因此所有的改变标签旁边必须都是小对勾。
在两个窗口下面是一个空白的区域,中间显示了提交更改的信息。这个地方可以添加一些关于此次更改的简短描述,点击它,加入如下内容:
书写有意义的提交信息非常有用,尤其是当你频繁提交的时候。因此,把它当做一个必要的步骤。
现在这个窗口的基本信息看的差不多了,是时候做我们第一次的提交了。在这个窗口的右下脚,有一个按钮上面写着:Commit 1 file。
这个按钮会显示需要提交的文件总数。点击它之后你的第一次提交就完成了!打开Source control & History,你会发现它会被显示在列表中。
从上图中可以看出,我们编写的信息以及更改的文件数量会被显示出来。Xcode执行初始提交,所有文件都会被提交一下,而这次只有我们修改的那个文件被提交。
另外,关闭历史窗口,看一下Project Navigator,你会发现ViewController.m旁边的M符号已经消失了。
现在,让我们准备下一次提交。这次,我们给工程添加一些新的文件。添加文件最好的方式就是创建个新类,因此,按下Command+N组合键,添加一个Objective-C类。让这个类继承NSObject类,取名叫TestClass,然后添加到工程中。
完成之后,注意一下Project Navigator,你会发现两个新的类文件旁边有个A的字母标识,这意味着这些文件已经被添加到项目中,当然,他们还没有被提交。
打开ViewController.h文件,导入我们的新类:
#import&&TestClass.h&&&
下一步,打开ViewController.m文件,像下面一样声明一个私有属性:
@interface&ViewController&() &
@property&(nonatomic)&int& &
@property&(nonatomic,&strong)&TestClass&*testC &
看一下项目导航栏,这次有四个文件有待提交。让我们打开Source Control & Commit菜单,将它们提交。
需要提交的一共有5个文件。除了之前修改的四个之外,还有一个项目配置文件。Xcode会在新类被添加到项目中之后自动修改这个文件。如果你你打开TestClass.h或TestClass.m文件,左边的窗口没有任何显示,如下图所示。
这是因为在这个文件在之前没有被提交的记录,因此没有一个可以比较的版本,在右边只显示了File was added。
在消息区写上这样一个描述:TestClass was added to project.. 之后点击Commit 5 files按钮即可。
这样第二次手动提交就成功了。你可以到Source Control & History 菜单查看提交的记录。
版本之间的比较(Comparing Versions)当你提交了同一工程的不同版本之后,在他们之间比较,追踪修改信息就会非常方便。当新添加的代码不能运行时,这时与之间版本进行比较就非常重要了,你可以看出新版本相比上个稳定版有了哪些更改。
要比较同一个文件的两个版本,你可以使用View&Version Editor&Show version editor,或是点击工具栏上的Version Editor按钮:
点击之后,编辑器会分为两栏。最初,两栏会显示相同的内容,点击编辑器下面的那个小时钟图标,可以选择之前已经提交的版本进行比较。
点击之后,两个版本的区别会在编辑器中显示出来。通常,左边显示的是当前版本的文件,右边显示的是之前的版本。蓝色高亮的区域显示了被更改的代码,因此比较代码的变化非常容易。继续选择任何此前的版本,并观察两栏的区别。
你可能会注意到,在两个编辑器中间,还有在提交窗口看到的小标签。点击向下的按钮可以跳出让你忽略更改的选项。如果你点击了忽略更改,Xcode会提示你是否同意。如果你同意忽略,这些被忽略的代码将会永远消失,无法再找回来。所以要注意不要无意中忽略任何代码。&
除了上面说到的方法,还有一种你回到之前版本的方法。如果你仔细观察两个编辑器下面的工具栏,在中间有个带箭头的时钟图标:
点击它之后,两个面板之间的纵列内容就发生了改变,变成了一系列表示之前更改的时间戳。注意并不是所有的都代表实际提交。代表先前版本的圆角矩形的数量取决于提交的次数。在这个例子中,只有两个这样的图形,代表了两次提交。
在这一列的下面,有两个箭头。左边的那个属于左边的面板,右边的箭头属于右边的面板。将箭头移动到任意之前的版本,你会看到在相应面板中的改变。如果你想比较当前版本和之前任意版本的区别,让一个箭头指向local行,然后移动第二个箭头。时间戳从底部到顶部代表了从新到旧的代码。在base行,你会看到上一次提交的内容。继续向上移动,你会看到最初的提交,如下图所示:
现在你知道如何比较版本之间的区别了。再继续深入之前,把前面学习的练习一下玩玩吧。
究竟是谁的错?(Who’s Got the Blame)除了比较文件的版本外,Xcode还可以让你追踪文件的提交者,以及是谁改变了哪一部分代码。在一个多人的团队中,这非常有用。要使用这个功能,点击View & Version Editor & Show Blame View菜单。或是讲鼠标放在工具栏的Version editor 按钮上,选择Blame选项。一个与上面类似的窗口将会出现:
正如你看到的,当前文件依据不同的提交被水平线分成几段,每个代码段的作者,以及提交信息和其他信息显示在窗口右边的一个特殊面板中。
如果你还没有做过,那自己动手打开这个blame视图,注意一下Xcode展现代码段作者的方式。在这个视图中,可以方便地找到某一代码在何时被谁提交以及其他你想要的信息。将鼠标放在blame面板上,将会显示修改的一些其他信息。当指针停在提交段上时,一个带图片的小按钮就会出现在它的右边。点击选中该段代码,就会弹出一个附带提交信息窗口。在这个窗口中,你还可以跳转到比较窗口(indication #1),以及特定提交的修改文件(indication #2)。
除了比较视图和blame试图,其实还有一个日志视图(Log view)。你可以通过View & Version Editor & Show Log View来打开它。或者如果你在这里就不在详细说它了。你可以自己去看看,毕竟这个用起来也没那么复杂。
分支(Branches)试想一下,你现在的工程有一个即将发布的版本,或是已经发布的版本,你突然想添加一些新的特性,如何防止这些新添加的代码让整个项目陷入瘫痪呢?答案很简单:你需要使用分支。
如何简单的理解分支呢?你可以把你的项目想象成一棵树,稳定版本就是树的主干。任何添加新功能的版本都必须是树干的一部分。分支,就像是树的枝干,它从树干生长出来,向不同的方向生长。在git中,你可以通过创建分支来为你的代码设置一个新的路径来实现新特性,而不用担心在开发中破坏主干。
实际上,在git中默认都会有一个分支,叫做master。Xcode自动执行的第一次提交中就发生在这个分支中。通常,单独的开发者只在master这个分支开发,这其实不是一个好习惯。无论你是单打独斗还是组团合作,我认为在对项目作出重大改变或添加重大功能时,使用分支是十分重要的,它会为你避免很多麻烦。当然,在团队项目中,为你自己负责部分的代码搞一个分支几乎是必须的。
关于分支,你必须记住以下两点:1.&提交到App Store或客户的最终产品必须是项目中的master分支项目。2.&任何在第二分支中实现的代码或者功能最终都必须合并到master分支,这样正式发布的应用程序才是完整的。(以后再讲这一点)
当你开始一个新分支时,你实际上是以当前工作状态作为起点,即使你有任何未提交的更改。从这个时候起,所有的改变都会只体现在分支中。
现在让我们回到Xcode,要创建一个分支,点击Source Control & GitDemo-master & New Brance…这个菜单,然后会弹出如下菜单:
为这个分支起一个名字,我就把它起名为AnotherBranch好了。现在你怎么给它起名其实都无所谓。点击OK按钮,等一下新的分支就会被创建,而当前的代码也会复制到新分支中去。
打开Source Control菜单,你就可以轻松地找出活动分支是哪一个:它就在项目名字的旁边。
现在,让我们做一次新的分支的提交。在这之前,让我们添加一些新的代码。打开类文件,在私有属性区添加以下方法声明:
@interface&ViewController&() &
-(void)sayH &
&然后实现它:
-(void)sayHello{ &
&&&&NSLog(&Hello&); &
最后,在viewDidLoad中调用它:
-&(void)didReceiveMemoryWarning &
&&&&...&&&& &
&&&&[self&sayHello]; &
现在,点击Source Control & Commit菜单,版本比较窗口将会出现,你会看到只有一个被修改过的文件--ViewController.m文件,新添加的部分会被高亮显示。
输入下一个提交信息:First commit to a new branch,然后点击commit 1 file按钮。现在AnotherBrance分支的改变就会被提交了。
打开Version Editor(menu View & Version Editor & Show Version Editor),找到右边编辑面板下面的工具栏,你会看到被选中的分支是AnotherBranch,点击它,你会看到这个分支和master分支同时出现,从master分支中选择任意版本,Xcode都会高亮显示两者之间的区别。通过这样,你可以方便地跟踪所有分支间代码的改变。
最后,切换到另一个分支,或是master分支,你可以点击Source Control & GitDemo –AnotherBranch & Switch to Branch…菜单。
从这个窗口你可以选择想要跳转的分支,在这里让我们跳回master分支:
选择它并点击Switch按钮,master分支就会成为当然活动分支。你会发现在AnotherBranch中做出的改变并没有出现在master分支。很好,我们在管理工程推进的同时,却没有修改稳定版本。
合并分支(Merging Branches)在分支中进行开发是一种好习惯,然而,如果代码改变要体现在发行版中,那么分支就必须被合并到master分支中。这一节我们将会告诉你怎样合并它们。在Xcode里,将两个分支合并成一个非常简单。
让我们做一个小实验来看看合并是怎样工作的。首先,确保master分支是现在的活动分支。如果不是,赶紧改过来:Source Control & GitDemo – AnotherBranch & Switch To Branch… menu,并从展示窗口选择master分支。
下一步,创建一个新的分支:Source Control & GitDemo – master & New Branch… menu,命名为LastBranch
先让Xcode飞一会,然后,到ViewController.m文件中,再创建一个私有方法,首先声明它:
@interface&ViewController&() &
-(void)sayByeB &
然后实现它:
-(void)sayByeBye{ &
&&&&NSLog(&Bye&-&Bye&); &
最后,在ViewDidLoad方法中调用它:
-&(void)viewDidLoad &
&&&&...&&&& &
&&&&[self&sayByeBye]; &
在合并之前,先提交这些更改。使用Source Control & Commit菜单来执行提交。
终于还是来到这一步,关于把两个不同的分支合并成一个,你有两种选择“1.&从分支合并:与你选择的分支相关的任何改变都会被合并到现在活动分支中。2.&合并到分支:当前活动分支的任何改变都会被合并到你选择的分支中。
这两种方式你都可以在Source Control & GitDemo 菜单中找到。注意当你的活动分支是master分支时,第二个选项是不可选的。
假设一个开发者在Anotherbranch分支实现一个sayHello方法,另外一个开发者在LastBranch中创建实现了sayByeBye方法,现在你需要将两个人的工作合并到下一个稳定版本中,想一想你需要怎么做?很简单,按以下方法将改变从两个分支中合并进来:
首先,确保当前活跃分支是master分支。
然后,打开Source Control & GitDemo – master & Merge From Branch…菜单,选择AnotherBranch然后点击Merge按钮。
接下来会出现一个比较窗口,在里面你会看到合并之后代码的更改,看一眼,感觉差不多了就再点击Merge按钮。
Xcode会询问你是否保存项目的快照,点击Enable按钮。让Xcode飞一会,然后就好啦。AnotherBranch里面添加的内容已经合并到master分支中。
使用同样的方法来合并LastBranch。你会发现如果你不提交更改,Xcode不会让你再次合并。于是,我们只好先提交一下。在比较窗口你会发现一个红色的区域显示合并之后的更改,而不是之前的蓝色。这意味着分支中的代码将会替换原先活动分支中的代码。
你可以轻松地避免这种现象的发生。在编辑面板的下面有几个小按钮,你可以试试他们都有什么作用,我选了第一个,它的意思是master分支的代码会被放在上面,另一个分支的代码会跟在它后面。
处理接下来所有需要更改的代码,不要有遗漏。完事后就点击Merge按钮。
恭喜你!你已经成功的学会从多个分支合并了代码,类似的情形你也应该会了。
忽略更改(Discarding Changes)放弃不想要的代码更改功能非常有用,只需轻轻一点,自从上一次提交之后的更改都会被放弃。当你在开发过程中发现出了大乱子,你想从上一个稳定状态重新开始时,这个功能就派上用场啦。注意放弃更改这个功能没有回头路,点完之后你就没有办法再撤销这个操作,所以,要小心使用啊!
之前,当我们在讨论版本比较时,我们学会了如何忽略某一部分更改的方法,下面,我们要学一下如何一下忽略自从上一次提交之后的所有更改。
为了测试这个功能,首先写一些代码打开ViewController.h ,添加一个公共方法声明:
@interface&ViewController&:&UIViewController &
-(void)aVeryCoolM &
现在,让我们在ViewController.m中添加一个这个方法的实现,简单点就行:
-(void)aVeryCoolMethod{ &
&&&&NSLog(&I'm&feeling&that&you'll&discard&me...&Really?&); &
如果你注意到Project Navigator,我们刚刚更改的文件旁边有了一个M标识,很好,我们想看看如果忽略这些更改,这些文件是否会回到更改之前的状态。
这里有一个重要的细节:你可以选择忽略所有文件的更改,也可以选择忽略单个文件的更改,这完全取决于你。如果你想忽略一个文件的更改,首先选定这个文件。在这个例子里,如果你只选择ViewController.m文件然后打开Source Control菜单,你会在ViewController.m中发现Didcard Changes这个选项。类似的,如果你只选择ViewController.h也是一个道理。然而,如果你想忽视这两个文件的更改(这里假定有两个以上的更改),就在Project Navigator中选中它们,然后再打开Source Control菜单。相应的位置就会显示Discard Changes in 2 Files,像下面这样:
然而,这次我们不会使用这个按钮,我们要用Discard All Changes。点击它之后,一个确定提示框就会出现,这是这部分Xcode防止你误删代码的唯一措施。
点击Discard All Changes, 那你刚才写的那个公共方法就永远属于过去了。看到了吧,只需几步就可以让你从当前工作状态恢复到之前的提交,所以我再一次提醒你要在使用Source Control 中小心点,别误点了这个按钮。
-[UIKBBlurredKeyView candidateList]: unrecognized selector sent to instance 0x
问题描述:
当我们的APP的UITextFieldView获得焦点,进入输入时候,也就是虚拟键盘弹出来了,此时点击左下方的地球跳入手写板界面,此时随便打一个字,选中自动提示的文字之后,手写板的提示栏会变成灰色,此时再点击任意屏幕位置,Crash.
解决方案:
1.你扩展了某个UIView or UIScrollVIew 的Category,并且重写了UITouchBegans、move、end方法。屏蔽该3个方法即可。
2.你当前的Controller 可能覆盖了1中的3个方法,也是屏蔽即可。
3.搜索其他覆盖1中的3个方法,屏蔽即可。
1.在UIScrollView上面加一个UIView,通过在view上面的手势来改变键盘
UITapGestureRecognizer *tapGr = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard:)];tapGr.cancelsTouchesInView = NO;[backView addGestureRecognizer:tapGr];
2.在UITableView上改变键盘
UITapGestureRecognizer *tapGr = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard:)];tapGr.cancelsTouchesInView = NO;[backView addGestureRecognizer:tapGr];
在一个UITableView中,有多条数据,可能每一个cell对应的剩余时间不一样,所以,如何实现不同的cell中倒计时的实现?之前,考虑到需要单独为每一个cell中开启一个定时器,来监控对应cell的数据更新,但是很快发现这种方法行不通,因为不知道具体有多少条数据,这些数据都是动态从服务器获取的。所以,想到在请求最新的数据时,开启一个定时器,根据该定时器,分别对所有的需要进行倒计时显示的cell进行数据修改。最后,功能已经实现,核心代码如下:
//所有剩余时间数组
NSMutableArray&*totalLastT
在网络请求到的所有数据中,根据需要将其中要进行倒计时显示的数据中的剩余时间单独保存出来,如果这里是所有的数据都需要倒计时,则只需要保存时间即可,如果是有部分数据才需要倒计时,则可以保存字典,两个键值对分别为其在UITableView的indexPath和剩余时间:num默认从0开始
NSDictionary&*dic =&@{@&indexPath&:[NSStrin&stringWithFormat:@&%i&,num],@&lastTime&: order.payLastTime};
&[totalLastTime&addObject:dic];
开启定时器方法:
- (void)startTimer
&&&&timer&= [NSTimer&scheduledTimerWithTimeInterval:1&target:selfselector:@selector(refreshLessTime)&userInfo:@&&&repeats:YES];
如果不添加下面这条语句,在UITableView拖动的时候,会阻塞定时器的调用
&&&&[[NSRunLoop&currentRunLoop]&addTimer:timer&forMode:UITrackingRunLoopMode];
主要的定时器中的方法,在该方法中,遍历totalLastTime,取出其中保存的lasttime和indexpath,time用来显示,在显示完后自减,indexpath代表对应显示的位置,在一次循环后,将新的time和没有改变的indexpath从新替换totalLastTime&中对应位置的元素,以此保证每一秒执行时,显示time都是最新的。
- (void)refreshLessTime
&&&&NSUInteger&
&&&&for&(int&i =&0; i &&totalLastTime. i++) {
&&&&&&&&time = [[[totalLastTime&objectAtIndex:i]&objectForKey:@&lastTime&]integerValue];
&&&&&&&&NSIndexPath&*indexPath = [NSIndexPath&indexPathForItem:0&inSection:[[[totalLastTime&objectAtIndex:i]&objectForKey:@&indexPath&]&integerValue]];
&&&&&&&&WLServiceOrderTableViewCell&*cell = (WLServiceOrderTableViewCell&*)[_tableView&cellForRowAtIndexPath:indexPath];
&&&&&&&&cell.remainingTimeLabel.text&= [NSString&stringWithFormat:@&剩余支付时间:%@&,[self&lessSecondToDay:--time]];
&&&&&&&&NSDictionary&*dic =&@{@&indexPath&: [NSStringstringWithFormat:@&%i&,indexPath.section],@&lastTime&: [NSStringstringWithFormat:@&%i&,time]};
&&&&&&&&[totalLastTime&replaceObjectAtIndex:i&withObject:dic];
- (NSString&*)lessSecondToDay:(NSUInteger)seconds
&&&&NSUInteger&day&&= (NSUInteger)seconds/(24*3600);
&&&&NSUInteger&hour = (NSUInteger)(seconds%(24*3600))/3600;
&&&&NSUInteger&min&&= (NSUInteger)(seconds%(3600))/60;
&&&&NSUInteger&second = (NSUInteger)(seconds%60);
&&&&NSString&*time = [NSString&stringWithFormat:@&%lu日%lu小时%lu分钟%lu秒&,(unsigned&long)day,(unsigned&long)hour,(unsigned&long)min,(unsigned&long)second];
&&&&return&
打开终端,输入以下指令:
$&cd&~/.itmstransporter&&
$&rm&update_check*&&
$&mv&softwaresupport&softwaresupport.bak&&
$&cd&UploadTokens&&
$&rm&*.token&&
(ITMS-90096)
1.检查你的AppIcon有没有。
2.检查启动图是否添加了启动图片设置
打开图片资源包Images.xcassets
如果没有看到LaunchImage,就添加。
LaunchImage将里面空缺的图片补全,注意?必须是*.png。
项目设置如下
(ERROR ITMS-90049)
参考办法中的方式可行,可以上传了.不过有点要注意,使用了分享sdk的,我用的友盟, 腾讯的plist是在bundle下 搜索不到的,具体位置在:UMSocial_Sdk_Extra_Frameworks--TencentOpenAPI--TencentOpenAPI_IOS_Bundle.bundle--info.plist 找到这个文件后,修改Bundle版本号和identifier和项目一致就行了
1、这个是你使用Xcode7提交时启动页的尺寸,你可以增加对应的尺寸解决。
2、你可以把支持的iOS版本提高进行解决,我是提高到7.0再提交就可以了。
在升级Mac OS X 10.10+Xcode 6.1之后,Cocoapods的依赖库管理也相应的进行了升级。目前最新的Release版本是 0.34。在之前的版本中,进行库更新和管理时,会遇到如下错误
/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in&`require':&cannot&load&such&file&--&xcodeproj/prebuilt/universal.x86_64-darwin14-2.0.0/xcodeproj_ext&(LoadError)&&
&&&&from&/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in&`require'&&
&&&&from&/Library/Ruby/Gems/2.0.0/gems/xcodeproj-0.17.0/lib/xcodeproj/ext.rb:6:in&`rescue&in&&top&(required)&'&&
&&&&from&/Library/Ruby/Gems/2.0.0/gems/xcodeproj-0.17.0/lib/xcodeproj/ext.rb:3:in&`&top&(required)&'&&
&&&&from&/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in&`require'&&
&&&&from&/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in&`require'&&
&&&&from&/Library/Ruby/Gems/2.0.0/gems/xcodeproj-0.17.0/lib/xcodeproj.rb:30:in&`&top&(required)&'&&
&&&&from&/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in&`require'&&
&&&&from&/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in&`require'&&
&&&&from&/Library/Ruby/Gems/2.0.0/gems/cocoapods-0.33.1/lib/cocoapods.rb:2:in&`&top&(required)&'&&
&&&&from&/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in&`require'&&
&&&&from&/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in&`require'&&
&&&&from&/Library/Ruby/Gems/2.0.0/gems/cocoapods-0.33.1/bin/pod:32:in&`&top&(required)&'&&
&&&&from&/usr/bin/pod:23:in&`load'&&
&&&&from&/usr/bin/pod:23:in&`&main&'&&
解决的方案如下,打开Terminals
1. 卸载 cocoapods
$ sudo gem uninstall cocoapods
2. 安装 xcodeproj
$ sudo gem install xcodeproj
3. 重新安装cocoapods$ sudo gem install cocoa pods
如果出现红色字或者黄色的字,说明有错误,需要根据实际情况检查。
sudo rm -fr ~/Library/Caches/CocoaPods/
sudo rm -fr ~/.cocoapods/repos/master/
4. 检查pod 版本
pod --version
以上的命令执行过程中,如果出现红色字或者黄色的字,说明有错误,需要根据实际情况检查。
可能会遇到一个问题,在执行pod setup和 pod --version时,得到如下错误提示 verify_get_version
Options:&&
&&&&--silent&&&&&&&&&&&&&&Show&nothing&&
&&&&--completion-script&&&Print&the&auto-completion&script&&
&&&&--version&&&&&&&&&&&&&Show&the&version&of&the&tool&&
&&&&--verbose&&&&&&&&&&&&&Show&more&debugging&information&&
&&&&--no-ansi&&&&&&&&&&&&&Show&output&without&ANSI&codes&&
&&&&--help&&&&&&&&&&&&&&&&Show&help&banner&of&specified&command&&
&&&&from&/Library/Ruby/Gems/2.0.0/gems/cocoapods-0.34.4/lib/cocoapods/command.rb:129:in&`verify_git_version!'&&
&&&&from&/Library/Ruby/Gems/2.0.0/gems/cocoapods-0.34.4/lib/cocoapods/command.rb:48:in&`run'&&
&&&&from&/Library/Ruby/Gems/2.0.0/gems/cocoapods-0.34.4/bin/pod:33:in&`&top&(required)&'&&
&&&&from&/usr/bin/pod:23:in&`load'&&
&&&&from&/usr/bin/pod:23:in&`&main&'&&
打开xcode-&Preferences-&选择 Locaiton-&在Command Line Tools中选择 Xcode 6.1,会提示输入sudo密码。
完成之后,回到终端,输入git --version,确认是否1.9版本以上
然后重新安装上述 cocoapods的过程。
是因为平台版本号的问题
今天尝试手写podfile:
platform :iospod 'JSONKit',&'~&1.4'pod 'SDWebImage', '~& 3.7.3'pod &'AFNetworking', '~&2.0.1'
jsonkit没问题,可以安装成功,后边的就出问题,报错如下形式
[!] Unable to satisfy the following requirements:
- `DataModel (from `../`)` required by `Podfile`
platform :iOS,'6.0'pod 'JSONKit',&'~&1.4'pod 'SDWebImage', '~& 3.7.3'pod &'AFNetworking', '~&2.0.1'
加上6.0后就没问题了。
1.升级xcode7后,打开原来项目,工程中的动态库都变成了红色的无法导入动态库。
解决方案:
把所有的lib库删除,重新添加,此时的后缀是.tbd。
& & & & & & & & &-------------------------&&&
2.Xcode7中运行时可能会遇到以下错误:You&must&rebuild&it&with&bitcode&enabled&(Xcodesetting ENABLE_BITCODE)
未来Watch应用须包含Bitcode,iOS不强制,但Xcode7默认会开启Bitcode。
如何适配?
方法一:更新library使包含Bitcode,否则会出现以下中的警告;
(null):&URGENT:&all&bitcode&will&be&dropped&because&‘/Users/myname/Library/Mobile&Documents/com~apple~CloudDocs/foldername/appname/GoogleMobileAds.framework/GoogleMobileAds(GADSlot+AdEvents.o)‘&was&built&without&bitcode.&You&must&rebuild&it&with&bitcode&enabled&(Xcode&setting&ENABLE_BITCODE),&obtain&an&updated&library&&the&vendor,&or&disable&bitcode&for&this&.&Note:&This&will&be&an&error&in&the&future.
方法二:关闭Bitcode
工程设置中 buildingsetting 中搜索bitcode 选择no
Apple秋季新品发布会结束,iOS 9 GM版本也正式发布了。新的iPhone设备即将开售,iOS 9系统升级也将会在下周开始陆续进行推送。然而,在这之前,我们还可以为自己的App兼容适配做点什么?或者说,我们的App真的已经兼容适配好iOS 9系统了吗?
从7月份开始到现在,Apple已发布5个iOS 9的Beta版本,相信开发者在这段时间也已经把iOS 9系统的特性基本了解清楚,也为自己的App进行了一系列兼容适配处理。但在这里,笔者还是要再次跟大家聊聊iOS 9中两个比较特别的特性及其兼容问题,即:App Transport Security和App Thinning。App Transport Security
App Transport Security is a feature that improves the security of connections between an app and web services. The feature consists of default connection requirements that conform to best practices for secure connections.
App Transport Security(ATS)是Apple为提高系统及应用安全性而在iOS 9和OS X EI Capitan中引入的新特性,必然,出于安全性的考虑,在新发布的watchOS 2系统中也会适用。
一旦开启ATS后,应用所有的网络请求将会自动转换为HTPPS传输,且采用一系列配置要求来保证数据传输的安全性,包括:
Transport Layer Security协议版本要求TLS1.2以上;
服务的Ciphers配置要求支持Forward Secrecy等;
证书签名算法符合ATS要求等。
这些配置项在升级服务器支持HTTPS过程中都需要严格遵守的,否则就会导致你的HTTPS服务在iOS 9系统中连接仍是失效的。
如果你的App的服务也在升级以适配ATS要求,可以使用如下的方式进行校验:
在OS X EI Capitan系统的终端中通过nscurl命令来诊断检查你的HTTPS服务配置是否满足Apple的ATS要求: $ nscurl --verbose --ats-diagnostics&
当然,你也可以参考Apple提供官方指南&进行服务的升级配置以满足ATS的要求。
Apple虽然希望开发者可以积极的参与并为系统及应用安全共同努力,但官方仍提供了一些参考配置去禁用ATS功能或降低ATS的安全性要求。
开发者可以在App的Info.plist中添加NSAppTransportSecurity的相关配置,用以禁用ATS或者添加白名单,可用的配置参数如下:
NSAllowsArbitraryLoads - 设置true即支持所有HTTP请求
NSExceptionDomains - 添加白名单
NSExceptionMinimumTLSVersion - 白名单指定域名支持的TLS版本
NSExceptionRequiresForwardSecrecy - 白名单指定域名是否支持Forward Secrecy
NSExceptionAllowsInsecureHTTPLoads - 白名单指定域名禁用ATS
NSThirdPartyExceptionMinimumTLSVersion - 白名单指定第三方服务域名最低支持的TLS版本
NSThirdPartyExceptionRequiresForwardSecrecy - 白名单指定第三方服务域名是否支持Forward Secrecy
NSThirdPartyExceptionAllowsInsecureHTTPLoads - 白名单指定第三方域名禁用ATS
举个例子:
禁用所有连接使用ATS
在Info.plist中配置禁用ATS:
&key&NSAppTransportSecurity&/key&&&
&&&dict&&&
&&&&&&&key&NSAllowsArbitrary&/key&&&
&&&&&&&true/&&&
&&&/dict&&&
指定域名禁用ATS
在Info.plist中配置App的服务域名支持HTTP:
&key&NSAppTransportSecurity&/key&&&
&&&dict&&&
&&&&&&&key&NSExceptionDomains&/key&&&
&&&&&&&dict&&&
&&&&&&&&&&&key&&/key&&&
&&&&&&&&&&&dict&&&
&&&&&&&&&&&&&&&key&NSExceptionAllowsInsecureHTTPLoads&/key&&&
&&&&&&&&&&&&&&&false/&&&
&&&&&&&&&&&/dict&&&
&&&&&&&/dict&&&
&&&/dict&&&
指定域名修改ATS安全要求
在Info.plist中配置第三方服务的TLS1.1及禁用Forward Secrecy:
&key&NSAppTransportSecurity&/key&&&
&&&dict&&&
&&&&&&&key&NSExceptionDomains&/key&&&
&&&&&&&dict&&&
&&&&&&&&&&&key&&/key&&&
&&&&&&&&&&&dict&&&
&&&&&&&&&&&&&&&key&NSExceptionAllowsInsecureHTTPLoads&/key&&&
&&&&&&&&&&&&&&&false/&&&
&&&&&&&&&&&/dict&&&
&&&&&&&&&&&key&&/key&&&
&&&&&&&&&&&dict&&&
&&&&&&&&&&&&&&&key&NSThirdPartyExceptionMinimumTLSVersion&/key&&&
&&&&&&&&&&&&&&&string&1.1&string/&&&
&&&&&&&&&&&&&&&key&NSThirdPartyExceptionRequiresForwardSecrecy&/key&&&
&&&&&&&&&&&&&&&false/&&&
&&&&&&&&&&&/dict&&&
&&&&&&&/dict&&&
&&&/dict&&&
App Thinning
The App Store and operating system optimize the installation of iOS and watchOS apps by tailoring app delivery to the capabilities of the user’s particular device, with minimal footprint. This optimization, called app thinning, lets you create apps that use the most device features, occupy minimum disk space, and accommodate future updates that can be applied by Apple. Faster downloads and more space for other apps and content provides a better user experience.
开发者都知道,当前iOS App的编译打包方式是把适配兼容多个设备的执行文件及资源文件合并一个文件,上传和下载的文件则包含了所有的这些文件,导致占用较多的存储空间。
App Thinning是一个关于节省iOS设备存储空间的功能,它可以让iOS设备在安装、更新及运行App等场景中仅下载所需的资源,减少App的占用空间,从而节省设备的存储空间。
根据Apple官方文档的介绍,App Thinning主要有三个机制:
开发者把App安装包上传到AppStore后,Apple服务会自动对安装包切割为不同的应用变体(App variant),当用户下载安装包时,系统会根据设备型号下载安装对应的单个应用变体。
On-Demand Resources
ORD(随需资源)是指开发者对资源添加标签上传后,系统会根据App运行的情况,动态下载并加载所需资源,而在存储空间不足时,自动删除这类资源。
开启Bitcode编译后,可以使得开发者上传App时只需上传Intermediate Representation(中间件),而非最终的可执行二进制文件。 在用户下载App之前,AppStore会自动编译中间件,产生设备所需的执行文件供用户下载安装。
其中,Bitcode的机制可以支持动态的进行App Slicing,而对于Apple未来进行硬件升级的措施,此机制可以保证在开发者不重新发布版本的情况下而兼容新的设备。
如果你的应用也准备启用Bitcode编译机制,就需要注意以下几点:
Xcode 7默认开启Bitcode,如果应用开启Bitcode,那么其集成的其他第三方库也需要是Bitcode编译的包才能真正进行Bitcode编译。
开启Bitcode编译后,编译产生的.app体积会变大(中间代码,不是用户下载的包),且.dSYM文件不能用来崩溃日志的符号化(用户下载的包是Apple服务重新编译产生的,有产生新的符号文件)。
通过Archive方式上传AppStore的包,可以在Xcode的Organizer工具中下载对应安装包的新的符号文件。
这份学习资料是为 iOS 初学者所准备的, 旨在帮助 iOS 初学者们快速找到适合自己的学习资料, 节省他们搜索资料的时间, 使他们更好的规划好自己的 iOS 学习路线, 更快的入门, 更准确的定位的目前所处的位置.
该文档会持续更新, 同时也欢迎更多具有丰富经验的 iOS 开发者将自己的常用的一些工具, 学习资料, 学习心得等分享上来, 我将定期筛选合并, 文档尚有一些不完善之处, 也请不吝指出, 感谢您对 iOS 所做的贡献, 让我们一起把国内的 iOS 做得更好, 谢谢.视频教程(英文)视频简介
斯坦福开放教程之一, 课程主要讲解了一些 iOS 开发工具和 API 以及 iOS SDK 的使用, 属于 iOS 基础视频
该课程的讲师 Paul Hegarty 是斯坦福大学软件工程学教授, 视频内容讲解得深入, 权威, 深受好评
iOS 开发的进阶课程, 开始涉及到 Core Animation, Core Data, OpenGL 等框架的应用
苹果官方提供的 iOS 学习视频
Lynda 上面 iOS 和 Objective-C 的学习资料比较多, 从初级到高级的都有, 覆盖面比较广, 无论 iOS 走到哪个层次, 都可以在上面挑到适合自己的课程
CodeSchool 上面的 iOS 不多, 不过质量都不错, 一些课程也挺有趣的
Udemy 帮助初学者规划了视频学习路线, 从新手到高级分的比较详细
斯坦福白胡子老爷爷最新的 iOS8 和 Swift 课程, 现在&
上面也有人在翻译视频教程(中文)视频简介
斯坦福白胡子老爷爷的系列视频, 所有视频皆完成翻译, 视频较新, 翻译质量也很高
全部视频翻译完毕, 较为深入的讲解 iPhone 开发, 视频适合给有一定 Objective-C 基础的人观看
慕课网的视频, 主要讲 Swift 的一些基本使用, 并在讲解的过程中做了几个小 APP, 最后还讲了 Sketch 制作分享按钮
视频还未完结, 讲了一些 C 和 Objective-C 的基本语法, 适合零基础的人观看
GitHub 上正在翻译的斯坦福最新的 iOS8 课程, 目前正在翻译, 未完结书籍书籍名称推荐理由
内容不多, 却都是精华, 有了一点 C 语言基础可以快速阅读此书, 大概一天时间就可以看完, 看完后对 iOS 开发能够有个基本的印象, 该书的
有各个章节习题的解答.
这本书在 Quora 上被评为 iOS 入门最佳书籍, 具体评价可见豆瓣下方该书籍的评论
适合打算深入了解 Cocoa 的人看
短小精练, 适合有编程基础的人在半小时内对 Objective-C 有个一定了解
看完 Learn Objective-C 可以接着看这个官方对 Objective-C 更为深入的介绍
该书作者 Scott Knaster 是 Mac 开发界的传奇人物, 目前在 Google 出过多数书籍都广受许多程序员好评, 此书适合从初级跳到中级的 iOS 开发者阅读
该书作者唐巧是国内 iOS 开发界的名人, 曾参与多个知名软件的开发, 目前该书尚在预售中, 书本内容由浅入深, 将读者一步一步引入到 iOS 中去, 同样适合初级跳到中级的 iOS 开发者阅读
这本书在亚马逊上面深受欢迎, 有关 Objective-C 的东西讲得非常详细
该书作者是豆瓣的员工, 书中写的多数内容都是作者在平时的工作实践当中提炼出来的测试经验, 重点讲述了各个测试阶段的具体实践方法, 并且通过持续集成串联了各个测试阶段的活动。
解析 iOS 的开山之作, 详细介绍了 MVC 在 Cocoa Touch 上的运作过程, 该书适用于 iOS 中级开发者阅读
本书主要介绍 iOS 与 OS X 多线程和内存管理, 深入破析了苹果官方公布的源代码, 告诉你一些苹果公司官方文档中不会出现的知识, 适合中级以上 iOS 开发人员阅读
书里写了编写高质量 iOS 与 OS X 代码的 52 个有效方法, 适合 iOS 开发的进阶使用
估计将来这本书会成为 Swift 的经典入门书籍, 它的 Stars 数说明了一切
90 后开发者梁杰组织翻译的 Swift 编程语言中文版博客博客地址博主信息
王巍(喵神), 现居日本, 就职于 LINE, 知名 iOS 开发者, 写的文章大多深入浅出, 内容广泛, 目前在维护的&
&也值得收藏
唐巧, 国内知名 iOS 开发者, 现就职于猿题库, 博客推出的 iOS 移动开发周报很受欢迎, 更新频繁
90 后 iOS 开发者, 人称虾神, 文章内容讲解大多浅白易懂, 很值得看
博主也是 iOS 大神一个, 经常更新一些 iOS 教程, 文章的质量都很高, 非常值得看
NSHipster 的中文网站, 主要对 NSHipster 的英文网站进行翻译, 博文出自 Mattt 大神之手, 文章大都写得很深入, 详细, 每周一更
李忠, 知乎前员工, 目前在负责花瓣 iOS 开发, 不少文章里面有介绍博主个人的学习方法, 让读者在学到技术的同时也掌握学习的技巧
iOS 圈的女神人物, 写的关于安全问题的文章都值得一看, 由于新博客刚开通不久, 目前文章较少, 可以去看下她以前的
吴发伟, 天猫资深软件开发工程师, iOS 技术周报每周一更, 推送一些 iOS 技巧, 代码库, 设计等资讯.
王轲, IndieBros Studio 创始人, 优秀的 iOS 开发工程师, 写的文章深入浅出, 很多问题分析透彻, 非常有条理性
叶孤城, 优秀 iOS 开发工程师, 发表的文章都有很多干货, 对源码解析类文章写得浅显易懂, 并时常总结一些 iOS 开发技巧, 值得一读
周楷雯, 秒视创始人, 知名 iOS 工程师, 做出了&
&这样的好项目, 在博客中也有谈到具体的实现过程
图拉鼎, 知名 Apple 平台开发者, 曾经的 Ubuntu 平台开发者, 文章有不少干货, 大多讲解技术实现和学习经验
唐巧收集的中文 iOS/Mac 开发博客列表, 更新频繁, 值得收藏文章标题内容简介
Udemy 写的文章, 说明了一些学习 Objective-C 的前提条件, Objective-C 的发展历史, 学习方法以及学习资源
主要对 iOS 的开发环境进行了介绍, 并且涉及到了 Swift 的学习, iOS 上架的注意事项, iOS 的设计, 测试, 代码托管等, 讲解较为广泛, 同时也给出不少学习资源
文章写的很有条理, 文中多次强调了版本控制系统的重要性, 主要内容是对学习 iOS 开发到就职, 给出了自己的建议
作者总结了一些自己学习 iOS 的血的教训, 最后给出了一些不错学习建议
作者列举了一些学习 iOS 的方法以及常用的库, 以及自学 iOS 的一些建议
唐巧写的一篇文章, 主要是对 iOS 技术的提高做的一个总结, 文中不少资源, 工具, 学习方法
文章从入门到进阶到高级, 分为三个阶段, 有条理的讲出了 iOS 的整个学习过程中开发者可能遇到的问题, 并给出了解决办法, 奉献了不少好工具, 资源还有珍贵的学习经验
作者给出了学习 iOS 的流程, 并给出一些不错的学习资源
作者在文中给出了学习的一些建议, 也谈到了自己的学习方法
文中谈到了英语的重要性, 以及写博客, 看源代码的好处
作者分享了自己学习 iOS 的经验和资源
破船之家发布的资源汇总
文章讲解了 CocoaPods 的基本使用, 并且配上 AFNetworking 做出了一个小 Demo, 值得一看
作者简单介绍了一下自己 iOS 开发的感受,也是他学习 iOS 开发的一个体系架构。相关网站网站简介
不定时更新一些 iOS 教程
苹果官方每年一度的 WWDC 视频, 可以了解历年有关 iOS 发布的内容
WWDC 的文字版
该网站收集了很多关于 Swift 的学习资料, 新闻
经常发布一些 iOS 编程教程, 更新比较频繁, 想了解更多可以查看该网站的 About 界面
NSHipster is a journal of the overlooked bits in Objective-C, Swift, and Cocoa. Updated weekly.
Some tutorials about Core Graphic and Core Animation.
大把的 Objective-C, Swift, iOS 教程, 且全部免费, Raywenderlich 真是业界良心, 赞!社区社区简介
全球最大苹果开发者中文社区
经常更新一些很不错的 iOS 代码片段和一些 iOS 资源
定期发布一些有关 Objective-C 的高质量的文章
喵神组织的对 objc.io 的翻译网站, 旨在推进国内技术圈整体水平, 翻译质量非常高
发布一些 iOS 的最新资讯及教程
Cocos2d-x 论坛
国外较有名的 iOS 开发者论坛
这两本书籍的官方论坛, 用户活跃度较高
苹果官方的开发者论坛
Swift 中文社区工具/插件工具/插件简介
开发 OS X 和 iOS 应用程序的一个第三方库的依赖管理工具, 本身是 Ruby 的一个 Gem, 极大的简化了 Objective-C 的开发流程
Alcatraz 是一款管理 Xcode 插件、模版以及颜色配置的工具
使 Xcode 调试控制台色彩更丰富
Facebook 开源的一个 iOS 编译和测试的工具
一款注释辅助插件,主要用于收集并列出项目中的TODO,&FIXME,&???,&!!!
自动补全图片命名的一款插件
一个自动生成代码注释的工具
用于压缩图片一款工具
开发流程工具,将开发过程流程化,极大提高开发效率
其中包含了非常多好用的工具, 涉及到设计, 分析, 部署等, 总结的十分详细, 有
唐巧总结的一些图形应用工具, 命令行工具, Xcode 插件, 并介绍了一点基础的用法指南/教程网址简介
iOS 应用商店审核指南, 有
有很多丰富的 Swift 学习资料, 学习 Swift 有这份资料可以省下很多力气
Tinyfool 推出的一篇对于帮助新手阅读官方文档的指南
苹果写的一篇入门指南, 粗略讲解了 iOS 程序从开发到上架的整个流程
文章主要讲解 Objective-C 的一些语法, 文章内容有趣且通俗易懂
一张 iOS 开发地图, 做得很赞, 看完对 iOS 开发流程有一定的认知
苹果官方给出的 iOS 入门教程, 看过之后能够做一个 To-Do 小程序
讲解 Objective-C 的教程, 图文并茂, 适合新手阅读
Ray Wenderlich 推出的 Objective-C 风格指南
每日一个 iOS8 的小教程, 所以的 DEMO 都可以在其&
上面的找到相关代码邮件订阅
&(每周一期,内容多为这一星期里值得关注的 GitHub 项目、文章、工具等)
&(Tips, news and inspiration delivered each week)
&(iOS 开发必看, 有此文档足矣, 内容非常之详细)
Awesome 系列
知乎上的讨论
Quora 上的讨论
国内知名的程序员开发日报
在WWDC2014中,苹果推出了最新的iOS8系统,其中也伴随着很多控件的更新与升级。其中全新的WebKit库让人很是兴奋。本文也将讲解到WebKit中更新的WKWebView控件的新特性与使用方法,它很好的解决了UIWebView存在的内存、加载速度等诸多问题。
环境信息:
Mac OS X 10.10.1
Xcode 6.1.1
正文:一、WKWebView新特性
在性能、稳定性、功能方面有很大提升(最直观的体现就是加载网页是占用的内存,模拟器加载百度与开源中国网站时,WKWebView占用23M,而UIWebView占用85M);
允许JavaScript的Nitro库加载并使用(UIWebView中限制);
支持了更多的HTML5特性;
高达60fps的滚动刷新率以及内置手势;
将UIWebViewDelegate与UIWebView重构成了14类与3个协议();
二、初始化1. 首先需要引入WebKit库 #import &WebKit/WebKit.h& 2. 初始化方法分为以下两种 // 默认初始化 - (instancetype)initWithFrame:(CGRect) // 根据对webview的相关配置,进行初始化 - (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration NS_DESIGNATED_INITIALIZER; 3. 加载网页与HTML代码的方式与UIWebView相同,代码如下: WKWebView *webView = [[WKWebView alloc] initWithFrame:self.view.bounds]; [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@&&]]]; [self.view addSubview:webView]; 三、 WKWebView的代理方法1. WKNavigationDelegate
该代理提供的方法,可以用来追踪加载过程(页面开始加载、加载完成、加载失败)、决定是否执行跳转。 // 页面开始加载时调用 - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *) // 当内容开始返回时调用 - (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *) // 页面加载完成之后调用 - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *) // 页面加载失败时调用 - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)
页面跳转的代理方法有三种,分为(收到跳转与决定是否跳转两种) // 接收到服务器跳转请求之后调用 - (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *) // 在收到响应后,决定是否跳转 - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionH // 在发送请求之前,决定是否跳转 - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionH 2. WKUIDelegate // 创建一个新的WebView - (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowF
剩下三个代理方法全都是与界面弹出提示框相关的,针对于web界面的三种提示框(警告框、确认框、输入框)分别对应三种代理方法。下面只举了警告框的例子。 /** * web界面中有弹出警告框时调用 * * @param webView 实现该代理的webview * @param message 警告框中的内容 * @param frame 主窗口 * @param completionHandler 警告框消失调用 */ - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(void (^)())completionH 3. WKScriptMessageHandler
这个协议中包含一个必须实现的方法,这个方法是提高App与web端交互的关键,它可以直接将接收到的JS脚本转为OC或Swift对象。(当然,在UIWebView也可以通过“曲线救国”的方式与web进行交互,著名的Cordova框架就是这种机制) // 从web界面中接收到一个脚本时调用 - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *) 四、WKWebView加载JS // 图片缩放的js代码 NSString *js = @&var count = document.images.for (var i = 0; i & i++) {var image = document.images[i];image.style.width=320;};window.alert('找到' + count + '张图');&; // 根据JS字符串初始化WKUserScript对象 WKUserScript *script = [[WKUserScript alloc] initWithSource:js injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES]; // 根据生成的WKUserScript对象,初始化WKWebViewConfiguration WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init]; [config.userContentController addUserScript:script]; _webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config]; [_webView loadHTMLString:@&&head&&/head&&img src='http://www./v/2014v3/img/background/3.jpg' /&&baseURL:nil]; [self.view addSubview:_webView]; 五、本文Demo下载
六、关于JS的加载或WebView的其他使用技巧,可查看一下文章:
参考资料:}

我要回帖

更多关于 eve好玩吗 到底怎么玩 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信