ios开发_ios开发源码 - CSDN
精华内容
参与话题
  • iOS9程序设计(顶级iOS开发视频课程-Objective-C版) 本课程主要内容包括: iOS9的基础知识 常用控件 屏幕适配 多窗口 导航 表视图 GPS 地图 网络 数据存储、 音频 视频 本地化等内容,并提供了大量的...
  • iOS开发入门教程

    万次阅读 2016-07-22 21:52:18
    iOS开发入门教程,从创建项目到运行项目,包括OC基础,调试,模拟器设置等相关知识。 程序发轻狂,代码阑珊,苹果开发安卓狂!——写给狂热的编程爱好者们 写在前面的话 学习iOS应用程序开发已有一段...
    摘要
    iOS开发入门教程,从创建项目到运行项目,包括OC基础,调试,模拟器设置等相关知识。

    程序发轻狂,代码阑珊,苹果开发安卓狂!——写给狂热的编程爱好者们

    本文概览

    写在前面的话

    学习iOS应用程序开发已有一段时间,最近稍微闲下来了,正好也想记录一下前阶段的整个学习过程。索性就从最基础的开始,一步一步记录一个最简单的iOS应用从创建到运行的全过程,其中会穿插很多相关知识或是遇到过的问题。其实算不上教程,但希望能够帮助更多的开发爱好者更快、更好的入门。

    iOS开发环境简述

    最友好,最现实,也是最方便的开发环境就是在Mac系统中安装Xcode进行开发。原因在于:第一,开发工具(Xcode)限制。苹果官方只提供Mac版的Xcode,而Xcode内置了Xcode IDE,性能分析工具,iOS SDK,iOS模拟器和最新的OS X,可以方便迅速的进行代码编辑以及应用调试,可谓是Mac和iOS开发工具的不二选择。第二,代码提示和自动补全。iOS开发中用到的类或方法的名称,为了更具语义化,让开发者一目了然,通常会比较长,这往往会让刚刚接触iOS开发的开发者为了记住这些方法而伤透脑经。而Xcode拥有优于其他编辑器的OC代码提示和自动补全功能,这将很大程度降低开发入门的门槛,这决定你开发iOS应用没有理由不使用Xcode。因此,使用非苹果电脑的开发者们最好安装Mac OS X的虚拟机,进行开发学习,否则你不仅会比别人花上多出一倍甚至更多的时间去搭建开发环境,而且代码编写上也会比使用Xcode开发的人花上更多的精力。

    第一步,创建项目

    1.1 新建iOS项目

    打开Xcode,如果是首次打开Xcode,你将会看到一个欢迎界面,如图:

    Welcome to Xcode

    你可以直接在该界面中点击图中1处标记的Create a new Xcode project来创建一个项目,也可以点击图中2处标记的按钮来打开电脑中已经存在的Xcode项目。你还可以修改3处标记的复选框状态设置下次启动Xcode是否显示该欢迎界面。

    本文不演示在此点击1处所示创建项目,首先点击该界面左上角的红色按钮退出该欢迎界面,然后点击屏幕左上角的File->New->Project。截图如下:

    新建项目

    接下来你将看到如下界面:

    选择应用模板

    首先进行系统筛选,iOS应用则选择iOS列表对应项,OS X应用则选择OS X列表对应项。本例为iOS应用,故在此选择iOS中的Application(图中左上角红框所示),然后选择应用模板选择,在界面右边列出了多种最常用的应用模板类型,开发者按照自己的应用需求可自行选择,本例选择Single View Application(图中右上角红框所示)。做完以上选择后点击窗口右下角Next按钮,进入下一个设置窗口:

    应用基础信息设置

    此处内容会根据个人情况而不同,故不做赘述,按照窗口提示,填写相关信息即可。注意窗口下方的三个复选框,其功能分别是使用storyboards使用自动引用计数器包含单元测试,根据个人情况勾选/取消即可。设置完成后点击右下角Next按钮,进入下一个窗口:

    选择保存位置

    按照窗口所示,选择项目存储位置后点击窗口右下角Create按钮,完成应用创建过程。

    1.2 应用程序目录结构说明

    项目创建完成之后,Xcode会进入项目开发界面,界面大致分为三部分,左侧项目及目录结构列表、中间为代码编辑区、右侧属性设置和控件列表等区域。下面是目录结构的截图:

    项目目录结构

    项目初始时包含如图所示三个主要目录,后续开发中开发者可以自行添加目录。其中:

    • FirstIosApp目录与项目名称同名,主要存放应用相关源代码和配置文件;
    • Framework存放项目使用到的框架,默认会添加图示三个必备框架;
    • Products用于存放生成的应用文件,开发中开发者一般不必关心。

    1.3 应用程序初始结构概览

    整个应用程序的入口文件默认为AppDelegate.m,应该可以通过配置文件修改(未尝试)。其内部结构如下:

    应用程序入口结构

    该文件包含应用程序生命周期中各个阶段可以调用的方法接口,以便应用程序在不同的状态阶段能进行相应的操作。这些方法就不一一说明了,开发者几乎可以望名知意。

    1.3.1 iOS应用程序的生命周期

    对于上面图示方法如果还有不解的地方,可以参考下图(来源于网络):

    iOS生命周期

    第二步 代码入门(数据类型)

    做iOS开发,仅仅懂得使用Xcode,仅仅了解目录结构,仅仅了解生命周期,是远远不够的,这些只是基础中的基础。一定的编程能力也是必不可少的。下面就简单的介绍一下iOS开发的编程语言——Objective-C,后面简称OC。

    学习一门语言,往往需要从最基础的数据类型开始(记得大学学习的时候老师就是这么干的),至于编程逻辑,奇技淫巧等则是在开发过程中慢慢积累的。好言归正传。

    2.1 基础数据类型

    OC是C语言的一个超类,因此OC拥有C或C++的几乎所有特性,当然它也有自己独具一格的地方。所以OC也支持C语言的数据类型,诸如int,float等也都可以在OC中使用。基础数据类型不是本文重点,在此就不多言辞了。

    2.2 OC数据类型

    OC不是仅仅只能使用C/C++的数据类型,它也拥有自己的数据类型,虽然与通常人们熟知的各种数据类型看起来有点怪异,但事实上OC的数据类型是个很好玩的东西,也不难理解。下面列举几个常见的OC数据类型。

    2.1.1 NSNumber类和NSInterger

    NSNumber是以对象的形式来包装基础数据类型,它提供以下方法:

    <!-- lang: cpp -->
    + (NSNumber *) numberWithChar: (char) value;
    + (NSNumber *) numberWithInt: (int) value;
    + (NSNumber *) numberWithFloat: (float) value;
    + (NSNumber *) numberWithBool: (BOOL) value;
    

    例如,要从一个int数据初始化一个NSNumber可以这样写:

    <!-- lang: cpp -->
    NSNumber *number = [NSNumber numberWithInt: 100];
    

    而要从NSNumber实例得到NSInteger数据则可以如下操作:

    <!-- lang: cpp -->
    NSInteger integer = [number intValue];
    
    2.1.2 NSString类型

    NSString是OC的字符串类。与普通字符串不同的是NSString的值需要在普通字符串前加上一个@符号。例如要初始化一个'I'm a string.'的OC字符串,我们需要这样做:

    <!-- lang: cpp -->
    NSString *str = [NSString stringWithString: @"I'm a string."];
    

    看起来很麻烦,很复杂的样子,不要担心,OC应该也考虑到了这一点,所以它也提供简写形式:

    <!-- lang: cpp -->
    NSString *str = @"I'm a string.";
    

    NSString类还提供了很多其他形式的创建字符串的方法(比如:stringWithFormat等),这里就不一一列举了,以后在开发中慢慢体会吧。

    2.1.3 NSArray类型

    NSArray是OC的数组类。OC的数组是很强大的,在一个数组中可以允许存在不同类型的数据,这个特性就跟强大的JavaScrit一样。初始化一个数组可以这样操作:

    <!-- lang: cpp -->
    NSArray *arr = [NSArray arrayWithObjects:@"a", @"b", @1, nil];
    

    当然也支持简化形式:

    <!-- lang: cpp -->
    NSArray *arr = @[@"a", @"b", @1];
    

    需要说明一点,使用arrayWithObjects方法创建数组的时候最后需要以nil结尾,而使用简化方式的时候不需要。

    开发中可以使用以下两种形式获取数组对应索引位置(index)的值:

    <!-- lang: cpp -->
    NSString *a = arr[index];
    NSString *b = [arr objectAtIndex: index];
    

    2.1.4 NSDictionary类型

    NSDictionary是OC的字典类。字典类型在使用中以key-value键值对的形式存在。也支持多种初始化方式,下面列举两种:

    <!-- lang: cpp -->
    NSDictionary *dic = [NSDictionary dictionaryWithObjects:@[@"a",@"b", @"c"] forKeys:@[@"first", @"second", @"third"]];
    //或者使用下面的形式
    NSDictionary *dic = @{@"first": @"a", @"second": @"b", @"third": @"c"};
    

    取值方法跟NSArray大同小异:

    <!-- lang: cpp -->
    NSString *a = [dic objectForKey: @"first"];
    NSString *b = dic[@"second"];
    

    2.1.5 NSDate类型

    NSDate是OC的日期类。常见用法举例:

    <!-- lang: cpp -->
    NSDate *date = [NSDate date]; //返回当前时间
    NSDate *date = [[NSDate alloc] init]; //初始化为当前时间,类似date
    

    第三步 OC类的认识(成员变量和方法)

    iOS开发常常伴随着视图,而视图往往离不开视图控制器,在iOS开发中每一个视图控制器就是一个OC的类,因此学习iOS开发就必须了解OC的类。

    OC的类使用@interface ClassName: superClass <protocol> … @end结构来定义,NSObject是所有OC类的父类。与java相比OC的@interface关键字就等同于JAVA的class关键字,OC的protocol就是JAVA中的interface,这一点很据迷惑力,大家在学习时需要特别注意。

    3.1 类的声明

    举例声明一个Person的类(视图控制器)并实现它,拥有nameage两个成员变量,自然需要定义getNamesetNamegetAgesetAge,下面我们看下这个过程。

    首先,类的结构如下:

    <!-- lang: cpp -->
    @interface Person: NSObject {
        NSString *name;
        int age;
    }
    
    @end
    

    然后,我们声明它的setter和getter方法,用来设置和读取它的成员变量的值。按照传统方式应该如下定义:

    <!-- lang: cpp -->
    @interface Person: NSObject {
        NSString *name;
        int age;
    }
    
    - (void) setName: (NSString *) newName;
    - (NSString *) getName;
    
    - (void) setAge: (int) newAge;
    - (int) getAge;
    
    @end
    

    看,是不是很简单?然而,既然上面说了是传统方式,那么肯定OC还提供了更现代的方式:

    <!-- lang: cpp -->
    @interface Person: NSObject {
        NSString *name;
        int age;
    }
    
    @property(nonatomic, strong) NSString *name;
    @property(nonatomic, assign) int age;
    
    @end
    

    没错,你没看错,就这么简单,它的功能和上面的代码是一样的。补充一下,@property本身可以接受参数来指定变量的getter和setter方式,其参数可用值和具体功能如下:

    <!-- lang: cpp -->
    nonatomic //声明变量只在单线程中工作
    atomic //默认值,可能有多个线程会用到这个变量
    
    copy //分配一个新的空间,把原地址的内容复制过来
    assign //简单的传递指针
    retain //传递指针后引用计数器(retainCount)会自加1
    
    strong //强引用
    weak //弱引用
    

    声明就这样就完成了,下面我们看下它的具体实现,在OC中类的实现需要使用另外一个关键字@implementation,格式如下:

    <!-- lang: cpp -->
    @implementation Person
    
    @end
    

    我们还是先看下传统方式声明getter和setter方法该如何实现:

    <!-- lang: cpp -->
    @implementation Person
    
    - (void) setName: (NSString *) newName {
        self.name = newName;
    }
    
    - (NSString *) getName {
        return self.name;
    }
    
    - (void) setAge: (int) newAge {
        self.age = newAge;
    }
    
    - (int) getAge {
        return self.age;
    }
    
    @end
    

    看完传统实现方式,是不是很想一睹现代方式的风采?我们继续往下看:

    <!-- lang: cpp -->
    @implementation Person
    
    @synthesize name;
    @synthesize age;
    //或者直接下面一句
    //@synthesize name,age;
    
    @end
    

    是不是很神奇?在新版的Xcode中,@synthesize是可以省略的,但是建议还是都写上。

    3.2 “+”和“-”

    仔细的读者应该已经发现在上面的传统方式中包含了一个神奇的符号“-”。这个是什么意思呢?首先我们需要说明一下,一个类可以拥有成员变量和方法,而方法可以包含类方法和实例方法。所谓类方法是可以使用类名直接调用的方法,而实例方法是需要该类的实例才可以调用的方法。而在OC中使用“+”表示该方法为类方法,而“-”很简单自然是表示实例方法了。

    至于方法的声明和实现大致和传统方式声明getter和setter是一样的,这部分就不再重复了。

    第四步 运行和调试

    每一个应用的开发过程都是漫长的,而在这个过程中我们免不了需要不时的运行一下程序,看看当前的效果,检查一下代码是否存在异常或者错误。

    4.1 iOS模拟器

    4.1.1 选择设备

    Xcode的强大不是吹出来的,在Xcode中内置了iOS模拟器,能够模拟几乎所有iOS真机的功能,因此开发者可以通过iOS模拟器测试正在开发中的应用程序,提高开发效率,减少错误,节省开发时间。在运行前选择与应用对应的模拟设备是必须的,否则可能导致运行结果出现意外的问题。

    在Xcode的菜单栏下方提供了选择模拟器的地方,如图所示:

    选择模拟器

    选择好模拟器后点击左侧的Run按钮,就可以在指定的模拟器中启动应用了。第一次启动模拟器一般会比较慢,后面就好了。同样可以点击Run旁边的Stop按钮,停止模拟器中的当前应用。也许有些时候你想独立运行iOS模拟器,而不启动当前应用,这也是可以的,请看下图:

    启动模拟器

    也许相同的设备,但是却又多个尺寸,多个屏幕分辨率,例如:iPhone就有4、4S、5等。那怎么选择呢?别当心,有模拟器呢:

    选择不同的分辨率

    真是iOS模拟器在手,开发调试不用愁啊!

    4.1.2 模拟器自定义设置

    看完了上面的介绍,是不是感觉有一种马上动手的冲动?先别急,还有更高级的呢!大家知道,现在很多流行的iOS应用都有定位功能,那么在模拟器怎么测试定位呢?看看下图你就明白了:

    设置模拟器经纬度

    4.1.3 存储屏幕快照

    开发应用程序通常都不是一步到位的,过程中可能会产生各种各样稀奇古怪的现象,也许是显示不正常,也许是出现意外的效果,也或者你想把你当前的显示效果分享给开发团队的其他成员,这个时候作为开发者,你也许想要记录出现的这些现象,比如:截图、录屏什么的。这些都是不错的方法,但是iOS模拟器拥有更加方便的方式,如图所示:

    存储屏幕快照

    4.2 程序调试

    每一个开发者都不能保证他的程序是完美的,所以通常在我们运行程序的时候会出现很多奇怪的警告或者错误,有的可以一目了然,迎刃而解,有的却隐藏得很深,很难发现。这时候断点调试就直观重要了。

    在代码编辑器的左边的行号区,鼠标在这个区域单击可以在对应行上添加/关闭(不是删除)断点。启动断点,当再次运行程序的时候,程序若执行到当前行,则会暂停在当前行上,开发者可以在控制台看到断点处记录的信息。大致如图:

    断点调试

    如图所示,在断点处我们可以在控制台看到变量date的当前值以及内存地址等信息,这样就可以通过这些信息判断程序运行到该处时是否正常,也可以这样查看一些其他信息。

    4.3 NSLog

    有些时候我们可能会遇到一些仅靠断点无法解决的问题,这时我们还可以借助NSLog进行调试。NSLog也用于在控制台输出信息。如图:

    NSLog调试

    展开全文
  • IOS 初级开发入门教程(一)介绍篇

    千次阅读 2019-02-24 11:29:02
     目前移动端开发市场上引导开发者追求技多不压身,一个全栈开发者至少要懂后台服务器、数据库、Android、web、ios开发等。“一超多强”是指开发者先成为一门技术的专家然后掌握了解多门技术,这是一种好的发展趋势...

    导读
           目前移动端开发市场上引导开发者追求技多不压身,一个全栈开发者至少要懂后台服务器数据库Androidwebios开发等。“一超多强”是指开发者先成为一门技术的专家然后掌握了解多门技术,这是一种好的发展趋势,另外,这种技多不压身我认为当开发者更适合发展成为Leader管理岗位,随着年龄慢慢变大,成家立业后,基层单一码农已晋升之路受到阻碍了,作为项目经理或总监的时候,需要你能够“多才多艺”,才能管理好带领好你的团队。这一篇将掀起 IOS 开发之路,点关注不迷路。
     
    可跳过介绍,直接上手敲代码: IOS 新手入门实现第一个HelloWorld项目

    什么是iOS
      iOS是苹果公司为它的移动设备(iPhone、iPad、iWatch等)开发的移动操作系统。

    iOS发展史
    2007年苹果发布iPhone Runs OS X
    2008年更名iPhone OS
    2010年更名iOS
    2012年WWCD 2012上发布iOS 6
    2013年WWCD 2013上发布iOS 7
    2014年WWCD 2014上发布iOS 8和Swift
    2015年WWCD 2015上发布iOS 9和Watch OS
    IOS开发语言
    ios目前流行两种开发语言:Objective-C 和 Swift 。前者有C语言基础者上手会容易些;后者Swift是iOS/Mac未来开发的主要语言,无论从编程思想还是从api书写,都赏心悦目,但缺点是没有Objective更稳定,且事实上去面试一些公司都要求的是用 Objective-C,只是把 Swift 作为学习语言。
    苹果设备屏幕尺寸
    设备    屏幕尺寸    分辨率    坐标点
    iPhone 3和3s    3.5英寸    320*480    320*480
    iPhone 4和4s(支持Retina)    3.5英寸    640*960    320*480
    iPhone 5和5s(支持Retina)    4英寸    640*1136    320*568
    iPhone 6    4.7英寸    750*1334    375*667
    iPhone 6 Plus    5.5英寸    1080*1920    414*736
    iPad 1和2(不支持Retina)    9.7    768*1024    768*1024
    iPad 3和4(支持Retina)    9.7    1536*2048    768*1024
    iPad Air    9.7    1536*2048    768*1024
    iPad Mini(不支持Retina)    7.9    768*1024    768*1024
    iPad Mini2(支持Retina)    7.9    1536*2048    768*1024

    系统基础框架
     1、ios系统架构可以分为如图所示的四层,Cocoa Touch框架的地位不言而喻。 

    è¿éåå¾çæè¿°

    Core OSCore Service提供了底层支持,包括文件访问、网络协议、低级数据类型等。
    Media提供了基本绘图和音视频的支持,包括OpenGLQuartzCore AudioCore Animation等。
    Cocoa Touch包括了开发使用的大部分API,主要由Foundation(文件访问、网络操作、数据和容器类型)和UIKit(UI控件、控制器等)两个部分构成。在进行App开发时,应该由上到下使用这些技术层次,越上层的API封装得越好,开发越方便,但能自己发挥的东西越少。
    2、对比,android系统架构:
    Android其本质就是在标准的Linux系统上增加了Java虚拟机Dalvik,并在Dalvik虚拟机上搭建了一个JAVA的application framework,所有的应用程序都是基于JAVA的application framework之上。

    也分为四个层,从高层到低层分别是应用程序层、应用程序框架层、系统运行库层和linux核心层。
    UIKit继承结构

      实现App开发中的用户界面首先要从UIResponder及其子类开始研究,当然整个过程会覆盖整个UIKit框架,比如UIColor(颜色)、UIEvent(事件)、UIFont(字体)、UIGestureRecognizer(手势识别)、UIImage(图像)、UIScreen(屏幕)等诸多内容。
    UIView和UIWindow
    1、UIWindow和UIView的继承关系
      UIWindow是UIView的子类。UIView定义了一个矩形区域以及操作这个矩形区域中内容的编程接口,除此之外UIView还要处理运行时区域中内容的交互行为(绘图、动画和事件处理)。从上面的图中我们也可以看出,我们要使用的控件都是UIView的子类型。视图会按层次结构排列,位于视图层次结构顶端的就是应用窗体。任何应用都有且仅有一个UIWindow对象,UIWindow对象就像一个容器,负责包含应用中的所有视图。应用需要在启动时创建并设置UIWindow对象,然后为其添加其他的视图,就像上面的代码呈现的那样。加入窗口的视图会成为该窗口的子视图。子视图也可以有自己的子视图从而构成一个以UIWindow作为根的视图层次结构(树形结构)。

    2、UIView的基本属性和方法
    frame属性:设置视图的坐标和尺寸
    backgroundColor属性:设置视图的背景色
    window属性:视图所在的窗口对象
    -addSubview方法:添加子视图
    Xcode创建iOS项目
      启动Xcode在欢迎页中选择"Create a new Xcode project"。在项目创建向导中选择iOS->Application->Single View Application然后点击下一步。接下来需要设置项目名称、组织名称、组织标识、开发语言(OC或Swift)和设备(iPhone、iPad或Universal)。下一步之后选择项目的位置就可以点击"Create"完成项目创建了。参考我的下一个博文:IOS新手入门第一个HelloWorld项目
    熟悉开发工具Xcode


    IDE布局说明:
    Xcode的上方是工具栏,有很多工具按钮。Xcode的左侧是导航区域,包括:项目导航、符号导航、查询导航、问题导航、测试导航、调试导航、断点导航、报告导航,可以使用Command+1-8的数字键在8种导航之间切换。Xcode的中间是编辑器区域;中间的下面是调试区域。Xcode的右侧上方是检查器(审查)区域;右侧下方是各种库的区域。

    Xcode常用功能和快捷键 (*实用)
    Command+[ -> 代码块左移
    Comamnd+] -> 代码块右移
    Tab -> 接受代码自动完成提示
    Esc -> 显示代码提示
    Command+B -> 编译
    Command+R -> 运行
    Control+F -> 前移光标
    Control+B -> 后移光标
    Control+P -> 光标移到上一行
    Control+N -> 光标移到下一行
    Control+A -> 光标移到行首
    Control+E -> 光标移到行尾
    Control+T -> 交换光标左右字符
    Control+D -> 删除光标右边的字符
    Control+K -> 删除本行
    Control+L -> 将光标所在位置置于窗口中央
    按住Option双击鼠标 -> 搜索文档
    Command+Y -> 激活/禁用断电
    Command+Control+Y -> 继续运行
    F6 -> 单步跳过
    F7 -> 单步跳入
    F8 -> 跳出
    AppDelegate与ViewController的作用与区别:
    AppDelegate是你整个应用的一个代理。当你应用启动的时候,最先被调用到的就是你AppDelegate中的- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions方法。你可以在这个方法中做些全局初始化。

    一般设计准则是尽量保持AppDelegate干净、简洁。

    AppDelegate中可以做应用退出后台或从后台返回到前台的一些处理。

    ViewController一般作为根视图控制器,把显示相关的都放到这里面去做。

    虚拟机HOME键:
    由于Xcode自带的虚拟机不像真机那样有一个可以用手指按的Home键回到主界面的实体按钮,所以需要用到快捷键:
    command + shift + h    (回到主界面)
    command + shift + hh  (可滑动清理应用)
    --------------------- 
    作者:艾阳丶 
    来源:CSDN 
    原文:https://blog.csdn.net/csdn_aiyang/article/details/77480907 
    版权声明:本文为博主原创文章,转载请附上博文链接!

    展开全文
  • 怎么学习iOS,如何学习iOS开发

    千次阅读 2018-05-04 17:49:50
    近年来ios app开发在不断发展中,各中小型也如雨后春笋纷纷露头,像广州商侣软件公司这样的app开发企业可以说是处处可见,然而ios app开发到底该如何入手,如何才能如鱼得水般在这个领域里面畅游呢? 一、什么是ios ...

         近年来ios app开发在不断发展中,各中小型也如雨后春笋纷纷露头,像广州商侣软件公司这样的app开发企业可以说是处处可见,然而ios app开发到底该如何入手,如何才能如鱼得水般在这个领域里面畅游呢?


      一、什么是ios app开发

      ios app开发是指针对苹果公司所生产的手机的ios系统的客户端软件进行开发,自从苹果手机开始上市以来,截止到2012年,4 年,65 万个 App,下载量 300 亿次,与开发者分成 50 亿美元,这是今年 WWDC苹果公布的数据。4 年来,苹果的 App Store 改变了很多人的命运,改变了人们的一些行为习惯。



    在这里我还是要推荐下我自己建的iOS开发学习群:727474737,群里都是学ios开发的,如果你正在学习ios ,小编欢迎你加入,今天分享的这个案例已经上传到群文件,大家都是软件开发党,不定期分享干货(只有iOS软件开发相关的),包括我自己整理的一份2018最新的iOS进阶资料和高级开发教程


      二、ios app开发前景如何

      在这部分中国 iOS 开发者们看来,5 年来,苹果 App Store 带给我们最大的影响在于带来了巨大的机会和希望。而这种机遇更多的在于为个人、小团队开发者提供希望。在 App Store 面前,无论公司大小、也不管公司是否强大,一律都是平等的,这在以前是不存在这种平台的。因此对于小团队、个人开发者来说,它提供的是一种改变自身命运的平台机遇。只要能开发出足够好的产品,你就有机会在短时间内创造奇迹。

    三、如何学习ios app开发

      为了吸引、帮助更多的人成为苹果iOS app应用开发者,苹果上线了一个iOS app应用开发官方教程。想成为一名iOS应用开发者的朋友,不用再埋头苦啃什么秘籍了,苹果官方将会推出ios app开发教程来告诉你如何开发ios app应用,需要什么工具、哪方面的知识等等。现在苹果iOS设备用户数越来越多,开发者的收入也水涨船高,不少人都跃跃欲试但却又无从下手。现在有了苹果iOS应用开发官方教程,大家可以自我增值,说不定下一个畅销的iOS应用,就出自你的手。


         开发ios app,除了需要必备的软件,比如Xcode、iOS SDK,还有硬件,比如一部Mac电脑、一部iOS设备用作测试。此外,你最好还是参加苹果的iOS开发者计划,这样,你才可以更好地测试你的app应用软件,甚至让你自己开发的app在iTunes App Store上架。

         论想学什么,也无论出于什么目的想学,都需要你保持好奇心。但是作为刚想入门的新手,面对眼前海量的信息,或许根本不知道从哪里开始。想学习编程?想自学?想高效的搞定编程这件事儿?学习编程的网站给刚入门的你,赶紧学起来。


        学习ios 。首先,基础很重要,学校开设的课程比如:数据结构和算法,设计模式,编译原理,操作系统原理,等不要认为是没有用的,在日后的编程中其实很多东西都需要用到那些知识。再掌握一门语言比如c/c++,因为很多底层的类库都是C写的。而且可以混编,特别是一些第三方的类库直接就是C++写的。其他的包括T-Sql,html,js等也可以了解下,因为基于hyper link方式的开发也在发展。


    然后,就要研究iOS开发的武器库了。入门的话可以看看基本的,很好理解也很实用。一定要学以致用!学以致用!学以致用!

    1.Beginning.iOS.5.Development.Exploring.the.iOS.SDK.Dec.2011



       2.Learn_Objective-C_for_Java_Developers/ Objective-C编程之道





    3.iOS 10 Programming Cookbook






    这三本看下来可以试试做一些简单的小项目,但是这离大神的级别是远远不够的。可能你知道但是具体为什么这么用,或者更深层次的东西你不一定了解清楚,这个时候就要看进阶文档了。

    针对程序员行业,这是一个需要努力奋斗的行业,也许他并不需要你有多高的文凭,好的文凭可以去大公司工作,没有好的文凭,但拥有丰富的工作经验,和开源库,也会是你本人实力的体现.所以,努力学习,路是自己走出来的,原地踏步谁也救不了你.。


    展开全文
  • 本视频教程拥有180节课程,包含iOS开发的方方面面:iOS开发基础理论知识、 视图、视图控制器、多媒体、数据处理、常用插件、信用卡卡号识别、自动化测试、网络访问、多线程、ShareSDK社会化分享、CoreImage、...
  • ios开发知识汇总

    千次阅读 2018-06-11 09:30:10
    1.技术基础1、为什么说Objective-C是一门动态的语言?这里的动态和静态是相对的,动态的意思是不需要在编译时确定所有的东西,在运行时也可以动态添加变量,属性,方法和类. Objective-C 可以通过Runtime这个运行时机制,...

    1.技术基础

    1、为什么说Objective-C是一门动态的语言?

    这里的动态和静态是相对的,动态的意思是不需要在编译时确定所有的东西,在运行时也可以动态添加变量,属性,方法和类. Objective-C 可以通过Runtime这个运行时机制,在运行时动态的添加变量,方法和类等,所以说Objective-C是一门动态的语言. 
    Objective-C的动态性,让程序在运行时判断其该有的行为,而不是像c等静态语言在编译构建时就确定下来。它的动态性主要体现在3个方面: 
    1.动态类型:如id类型。实际上静态类型因为其固定性和可预知性而使用的特别广泛。静态类型是强类型,动态类型是弱类型,运行时决定接收者。 
    2.动态绑定:让代码在运行时判断需要调用什么方法,而不是在编译时。与其他面向对象语言一样,方法调用和代码并没有在编译时连接在一起,而是在消息发送时才进行连接。运行时决定调用哪个方法。 
    3.动态载入。让程序在运行时添加代码模块以及其他资源。用户可以根据需要执行一些可执行代码和资源,而不是在启动时就加载所有组件。可执行代码中可以含有和程序运行时整合的新类。

    2、讲一下MVC和MVVM,MVP?

    • Models(模型) — 数据层,或者负责处理数据的 数据接口层。比如 Person 和 PersonDataProvider 类 
    • Views(视图) - 展示层(GUI)。对于 iOS 来说所有以 UI 开头的类基本都属于这层。 
    • Controller/Presenter/ViewModel(控制器/展示器/视图模型) - 它是 Model 和 View 之间的胶水或者说是中间人。一般来说,当用户对 View 有操作时它负责去修改相应 Model;当 Model 的值发生变化时它负责去更新对应 View。

    MVC

    MVC
    Controller: 控制器层,它是 Model 和 View 之间的胶水或者说是中间人。一般来说,当用户对 View 有操作时它负责去修改相应 Model;当 Model 的值发生变化时它负责去更新对应 View。

    MVVM

    MVVM
    在MVVM 中,view 和 view controller正式联系在一起,我们把它们视为一个组件 
    view 和 view controller 都不能直接引用model,而是引用视图模型(viewModel) 
    viewModel 是一个放置用户输入验证逻辑,视图显示逻辑,发起网络请求和其他代码的地方

    MVP

    MVP
    MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负责显示。作为一种新的模式,MVP与MVC有着一个重大的区别:在MVP中View并不直接使用Model,它们之间的通信是通过Presenter (MVC中的Controller)来进行的,所有的交互都发生在Presenter内部,而在MVC中View会从直接Model中读取数据而不是通过 Controller。

    参考资料: 
    https://blog.coding.net/blog/ios-architecture-patterns 
    https://www.jianshu.com/p/eedbc820d40a 
    http://blog.csdn.net/li_shuang_ls/article/details/50176891 
    https://www.jianshu.com/p/33c7e2f3a613

    3、为什么代理要用weak?代理的delegate和dataSource有什么区别?block和代理的区别?

    1.为什么代理要用weak? 
       防止循环引用。例如View有一个协议,需要一个代理实现回调。一个Controller添加这个View,并且遵守协议,成为View的代理。如果不用week,用strong,Controller ->View -> delegate -> Controller,就循环引用了。

    2.代理的delegate和dataSource有什么区别? 
       delegate偏重于与用户交互的回调,有那些方法可以供我使用,例如UITableviewDelegate;dataSource偏重于数据的回调,view里面有什么东西,属性都是什么,例如UITableviewDatasource;

    3.block和代理的区别? 
    1.block简介 
    在 iOS中, block一共分三种。 
      (1)全局静态 block,不会访问任何外部变量,执行完就销毁。

        ^{
            NSLog(@"Hello World!");
        }();
    • 1
    • 2
    • 3

    (2)保存在栈中的 block,当函数返回时会被销毁,和第一种的区别就是调用了外部变量。

        [UIView animateWithDuration:3 animations:^{
    
            self.view.backgroundColor = [UIColor redColor];
        }];
    • 1
    • 2
    • 3
    • 4

    (3)保存在堆中的 block,当引用计数为 0 时会被销毁。例如按钮的点击事件,一直存在,即使执行过,也不销毁,因为按钮还可能被点击,持有按钮的View被销毁,它才会被销毁。

    2.block优点 
    block的代码可读性更好。因为应用block和实现block的地方在一起。代理的声明和实现就分开来了,在两个类中。代理使用起来也更麻烦,因为要声明协议、声明代理、遵守协议、实现协议里的方法。block不需要声明,也不需要遵守,只需要声明和实现就可以了。 
      block是一种轻量级的回调,可以直接访问上下文,由于block的代码是内联的,运行效率更高。block就是一个对象,实现了匿名函数的功能。所以我们可以把block当做一个成员变量、属性、参数使用,使用起来非常灵活。像用AFNetworking请求数据和GCD实现多线程,都使用了block回调。

    3.block缺点 
    blcok的运行成本高。block出栈需要将使用的数据从栈内存拷贝到堆内存,当然对象的话就是引用计数加1,使用完或者block置nil后才销毁。delegate只是保存了一个对象指针(一定要用week修饰delegate,不然也会循环引用),直接回调,没有额外消耗。就像C的函数指针,只多做了一个查表动作。 
      block容易造成循环引用,而且不易察觉。因为为了blcok不被系统回收,所以我们都用copy关键字修饰,实行强引用。block对捕获的变量也都是强引用,所以就会造成循环引用。

    4.如何使用 
    优先使用block。 
      如果回调函数很多,多余三个使用代理。 
      如果回调的很频繁,次数很多,像UITableview,每次初始化、滑动、点击都会回调,使用代理。 
       
    5. 代理和Block的区别 
    相同点:代理和Block大多是我们都可以用来做倒序传值的。我们都得注意避免循环引用。不然我们去使用代理还是Block的时候,都需要判断它们是否实现 
    不同点:代理使用weak修饰,代理必须先声明方法。当我们调用代理的时候要判断是否已经实现。 
    block:使用的是copy来修饰,block保存的是一段代码,其实也就是一个函数。并且可以自动捕捉自动变量,如果想修改此自动变量,还必须使用__block修饰。 
       
    参考资料: 
    https://www.jianshu.com/p/6bba9b4a25d5

    4、属性的实质是什么?包括哪几个部分?属性默认的关键字都有哪些?@dynamic关键字和@synthesize关键字是用来做什么的?

    属性是一个类中用来描述对象的抽象概念。 
    属性包括的部分有setter和getter方法

    atomic: 
    nonatomic:
    @synthesize
    @dynamic
    getter=getterName
    setter=setterName
    readwrite
    readonly
    assign
    retain
    copy
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    @synthesize 
    如果没有实现setter和getter方法,编译器将会自动在生产setter和getter方法。

    @dynamic 
    表示变量对应的属性访问器方法 , 是动态实 现的 , 你需要在 NSObject 中继承而来的 +(BOOL) resolveInstanceMethod:(SEL) sel 方法中指定 动态实现的方法或者函数。 
    属性修饰其他关键字:

    参考 
    *http://www.wimhe.com/archives/46 
    *http://www.wimhe.com/archives/47

    5、属性的默认关键字是什么?

    默认关键字,基本数据: atomic,readwrite,assign 
    普通的 OC 对象: atomic,readwrite,strong

    6、NSString为什么要用copy关键字,如果用strong会有什么问题?(注意:这里没有说用strong就一定不行。使用copy和strong是看情况而定的)

    >

    // 深复制
    Person *xiaoMing = [[Person alloc] init];
    NSMutableString * name = [[NSMutableStringalloc] initWithString:@"xiaoming"];
    //name.string = @"xiaoming";
    xiaoMing.name = name;
    NSLog(@"%@", xiaoMing.name);
    [name appendString:@"hah"];
    
    //此时名字这个属性被修改了
    NSLog(@"%@", xiaoMing.name);
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    如果用Copy来修饰name这个属性不会改变, 
    如果使用Strong,当name这个字符串改变的时候,name这个属性也会随着改变。 
    补充:这其实也是看需求,看被赋值的字符串是否需要随着赋值字符串的变化而变化,而大多数情况下我们不希望被赋值的字符串如某个对象的某个字符串类型的属性会随着赋值字符串的变化而变化。 反之,如果我们希望被赋值的字符串随着赋值字符串的变化而变化,那么我们也可以使用strong来修饰字符串

    参考: 
    *https://www.jianshu.com/p/499f2927717c

    7、如何令自己所写的对象具有拷贝功能?

    需实现 NSCopying 协议。如果自定义的对象分为可变版本与不可变版本,那么就要同时实现 NSCopying与 NSMutableCopying协议。 
    具体步骤: 
    需声明该类遵从 NSCopying 协议 
    实现 NSCopying 协议。该协议只有一个方法: 
    - (id)copyWithZone:(NSZone *)zone; 
    注意:一提到让自己的类用 copy 修饰符,我们总是想覆写copy方法,其实真正需要实现的却是 “copyWithZone” 方法。 
    至于如何重写带 copy 关键字的 setter这个问题, 
    如果抛开本例来回答的话,如下:

    - (void)setName:(NSString *)name {
        //[_name release];
        _name = [name copy];
    }
    • 1
    • 2
    • 3
    • 4

    参考: 
    *https://dayon.gitbooks.io/-ios/content/chapter5.html

    8、可变集合类 和 不可变集合类的 copy 和 mutablecopy有什么区别?如果是集合是内容复制的话,集合里面的元素也是内容复制么?

    使用copy时 可变集合的指针地址以及内存地址都不相同 深复制 不可变集合的指针地址不一样但是内存地址一样 属于浅复制 
    使用mutableCopy的时候无论是可变集合还是不可变集合的指针地址和内存地址都不同 都属于深复制

    - (void)testCopy {
        NSMutableArray *mutableArray = [NSMutableArray arrayWithObject:@"mutableArray"];
        NSArray *array = [NSArray arrayWithObject:@"array"];
        id copy_mutableArray = mutableArray.copy;
        id copy_array = array.copy;
        id mutableCopy_mutableArray = mutableArray.mutableCopy;
        id mutableCopy_array = array.mutableCopy;
        NSLog(@"mutableArray:%@ ,内存地址%p -- 指针地址%p",mutableArray,mutableArray,&mutableArray);
        NSLog(@"array:%@ ,内存地址%p -- 指针地址%p",array,array,&array);
        NSLog(@"copy_mutableArray:%@ ,内存地址%p -- 指针地址%p",copy_mutableArray,copy_mutableArray,&copy_mutableArray);
        NSLog(@"copy_array:%@ ,内存地址%p -- 指针地址%p",copy_array,copy_array,&copy_array);
        NSLog(@"mutableCopy_mutableArray:%@ ,内存地址%p -- 指针地址%p",mutableCopy_mutableArray,mutableCopy_mutableArray,&mutableCopy_mutableArray);
        NSLog(@"mutableCopy_array:%@ ,内存地址%p -- 指针地址%p",mutableCopy_array,mutableCopy_array,&mutableCopy_array);
    
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    打印输出:

    2018-02-28 08:12:02.322754+0800 XWBlogsDemos[6646:275862] mutableArray:(
        mutableArray
    ) ,内存地址0x60400025ec90 -- 指针地址0x7ffee2eb0b48
    2018-02-28 08:12:02.322913+0800 XWBlogsDemos[6646:275862] array:(
        array
    ) ,内存地址0x604000019010 -- 指针地址0x7ffee2eb0b40
    2018-02-28 08:12:02.323038+0800 XWBlogsDemos[6646:275862] copy_mutableArray:(
        mutableArray
    ) ,内存地址0x604000019090 -- 指针地址0x7ffee2eb0b38
    2018-02-28 08:12:02.323140+0800 XWBlogsDemos[6646:275862] copy_array:(
        array
    ) ,内存地址0x604000019010 -- 指针地址0x7ffee2eb0b30
    2018-02-28 08:12:02.323236+0800 XWBlogsDemos[6646:275862] mutableCopy_mutableArray:(
        mutableArray
    ) ,内存地址0x60400025ef90 -- 指针地址0x7ffee2eb0b28
    2018-02-28 08:12:02.323333+0800 XWBlogsDemos[6646:275862] mutableCopy_array:(
        array
    ) ,内存地址0x60400025ee70 -- 指针地址0x7ffee2eb0b20
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    9、为什么IBOutlet修饰的UIView也适用weak关键字?

    在xib或者Sb拖控件时,其实控件就加载到了父控件的subviews数组里面,进行了强引用,使用weak,避免循环引用

    10、nonatomic和atomic的区别?atomic是绝对的线程安全么?为什么?如果不是,那应该如何实现?

    nonatomic:表示非原子,不安全,但是效率高。 
    atomic:表示原子行,安全,但是效率定。 
    atomic,不能绝对保证线程的安全,当多线程同时访问的时候,会造成线程不安全。可以使用线程锁来保证线程的安全。

    11、UICollectionView自定义layout如何实现?

    实现一个自定义layout的常规做法是继承UICollectionViewLayout类,然后重载下列方法:

    -(CGSize)collectionViewContentSize
    返回collectionView的内容的尺寸
    -(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
    返回rect中的所有的元素的布局属性
    返回的是包含UICollectionViewLayoutAttributes的NSArray
    UICollectionViewLayoutAttributes可以是cell,追加视图或装饰视    图的信息,通过不同的UICollectionViewLayoutAttributes初始化方法可以得到不同类型的UICollectionViewLayoutAttributes:
       layoutAttributesForCellWithIndexPath:
       layoutAttributesForSupplementaryViewOfKind:withIndexPath:
    layoutAttributesForDecorationViewOfKind:withIndexPath:
      -(UICollectionViewLayoutAttributes )layoutAttributesForItemAtIndexPath:(NSIndexPath )indexPath
    返回对应于indexPath的位置的cell的布局属性
    -(UICollectionViewLayoutAttributes )layoutAttributesForSupplementaryViewOfKind:(NSString )kind atIndexPath:(NSIndexPath *)indexPath
    返回对应于indexPath的位置的追加视图的布局属性,如果没有追加视图可不重载
    -(UICollectionViewLayoutAttributes * )layoutAttributesForDecorationViewOfKind:(NSString)decorationViewKind atIndexPath:(NSIndexPath )indexPath
    返回对应于indexPath的位置的装饰视图的布局属性,如果没有装饰视图可不重载
    -(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
    当边界发生改变时,是否应该刷新布局。如果YES则在边界变化(一般是scroll到其他地方)时,将重新计算需要的布局信息。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    12、用StoryBoard开发界面有什么弊端?如何避免?

    使用简单逻辑页面的跳转是可以使用sb的,开发比较块。 
    但是SB对于逻辑项目比较复杂的时候,开发起来比较慢。不适合多人合作开发;也不利于版本的梗系和后期的维护。使用sb在项目变异编译的时候,也都会直接加载到内存中,造成内存的浪费。 
    可以使用xib来代替,编辑复杂逻辑界面时候可以使用纯码编写。

    13、进程和线程的区别?同步异步的区别?并行和并发的区别?

    进程:是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位. 
    线程:是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源. 
    同步:阻塞当前线程操作,不能开辟线程。 
    异步:不阻碍线程继续操作,可以开辟线程来执行任务。 
    并发:当有多个线程在操作时,如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程,它只能把CPU运行时间划分成若干个时间段,再将时间 段分配给各个线程执行,在一个时间段的线程代码运行时,其它线程处于挂起状。.这种方式我们称之为并发(Concurrent)。 
    并行:当系统有一个以上CPU时,则线程的操作有可能非并发。当一个CPU执行一个线程时,另一个CPU可以执行另一个线程,两个线程互不抢占CPU资源,可以同时进行,这种方式我们称之为并行(Parallel)。 
    区别:并发和并行是即相似又有区别的两个概念,并行是指两个或者多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间间隔内发生。在多道程序环境下,并发性是指在一段时间内宏观上有多个程序在同时运行,但在单处理机系统中,每一时刻却仅能有一道程序执行,故微观上这些程序只能是分时地交替执行。倘若在计算机系统中有多个处理机,则这些可以并发执行的程序便可被分配到多个处理机上,实现并行执行,即利用每个处理机来处理一个可并发执行的程序,这样,多个程序便可以同时执行。

    14、线程间通信?

    当使用dispath-async函数开辟线程执行任务的完成时,我们需要使用dispatch_async(dispatch_get_main_queue(), ^{ });函数会到主线程内刷新UI。并完成通信

    15、GCD的一些常用的函数?(group,barrier,信号量,线程同步)

    >

    group:

    我们使用队列组来开辟线程时,队列组中的队列任务是并发,当所有的队列组中的所有任务完成时候,才可以调用队列组完成任务。

    /**创建自己的队列*/
    dispatch_queue_t dispatchQueue = dispatch_queue_create("ted.queue.next", DISPATCH_QUEUE_CONCURRENT);
    /**创建一个队列组*/
    dispatch_group_t dispatchGroup = dispatch_group_create();
    /**将队列任务添加到队列组中*/
    dispatch_group_async(dispatchGroup, dispatchQueue, ^(){
        NSLog(@"dispatch-1");
    });
       /**将队列任务添加到队列组中*/
    dispatch_group_async(dispatchGroup, dispatchQueue, ^(){
        NSLog(@"dspatch-2");
    });
      /**队列组完成调用函数*/
    dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^(){
        NSLog(@"end");
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    >

    barrier:

    表示栅栏,当在并发队列里面使用栅栏时候,栅栏之前的并发任务开始并发执行,执行完毕后,执行栅栏内的任务,等栅栏任务执行完毕后,再并发执行栅栏后的任务。

    dispatch_queue_t concurrentQueue = dispatch_queue_create("my.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(concurrentQueue, ^(){
        NSLog(@"dispatch-1");
    });
    dispatch_async(concurrentQueue, ^(){
        NSLog(@"dispatch-2");
    });
    dispatch_barrier_async(concurrentQueue, ^(){
        NSLog(@"dispatch-barrier"); 
    });
    dispatch_async(concurrentQueue, ^(){
        NSLog(@"dispatch-3");
    });
    dispatch_async(concurrentQueue, ^(){
        NSLog(@"dispatch-4");
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    >

    信号量:

    Semaphore是通过‘计数’的方式来标识线程是否是等待或继续执行的。信号量

    dispatch_semaphore_create(int) // 创建一个信号,并初始化信号的计数大小
    /* 等待信号,并且判断信号量,如果信号量计数大于等于你创建时候的信号量的计数,就可以通过,继续执行,并且将你传入的信号计数减1,
     * 如果传入的信号计数小于你创建的计数,就表示等待,等待信号计数的变化
     *  如果等待的时间超过你传入的时间,也会继续下面操作
     *   第一个参数:semaphore 表示信号量
     *   第二个参数:表示等待的时间
     *    返回int 如果传入的信号计数大于等于你创建信号的计数时候,返回0.  反之,返回的不等于0
     */
     int result = dispatch_semaphore_wait(dispatch_semaphore_t  semaphore,time outTime);// 表示等待,也是阻碍线程  
    // 表示将信号技术+1
    dispatch_semaphore_signl(dispatch_semaphore_t semaphore);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    
    - (void)semaphoreDemo1 {
        dispatch_semaphore_t semaphore = dispatch_semaphore_create(10);
        for (int i = 0; i < 100; i++) {
             由于是异步执行的,所以每次循环Block里面的dispatch_semaphore_signal根本还没有执行就会执行dispatch_semaphore_wait,从而semaphore-1.当循环10此后,semaphore等于0,则会阻塞线程,直到执行了Block的dispatch_semaphore_signal 才会继续执行
            NSLog(@"i %zd",i);
            /// 执行十次之后阻塞当前线程
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        }
    }
    
    - (void)semaphoreDemo2 {
        dispatch_semaphore_t goOnSemaphore = dispatch_semaphore_create(0);
        NSLog(@"ready");
        [self network:^(id result) {
            NSLog(@"net return:%@",result);
            dispatch_semaphore_signal(goOnSemaphore);
        }];
        dispatch_semaphore_wait(goOnSemaphore, DISPATCH_TIME_FOREVER);
        NSLog(@"go on");
    }
    - (void)network:(void(^)(id result))block {
        sleep(2.0);
        block(@(arc4random_uniform(2)));
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    实现线程的同步的方法:

    串行队列,分组,信号量。也是可以使用并发队列。

    //加入队列
    dispatch_async(concurrentQueue, ^{
        //1.先去网上下载图片
        dispatch_sync(concurrentQueue, ^{
    
        });
        //2.在主线程展示到界面里
        dispatch_sync(dispatch_get_main_queue(), ^{
    
        });
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    16、如何使用队列来避免资源抢夺?

    使用线程锁。也是可以使用串行队列来完成。如:fmdb就是使用FMDatabaseQueue,来解决多线程抢夺资源。

    17、数据持久化的几个方案(fmdb用没用过)

    持久化方案: 
    plist,存储字典,数组比较好用 
    preference:偏好设置,实质也是plist 
    NSKeyedArchiver:归档,可以存储对象 
    sqlite:数据库,经常使用第三方来操作,也就是fmdb 
    coreData:也是数据库储存,苹果官方的

    18、说一下AppDelegate的几个方法?从后台到前台调用了哪些方法?第一次启动调用了哪些方法?从前台到后台调用了哪些方法?

    启动流程图

    19、NSCache优于NSDictionary的几点?

    1.nscache 是可以自动释放内存的。 
    2.nscache是线程安全的,我们可以在不同的线程中添加,删除和查询缓存中的对象。 
    3.一个缓存对象不会拷贝key对象。

    20、知不知道Designated Initializer?使用它的时候有什么需要注意的问题?

    初始化器. 创建子类时需要调用父类的的初始化器,并且需要重写父类的Designated Initializer,将其指向子类新的初始化器

    //Designated Initializer
    - (instancetype)initWithFrame:(CGRect)frame andName:(NSString *)name{
        //incorrect
        if (self = [super initWithFrame:frame]){
            self.name=name;
        }
        return self;
    }    
    //super override
    - (id)initWithFrame:(CGRect)frame
    {
        return [self initWithFrame:frame andName:@""];
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    参考: 
    https://www.jianshu.com/p/57db46f013d7 
    http://www.cnblogs.com/smileEvday/p/designated_initializer.html

    21、实现description方法能取到什么效果?

    description是nsobject的一个实例的方法,返回的是一个nsstring。当我们使用nslog打印的时候,打印出来的一般都是对象的内存地址,如果我们实现description方法时,我们就可以使用nslog打印对象的时候,我们可以把它里面的属性值和内存地址一起打印出来.打印什么,就是看你写什么了。

    22、objc使用什么机制管理对象内存?

    引用计数. 当内存管理计数器为0的时候,对象会被释放

    中级Block

    1、block的实质是什么?一共有几种block?都是什么情况下生成的?

    >

    block的实质是什么?

    Block实质上就是Objective-C对象;

    一共有几种block?

    block一共有3种类型的block

    _NSConcreteGlobalBlock 全局静态 
    _NSConcreteStackBlock 保存在栈中,出函数作用域就销毁 
    _NSConcreteMallocBlock 保存在堆中,retainCount == 0销毁而ARC和MRC中,还略有不同;

    参考: 
    https://www.jianshu.com/p/bb163c433f7c 
    https://www.jianshu.com/p/dfdb1b379ea2

    2、为什么在默认情况下无法修改被block捕获的变量? __block都做了什么?

    Block只捕获Block中会用到的变量。由于只捕获了自动变量(自动变量是以值传递方式传递到Block的构造函数里面)的值,并非内存地址,所以Block内部不能改变自动变量的值。Block捕获的外部变量可以改变值的是静态变量,静态全局变量,全局变量

    参考: 
    *https://halfrost.com/ios_block/?utm_source=tuicool&utm_medium=referral

    3、模拟一下循环引用的一个情况?blok实现界面反向传值如何实现?

    >

    模拟一下循环引用的一个情况?
    #import "ViewController.h"
    #import "Student.h"
    
    @interface ViewController ()
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        Student *student = [[Student alloc]init];
        student.name = @"Hello World";
    
        student.study = ^{
            NSLog(@"my name is = %@",student.name);
        };
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    循环引用问题集合

    blok实现界面反向传值如何实现?

    1,定义一个block属性 2,一级界面实现block需要执行的操作 3,在需要回调的时候调用block

    参考 
    *http://blog.csdn.net/x32sky/article/details/73826662

    Runtime

    1、objc在向一个对象发送消息时,发生了什么?

    objc是动态语言,每个方法在运行时会被动态转为消息发送,即:objc_msgSend(receiver, selector)。 
    根据对象的isa指针找到类对象id,在查询类对象里面的methodLists方法函数列表,如果没有找到,在沿着superClass,寻找父类,再在父类methodLists方法列表里面查询,最终找到SEL,根据id和SEL确认IMP(指针函数),在发送消息;

    2、什么时候会报unrecognized selector错误?iOS有哪些机制来避免走到这一步?

    简单来说:

    当调用该对象上某个方法,而该对象上没有实现这个方法的时候, 可以通过“消息转发”进行解决。

    简单的流程如下,在上一题中也提到过:

    objc是动态语言,每个方法在运行时会被动态转为消息发送,即:objc_msgSend(receiver, selector)。

    objc在向一个对象发送消息时,runtime库会根据对象的isa指针找到该对象实际所属的类,然后在该类中的方法列表以及其父类方法列表中寻找方法运行,如果,在最顶层的父类中依然找不到相应的方法时,程序在运行时会挂掉并抛出异常unrecognized selector sent to XXX 。但是在这之前,objc的运行时会给出三次拯救程序崩溃的机会:

    1. Method resolution

    objc运行时会调用+resolveInstanceMethod:或者 +resolveClassMethod:,让你有机会提供一个函数实现。如果你添加了函数,那运行时系统就会重新启动一次消息发送的过程,否则 ,运行时就会移到下一步,消息转发(Message Forwarding)。

    2. Fast forwarding

    如果目标对象实现了-forwardingTargetForSelector:,Runtime 这时就会调用这个方法,给你把这个消息转发给其他对象的机会。 只要这个方法返回的不是nil和self,整个消息发送的过程就会被重启,当然发送的对象会变成你返回的那个对象。否则,就会继续Normal Fowarding。 这里叫Fast,只是为了区别下一步的转发机制。因为这一步不会创建任何新的对象,但下一步转发会创建一个NSInvocation对象,所以相对更快点。

    3. Normal forwarding

    这一步是Runtime最后一次给你挽救的机会。首先它会发送-methodSignatureForSelector:消息获得函数的参数和返回值类型。如果-methodSignatureForSelector:返回nil,Runtime则会发出-doesNotRecognizeSelector:消息,程序这时也就挂掉了。如果返回了一个函数签名,Runtime就会创建一个NSInvocation对象并发送-forwardInvocation:消息给目标对象。

    
    #import "XWTest.h"
    #import <objc/runtime.h>
    
    @interface XWTest2 : NSObject
    - (void)unrecognized;
    @end
    @implementation XWTest2
    - (void)unrecognized {
        NSLog(@"unrecognized");
    }
    @end
    
    @implementation XWTest
    void myMethod(id self, SEL _cmd) {
        NSLog(@"myMethod 被调用!");
    }
    /// 第一次
    + (BOOL)resolveInstanceMethod:(SEL)sel {
        NSLog(@" %s",__func__);
        if ([NSStringFromSelector(sel) isEqualToString:@"unrecognized"]) {
            class_addMethod([self class], sel, (IMP)myMethod,"v@:");
            return YES;
        }
        return [super resolveInstanceMethod:sel];
    }
    
    /// 第二次
    -(id)forwardingTargetForSelector:(SEL)aSelector {
        NSString *selectorName = NSStringFromSelector(aSelector);
        if ([selectorName isEqualToString:@"unrecognized"]) {
            XWTest2 *myobject = [[XWTest2 alloc] init];
            return myobject;
        }
        return [super forwardingTargetForSelector:aSelector];
    }
    
    /// 第三次
    -(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
        NSMethodSignature *signature = [super methodSignatureForSelector:aSelector];
        if (!signature) {
            if([XWTest2 instancesRespondToSelector:aSelector])
            {
                signature = [XWTest2 instanceMethodSignatureForSelector:aSelector];
            }
        }
        return signature;
    }
    
    -(void)forwardInvocation:(NSInvocation *)anInvocation
    {
        if ([XWTest2 instancesRespondToSelector:anInvocation.selector]) {
            [anInvocation invokeWithTarget:[[XWTest2 alloc] init]];
        }
    }
    
    @end
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    参考: 
    https://www.jianshu.com/p/1c8f708653c0

    3、能否向编译后得到的类中增加实例变量?能否向运行时创建的类中添加实例变量?为什么?

    不能向编译后得到的类中增加实例变量; 
    能向运行时创建的类中添加实例变量; 
    解释下: 
    因为编译后的类已经注册在 runtime 中,类结构体中的 objc_ivar_list 实例变量的链表 和 instance_size 实例变量的内存大小已经确定,同时runtime 会调用 class_setIvarLayout 或 class_setWeakIvarLayout 来处理 strong weak 引用。所以不能向存在的类中添加实例变量; 
    运行时创建的类是可以添加实例变量,调用 class_addIvar 函数。但是得在调用 objc_allocateClassPair 之后,objc_registerClassPair 之前,原因同上。

    4、runtime如何实现weak变量的自动置nil?

    runtime 对注册的类, 会进行布局,对于 weak 对象会放入一个 hash 表中。 用 weak 指向的对象内存地址作为 key,当此对象的引用计数为0的时候会 dealloc, 在这个 weak 表中搜索,找到所有以a为键的 weak 对象,从而设置为 nil。 
    weak 修饰的指针默认值是 nil (在Objective-C中向nil发送消息是安全的)

    5、给类添加一个属性后,在类结构体里哪些元素会发生变化?

    instance_size :实例的内存大小 
    objc_ivar_list *ivars:属性列表

    RunLoop

    1.runloop是来做什么的?runloop和线程有什么关系?主线程默认开启了runloop么?子线程呢?

    runloop:字面意思就是跑圈,其实也就是一个循环跑圈,用来处理线程里面的事件和消息。 
    runloop和线程的关系:每个线程如果想继续运行,不被释放,就必须有一个runloop来不停的跑圈,以来处理线程里面的各个事件和消息。 
    主线程默认是开启一个runloop。也就是这个runloop才能保证我们程序正常的运行。子线程是默认没有开始runloop的

    2.runloop的mode是用来做什么的?有几种mode?

    model:是runloop里面的模式,不同的模式下的runloop处理的事件和消息有一定的差别。 
    系统默认注册了5个Mode: 
    (1)kCFRunLoopDefaultMode: App的默认 Mode,通常主线程是在这个 Mode 下运行的。 
    (2)UITrackingRunLoopMode: 界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响。 
    (3)UIInitializationRunLoopMode: 在刚启动 App 时第进入的第一个 Mode,启动完成后就不再使用。 
    (4)GSEventReceiveRunLoopMode: 接受系统事件的内部 Mode,通常用不到。 
    (5)kCFRunLoopCommonModes: 这是一个占位的 Mode,没有实际作用。 
    注意iOS 对以上5中model进行了封装 
    NSDefaultRunLoopMode; 
    NSRunLoopCommonModes

    3.为什么把NSTimer对象以NSDefaultRunLoopMode(kCFRunLoopDefaultMode)添加到主运行循环以后,滑动scrollview的时候NSTimer却不动了?

    nstime对象是在 NSDefaultRunLoopMode下面调用消息的,但是当我们滑动scrollview的时候,NSDefaultRunLoopMode模式就自动切换到UITrackingRunLoopMode模式下面,却不可以继续响应nstime发送的消息。所以如果想在滑动scrollview的情况下面还调用nstime的消息,我们可以把nsrunloop的模式更改为NSRunLoopCommonModes

    4.苹果是如何实现Autorelease Pool的?

    Autorelease Pool作用:缓存池,可以避免我们经常写relase的一种方式。其实就是延迟release,将创建的对象,添加到最近的autoreleasePool中,等到autoreleasePool作用域结束的时候,会将里面所有的对象的引用计数器-1. 
    autorelease

    参考: 
    https://www.jianshu.com/p/74bb8e1f7036

    类结构

    1、isa指针?(对象的isa,类对象的isa,元类的isa都要说)

    对象的isa指针指向所属的类 
    类的isa指针指向了所属的元类 
    元类的isa指向了根元类,根元类指向了自己。

    实例、类对象、元类关系

    参考: 
    *http://www.zhimengzhe.com/IOSkaifa/253119.html

    2、类方法和实例方法有什么区别?

    调用的方式不同,类方法必须使用类调用,在方法里面不能调用属性,类方法里面也必须调用类方法。存储在元类结构体里面的methodLists里面 
    实例方法必须使用实例对象调用,可以在实例方法里面使用属性,实例方法也必须调用实例方法。存储在类结构体里面的methodLists里面

    参考: 
    http://blog.csdn.net/youshaoduo/article/details/55253041

    3、介绍一下分类,能用分类做什么?内部是如何实现的?它为什么会覆盖掉原来的方法?

    类别(Category)主要有3个作用: 
    将类的实现分散到多个不同文件或多个不同框架中。 
    创建对私有方法的前向引用。 
    向对象添加非正式协议。 
    声明:@interface 类名(分类名称) @end 
    实现:@implementation 类名(分类名称) @end 
    注意: 
    (1)在分类只能增加方法,不能增加成员变量,如果要增加成员变量的话该考虑用继承去实现 
    (2)在分类实现方法中可以访问类中的成员变量但是不能访问类中的属性@property 
    (3)在分类中可以重新实现原类中的方法,但会将原类中的方法覆盖而失效。 
    (4)如果一个类有多个分类,而且分类中有同名的方法那么最后编译的分类会将前面编译的分类覆盖而执行输出

    因为在执行对象成员方法的时候会优先去分类中查找,然后再去原类中去查找,最后去父类中去查找

    // 另外一份解释来自《招聘一个靠谱的 iOS》—参考答案(上)---24
    // 类方法:
       - 类方法是属于类对象的
       - 类方法只能通过类对象调用
       - 类方法中的self是类对象
       - 类方法可以调用其他的类方法
       - 类方法中不能访问成员变量
       - 类方法中不能直接调用对象方法
    
    //  实例方法:
       -  实例方法是属于实例对象的
       -  实例方法只能通过实例对象调用
       -  实例方法中的self是实例对象
       -  实例方法中可以访问成员变量
       -  实例方法中直接调用实例方法
       -  实例方法中也可以调用类方法(通过类名)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    参考: 
    https://tech.meituan.com/DiveIntoCategory.html

    4、运行时能增加成员变量么?能增加属性么?如果能,如何增加?如果不能,为什么?

    Category中不能动态添加成员变量; 
    在Objective-C提供的runtime函数中,确实有一个class_addIvar()函数用于给类添加成员变量,但是阅读过苹果的官方文档的人应该会看到: 
    This function may only be called after objc_allocateClassPair and before objc_registerClassPair. Adding an instance variable to an existing class is not supported. 
    大概的意思说,这个函数只能在“构建一个类的过程中”调用。一旦完成类定义,就不能再添加成员变量了。经过编译的类在程序启动后就被runtime加载,没有机会调用addIvar。程序在运行时动态构建的类需要在调用objc_registerClassPair之后才可以被使用,同样没有机会再添加成员变量。 
    因为方法和属性并不“属于”类实例,而成员变量“属于”类实例。我们所说的“类实例”概念,指的是一块内存区域,包含了isa指针和所有的成员变量。所以假如允许动态修改类成员变量布局,已经创建出的类实例就不符合类定义了,变成了无效对象。但方法定义是在objc_class中管理的,不管如何增删类方法,都不影响类实例的内存布局,已经创建出的类实例仍然可正常使用。 
    然而如果在运行时动态生成一个类,就可以为其添加成员变量和方法, 如下图所示: 
    添加的方法必须是已经实现的,所以先手写这个方法

    5、objc中向一个nil对象发送消息将会发生什么?(返回值是对象,是标量,结构体)

    objc中向一个nil对象发送消息将会发生什么?

    参考: 
    http://blog.csdn.net/x32sky/article/details/73826662 
    https://www.jianshu.com/p/19f280afcb24

    高级

    1、UITableview的优化方法(缓存高度,异步绘制,减少层级,hide,避免离屏渲染)

    缓存高度:当我们创建frame模型的时候,计算出来cell的高度的时候,我们可以将cell的高度缓存到字典里面,以cell的indexpath和Identifier作为为key。

    NSString *key = [[HeightCache shareHeightCache] makeKeyWithIdentifier:@"YwywProductGradeCell" indexPath:indexPath];
    if ([[HeightCache shareHeightCache] existInCacheByKey:key]) {
        return [[HeightCache shareHeightCache] heightFromCacheWithKey:key];
    }else{
        YwywProductGradeModelFrame *modelFrame = self.gradeArray[indexPath.row];
        [[HeightCache shareHeightCache] cacheHieght:modelFrame.cellHight key:key];
        return modelFrame.cellHight;
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    参考: 
    https://www.jianshu.com/p/93085c0de4c9

    2、有没有用过运行时,用它都能做什么?(交换方法,创建类,给新创建的类增加方法,改变isa指针)

    >

    交换方式:一般写在类的+(void)load方法里面
        Method originalM = class_getInstanceMethod([self class], @selector(originMethod));
        Method exchangeM = class_getInstanceMethod([self class], @selector(exChangeMethod));
        method_exchangeImplementations(originalM, exchangeM); 
    • 1
    • 2
    • 3

    >

    创建类:
    /// 创建类
    - (void)creatClassMethod {
    
        Class Person = objc_allocateClassPair([NSObject class], "Person", 0);
        //添加属性
        objc_property_attribute_t type = { "T", "@\"NSString\"" };
        objc_property_attribute_t ownership = { "C", "" }; // C = copy
        objc_property_attribute_t backingivar  = { "V", "_privateName" };
        objc_property_attribute_t attrs[] = { type, ownership, backingivar };
        class_addProperty(Person, "name", attrs, 3);
        //添加方法
        class_addMethod(Person, @selector(name), (IMP)nameGetter, "@@:");
        class_addMethod(Person, @selector(setName:), (IMP)nameSetter, "v@:@");
        //注册该类
        objc_registerClassPair(Person);
    
        //获取实例
        id instance = [[Person alloc] init];
        NSLog(@"%@", instance);
        [instance setName:@"hxn"];
        NSLog(@"%@", [instance name]);
    }
    //get方法
    NSString *nameGetter(id self, SEL _cmd) {
        Ivar ivar = class_getInstanceVariable([self class], "_privateName");
        return object_getIvar(self, ivar);
    }
    //set方法
    void nameSetter(id self, SEL _cmd, NSString *newName) {
        Ivar ivar = class_getInstanceVariable([self class], "_privateName");
        id oldName = object_getIvar(self, ivar);
        if (oldName != newName) object_setIvar(self, ivar, [newName copy]);
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    >

    添加方法
    /**参数一、类名参数
       二、SEL 添加的方法名字参数
        三、IMP指针 (IMP就是Implementation的缩写,它是指向一个方法实现的指针,每一个方法都有一个对应的IMP)
      参数四、其中types参数为"i@:@“,按顺序分别表示:具体类型可参照[官方文档](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html)i 返回值类型int,若是v则表示void@ 参数id(self): SEL(_cmd)@ id(str)
      V@:表示返回值是void 带有SEL参数 (An object (whether statically typed or typed id))
      */
    class_addMethod(Person, @selector(addMethodForMyClass:), (IMP)addMethodForMyClass, "V@:");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    >

    添加实例变量
    /**参数一、类名参数
      二、属性名称参数
      三、开辟字节长度参数
      四、对其方式参数
      五、参数类型 “@” 官方解释 An object (whether statically typed or typed id) (对象 静态类型或者id类型) 具体类型可参照[官方文档](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html)return: BOOL 是否添加成功
      */
    BOOL isSuccess = class_addIvar(Person, "name", sizeof(NSString *), 0, "@");
    isSuccess?NSLog(@"添加变量成功"):NSLog(@"添加变量失败");
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3、看过哪些第三方框架的源码?都是如何实现的?(如果没有,问一下多图下载的设计)

    iOS常用开源框架、技术博客、软件、插件等


    * SDWebImage *

    iOS之SDWebImage的实现原理

    * AFNetworking*

    AFNetworking到底做了什么?

    * MBProcessHUD*

    MBProcessHUD-分析、模仿与学习

    * Masonry *

    iOS自动布局框架-Masonry详解

    * MJRefresh*

    iOS 李明杰 MJRefresh源码解析

    * YYKit *

    第三方框架学习—YYKit

    * FMDB*

    iOS数据库第三方框架FMDB详细讲解

    详解 iOS 多图下载的缓存机制

    4、SDWebImage的缓存策略?

    sd加载一张图片的时候,会先在内存里面查找是否有这张图片,如果没有会根据图片的md5(url)后的名称去沙盒里面去寻找,是否有这张图片,如果没有会开辟线程去下载,下载完毕后加载到imageview上面,并md(url)为名称缓存到沙盒里面。 
    附:(代码解读) 
    SDWebImage缓存机制

    5、AFN为什么添加一条常驻线程?

    如果没有常住线程的话,就会每次请求网络就去开辟线程,完成之后销毁开辟线程,这样就造成资源的浪费,而开辟一条常驻线程,就可以避免这种浪费,我们可以在每次的网络请求都添加到这条线程。

    6、KVO的使用?实现原理?(为什么要创建子类来实现)

    iOS开发 – KVO的实现原理与具体应用 
    创建子类 
    每个对象都有isa 指针,指向该对象的类,它告诉 Runtime 系统这个对象的类是什么。所以对象注册为观察者时,isa指针指向新子类,那么这个被观察的对象就神奇地变成新子类的对象(或实例)了。

    7、KVC的使用?实现原理?(KVC拿到key以后,是如何赋值的?知不知道集合操作符,能不能访问私有属性,能不能直接访问_ivar)

    iOS开发技巧系列—详解KVC(我告诉你KVC的一切)

    项目

    1、有已经上线的项目么?

    2、项目里哪个部分是你完成的?(找一个亮点问一下如何实现的)

    3、开发过程中遇到过什么困难,是如何解决的?

    学习

    1、遇到一个问题完全不能理解的时候,是如何帮助自己理解的?举个例子?

    2、有看书的习惯么?最近看的一本是什么书?有什么心得?

    3、有没有使用一些笔记软件?会在多平台同步以及多渠道采集么?(如果没有,问一下是如何复习知识的)

    4、有没有使用清单类,日历类的软件?(如果没有,问一下是如何安排,计划任务的)

    5、平常看博客么?有没有自己写过?(如果写,有哪些收获?如果没有写,问一下不写的原因)

    6、有关技术类的问题可以在评论区留言,我重点说一下这轮面试的心得和体会。

    展开全文
  • iOS开发app打包

    2019-08-28 14:34:53
    1.申请苹果开发者账号 申请苹果开发者账号在APP store 里发布应用。 开发者账号分类:(1)个人开发者账号 (2)企业开发者账号 主要的区别是:点击这里 ...在电脑安装发布许可证,这样你的电脑才能发布程序。... ...
  • 我于2012年12月23日提交加入iOS开发者计划(即iOS Developer Program,简称IDP)的申请,至2012年12月28日申请成功,扣除星期天,一共仅用了5天时间,这超出了我的意料。在这里,我将我的申请过程记录下来,以供广大...
  • iOS开发者必备:五大编程类工具

    万次阅读 2018-03-28 16:51:24
    作为一个开发者应该学会去整理收集开发常用的...iOS开发工具多如牛毛,开发者在编写大段代码时,难免会出现结构或语法错误。所以选择一款功能强劲且实用的编程工具对开发者来说可谓是大有裨益。小编收录和整理了对...
  • iOS开发流程

    2020-06-07 19:47:14
    此流程适用给对iOS开发啥都不清楚的小白 iOS开发首先需要申请苹果开发者帐号, 来上线项目, 可供用户在app store下载, 开发者帐号费用为人民币688元每年, 以下为流程. 1.申请公司邓白氏编码 【申请链接】: ...
  • 本课程主要介绍了开发iOS app的一些基本情况。例如,需要的硬件和软件条件,如何申请开发者账号,XCode的常用功能介绍。后给出一个iOS App的案例来演示开发App的过程。
  • 从零练就iOS高手实战班

    万人学习 2018-10-22 21:38:03
    iOS课程教学从入门到实战,系统讲解Swift编程,精讲基础语法,详解iOS基础框架,知识点涵盖新潮实用的swift,AppleWatch App开发。 咨询QQ:2528047463 咨询群:462917576 付费学员答疑群:446896569
  • C语言基础1-2天。其中包括开发概述及简单语法。
  • C语言基础19-21天。其中包括property、继承多态、《购票系统》。
  • 小波说雨燕 第五季 Core Data实战

    万人学习 2019-06-26 11:52:34
    小波带你从新手角度,啃读原版英文ios8 +swift教材 课程素材免费下载
  • iOS8开发技术(Swift版):常用控件

    万人学习 2018-10-22 21:38:02
    本课程主要介绍了iOS中常用的控件的功能和使用方法。
  • C语言基础7-8天。知识点回顾、初识数组与排序。
  • C语言基础3-4天。其中包括运算符和判断语句。
  • 我是个Java开发者,熟悉的IDE工具有Eclipse和NetBeans, 现在想尝试iOS开发,想知道用Object C开发iOS程序,什么IDE工具最好用?
  • 小波说iOS8 智能视图 完整版

    万人学习 2019-06-24 11:58:27
    随着iOS8市占率达70%,开发知识已经大幅更新,如何跟上节奏,2015年是iOS开发者有挑战的一年。 小波说iOS8,为你加油助航!
1 2 3 4 5 ... 20
收藏数 407,605
精华内容 163,042
关键字:

ios开发