0. [代码]iOS判断是模拟器还是真机
#if TARGET_IPHONE_SIMULATOR//模拟器
#elseif TARGET_OS_IPHONE//真机
#endif
1、 什么情况使用weak
关键字,相比assign
有什么不同?
- 首先明白什么情况使用
weak
关键字?- 在ARC中,在有可能出现循环引用的时候,往往要通过让其中一端使用weak来解决,比如:delegate代理属性,代理属性也可使用assign
- 自身已经对它进行一次强引用,没有必要再强引用一次,此时也会使用weak,自定义IBOutlet控件属性一般也使用weak;当然,也可以使用strong,但是建议使用weak
- weak 和 assign的不同点
- weak策略在属性所指的对象遭到摧毁时,系统会将weak修饰的属性对象的指针指向nil,在OC给nil发消息是不会有什么问题的;如果使用assign策略在属性所指的对象遭到摧毁时,属性对象指针还指向原来的对象,由于对象已经被销毁,这时候就产生了
野指针
,如果这时候在给此对象发送消息,很容造成程序奔溃 - assigin 可以用于修饰非OC对象,而weak必须用于OC对象
- weak策略在属性所指的对象遭到摧毁时,系统会将weak修饰的属性对象的指针指向nil,在OC给nil发消息是不会有什么问题的;如果使用assign策略在属性所指的对象遭到摧毁时,属性对象指针还指向原来的对象,由于对象已经被销毁,这时候就产生了
2、 define 和 const常量有什么区别?
- define在预处理阶段进行替换,const常量在编译阶段使用
- 宏不做类型检查,仅仅进行替换,const常量有数据类型,会执行类型检查
- define不能调试,const常量可以调试
- define定义的常量在替换后运行过程中
会不断地占用内存
,而const定义的常量存储在数据段只有一份copy
,效率更高 -
define可以定义一些简单的函数,const不可以
3、UIScrollView的自动布局?
4、理清[self class]和[super class]?
下面的代码输出什么?
@implementation Son : Father
- (id)init
{
self = [super init];
if (self) {
NSLog(@"%@", NSStringFromClass([self class]));
NSLog(@"%@", NSStringFromClass([super class]));
}
return self;
}
@end
- 答案:都输出 Son
- 这个题目主要是考察关于objc中对 self 和 super 的理解:
- self 是类的隐藏参数,指向当前调用方法的这个类的实例。而 super 本质是一个
编译器标示符
,和 self 是指向的同一个消息接受者 - 当使用 self 调用方法时,会从
当前类
的方法列表中开始找,如果没有
,就从父类中再找
; - 而当使用 super时,则从父类的方法列表中开始找。然后调用父类的这个方法
-
调用[self class] 时,会转化成 objc_msgSend函
- self 是类的隐藏参数,指向当前调用方法的这个类的实例。而 super 本质是一个
5、理清Frame和Bounds的关系
-
注意:(bounds正负参数参照数学坐标系,起作用相当于设置内边距(contentOffset)那样起作用)
6、Block的内存管理
- Block是对象。为什么?苹果官方文档注明(working with Block)
/*
Block作为变量用什么修饰:
ARC下:`copy`或者`Strong`
MRC:block只能使用`copy`,因为只有copy才会把block放在堆中
block如果没有访问外部变量,默认都是全局的.
ARC中默认一个局部变量对象都是强指针.
MRC中默认一个局部变量对象没有强弱之分,相当于基本数据类型.
2013之前:MRC
MRC:
block如果访问外部变量,就是栈中
block使用copy,才会堆中
ARC:
block如果访问外部变量,就是堆中
block使用copy,strong
*/
7、Block
- 1.Block的值传递和指针传递
- 2.以及在方法中作为作为参数
#import "ViewController.h"
// 定义block类型别名
typedef void(^BlockName)();
@interface ViewController ()
//@property (nonatomic ,strong) BlockName block;
// 声明变量名叫block的代码块
@property (nonatomic, strong) void(^block)();
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 1.保存代码,(保存每一行cell的操作)
// 1.如何声明Block属性,ARC:strong MRC:copy
// 2.传值
// 定义Block
void (^block)() = ^{
NSLog(@"调用block");
};
_block = block;
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
// 调用block.就是调用保存代码块
_block();
}
- 3.循环引用问题
#import "ModalViewController.h"
@interface ModalViewController ()
@property (nonatomic, strong) void(^block)();
@property(nonatomic, assign) int age; /**< 属性 */
@end
@implementation ModalViewController
- (void)viewDidLoad {
[super viewDidLoad];
// self.view.backgroundColor = [UIColor redColor];
NSString *str = @"123";
_age = 20;
// 定义: ^返回值(参数){};
// 注意:block循环引用
// block:会把外界所有强指针对象都强引用.
// 在block尽量少使用self,下划线
#pragram - 处理循环应用问题
// typeof:获取里面的类型
__weak typeof(self) weakSelf = self;
_block = ^{
typeof(self) strongSelf = weakSelf;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"%d",strongSelf.age);
});
};
_block();
// UIView里面的Block不存在循环引用问题
[UIView animateWithDuration:2 animations:^{
NSLog(@"%@",self.age);
}];
}
- Block传值
/*
block传值:逆传(下一个控制器传值给上一个控制器)
block代替代理
blocK传值步骤:
1.在需要传值的类(ModalViewController)中,定义Block属性
2.block声明:把需要传递的值作为Block参数
3.在需要接收值的类(ViewController)中,定义block
4.在需要传值的时候,就直接调用block
*/
8.UICollectionView的一些注意点
-
如何创建一个UICollectionView
-
UICollectionViewDataSource数据源方法
- 新的封装代码方式(新思维方式)
-
主要灵感是来源于逗号表达式
-
9.内存溢出/内存泄露 ---- 类别(category)/继承的区别?
1-内存溢出/内存泄露
-
内存溢出 out of memory
- 是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。
- 举个形象的例子吧:一个盘子用尽各种方法只能装4个果子,你装了5个,结果掉倒地上不能吃了。这就是溢出!
- 总结:就是分配的内存不足以放下数据项序列,称为内存溢出.
-
内存泄露 memory leak
- 是指程序在申请内存后,无法释放已申请的内存空间,结果你申请到的那块内存你自己也不能再访问,而系统也不能再次将它分配给需要的程序。一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。
2-类别(category)和继承的区别?
共同点:都是给一个类进行扩展
-
区别:
- 1.类别是对方法的扩展,不能添加成员变量。继承可以在原来父类的成员变量的基础上,添加新的成员变量
- 2.类别只能添加新的方法,不能修改和删除原来的方法。继承可以增加、修改和删除方法。
- 3.类别不提倡对原有的方法进行重载。继承可以通过使用super对原来方法进行重载。
- 4.类别可以被继承,如果一个父类中定义了类别,那么其子类中也会继承此类别。
10.图片模糊效果
- 1-可以用UIToolBar
- 2-可以用coreImage
上面两个我就不多说了
- 3-用UIVisualEffectView
-
操作效果图如下,可以自己去尝试试看
11如何反向转场(SWift)如图
-
注:是基于storyboard的基础上操作(不是纯代码)
- 补充:反向转场时当你需要传递参数的时候,那该何如传递参数到另一个控制器呢?答案是:利用segue拿到目标控制器,然后进行参数的赋值
- 只要执行了这些操作,你就可以dismiss掉控制器
12transform变化效果组合
- 开发中经常要利用transform做动画效果,但是如何使几个动画一起执行呢?之前的我感觉是蛋疼的,直到后来知道了这个函数
- transform变化效果组合需要用到一个函数:
CGAffinetransformConcat(transform1,transform2)
- 补充:Swift3.0写法(变化大,好坑)
- transform变化效果组合需要用到一个函数:
let scale = CGAffineTransform(scaleX: 1.3, y: 1.3)
let location = CGAffineTransform(translationX: 0, y: 20)
self.titleLabel.transform = scale.concatenating(location)
13导航栏问题
- 怎么把顶部这个navigationbar设置为透明呢,能够让下面的图片显示出来,但是返回按钮不透明?
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), forBarMetrics: UIBarMetrics.Default)
self.navigationController?.navigationBar.shadowImage = UIImage()
- 设置navigationBar的透明:
们需要将navigationBar设置透明,但不是隐藏,有很多种方法,这里只是提供一种简单的方法- 根据视图层级关系,设置navigationBar的透明
[[[self.navigationController.navigationBar subviews] objectAtIndex:0] setAlpha:0];
14二维码扫描闪光灯问题或相册选择二维码图片进行扫描
扫描二维码功能也许大家都会,这里就不一一诉说。但实际开发过程中扫描二维码肯定要复杂一些(比如需要添加打开闪光灯功能或相册选择二维码图片进行扫描或者扫描的时候绘制一个扫描边框),其实这个功能很容易实现
- 实现闪光灯功能代码:
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError *error;
if (device.hasTorch) { // 判断设备是否有闪光灯
BOOL b = [device lockForConfiguration:&error];
if (!b) {
if (error) {
NSLog(@"lock torch configuration error:%@", error.localizedDescription);
}
return;
}
device.torchMode =
(device.torchMode == AVCaptureTorchModeOff ? AVCaptureTorchModeOn : AVCaptureTorchModeOff);
[device unlockForConfiguration];
}
- 相册选择二维码图片进行扫描(Swift版,其实OC版也一样,有兴趣的可以自己去研究)
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
guard let image = info[UIImagePickerControllerOriginalImage] as? UIImage else{
print("没有获取到照片")
return
}
// 2.识别照片中的二维码的信息
getQRCodeInfo(image)
// 3.退出控制器
dismissViewControllerAnimated(true, completion: nil)
}
private func getQRCodeInfo(image:UIImage) {
// 1.创建扫描器
let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: nil)
// 2.扫描结果
guard let ciImage = CIImage(image: image) else {
print("转CIImage失败")
return
}
let features = detector.featuresInImage(ciImage)
// 3.遍历扫描结果
for f in features {
guard let feature = f as? CIQRCodeFeature else {
continue
}
print(feature.messageString)
}
}
- 扫描的时候绘制一个扫描边框(有兴趣的可以自己去研究,当然也可以找我一起研究)
15.计算缓存
16.Runtime运行时特性
17.MJRefresh框架的使用
18.键盘的变化(显示和隐藏)
补录:
打印日志输出(DEBUG是在编译器环境定义的宏)
19.全屏滑动功能
20返回参数的失败类型
21.横竖屏的控制
22tableview的移动
// tableview的移动
-(void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath{
//1.先获取要移动的数据
NSString *str = self.arr[sourceIndexPath.row];
//2.把数组里对应的字符串从数组中移除掉
[self.arr removeObjectAtIndex:sourceIndexPath.row];
[self.arr insertObject:str atIndex:destinationIndexPath.row];
}
// 听说这个可以设置编辑模式下的圈圈图片
if (cell.selected == YES && tableView.editing == YES) {
UIImageView *imageView = [[[cell.subviews lastObject]subviews]firstObject];
imageView.image = [UIImage imageNamed:@"chose_06"];
}
23.MVVM遵循的原则
-
MVC是苹果权威架构,而MVVM是MVC的升级。M就是Model,V就是View和Controller,VM就是ViewModel。
24.GBK解码(如果UTF-8解析出来的数据是null)
25.常见error代码说明--mob提供的短信验证码SDK( http://sms.mob.com )
/**
* @brief 错误代码,如果为调用API出错则应该参考API错误码对照表。错误码对照表如下:
"错误码" "错误描述" "备注"
400 无效请求 客户端请求不能被识别。
408 无效参数 无效的请求参数
456 手机号码为空 提交的手机号或者区号为空
457 手机号码格式错误 提交的手机号格式不正确(包括手机的区号)
458 手机号码在黑名单中 手机号码在发送很名单中
459 无appKey的控制数据 获取appKey控制发送短信的数据失败
460 无权限发送短信 没有打开客户端发送短信的开关
461 不支持该地区发送短信 没有开通当前地区发送短信的功能
462 每分钟发送次数超限 每分钟发送短息的次数超出限制
463 手机号码每天发送次数超限 手机号码每天发送短信的次数超出限制
464 每台手机每天发送次数超限 每台手机每天发送短信的次数超限
465 号码在App中每天发送短信的次数超限 手机号码在App中每天发送短信的数量超限
466 校验的验证码为空 提交的校验验证码为空
467 校验验证码请求频繁 5分钟内校验错误超过3次,验证码失效
468 需要校验的验证码错误 用户提交的验证码错误
470 账号余额不足 账号短信余额不足
472 客户端请求发送短信验证过于频繁 客户端请求发送短信验证过于频繁
475 appKey的应用信息不存在 appKey的应用信息不存在
500 服务器内部错误 服务器程序报错
*/
-
26如果要统计ios开发代码,包括头文件的,终端命令进入项目目录下,命令如下
cd 项目目录路径
find . -name "*.m" -or -name "*.h" -or -name "*.xib" -or -name "*.c" |xargs wc -l
列出每个文件的行数
find . -name "*.m" -or -name "*.h" -or -name "*.xib" -or -name "*.c" |xargs grep -v "^$"|wc -l
列出代码行数总和
grep -v "^$"是去掉空行
注释也统计在代码量之内,毕竟也一个字一个字码出来的
-
27退出当前运用
-
abort();
-
exit()或exit(0)
-
两者异同:
- exit和abort都是终止程序执行退出的处理函数。
- 其中exit是正常退出,abort是异常退出,退出时会输出错误信息,然后再调用exit退出。
- 退出当前运用参考网址
-
- 后续.......
- 待更新
补充:OC中一些常见的基本常识(个人总结)
-
1.问题:__weak与__block修饰符对于Block到底有什么区别?
- __block和__weak修饰符的区别其实是挺明显的:
- 1.__block不管是ARC还是MRC模式下都可以使用,可以修饰对象,还可以修饰基本数据类型。
- 2.__weak只能在ARC模式下使用,也只能修饰对象(NSString),不能修饰基本数据类型(int)。
- 3.__block对象可以在block中被重新赋值,__weak不可以。
- PS:__unsafe_unretained修饰符可以被视为iOS SDK 4.3以前版本的__weak的替代品,不过不会被自动置空为nil。所以尽可能不要使用这个修饰符。
- __block和__weak修饰符的区别其实是挺明显的:
-
2.问题:BOOL和bool的区别?
- 1、类型不同
BOOL为int型
bool为布尔型 - 2、长度不同
bool只有一个字节
BOOL长度视实际环境来定,一般可认为是4个字节 - 3、取值不同
bool取值false和true,是0和1的区别
BOOL取值FALSE和TRUE,是0和非0的区别
- 1、类型不同
-
3.问题:cocoa与cocoa Touch区别之分
- 相同之处:两者都包含OC运行时的两个核心框架
- cocoa包含Foundation和AppKit框架,可用于开发Mac OS X系统的应用程序
- cocoa touch包含Foundation和UIKit框架,可用于开发iPhone OS 系统的应用程序
- Cocoa时Mac OS X的开发环境,cocoa Touch是 Iphone OS的开发环境
-
4.问题:ios如何性能优化?
- 用ARC管理内存
- 在正确的地方使用 reuseIdentifier
- 3.尽量把views设置为透明
.............
详情请看:http://www.2cto.com/kf/201505/401059.html
-
5.问题:关于OC 优缺点有点疑问 ?
-
优点:
- 1 Category
非常实用的扩展机制,可以很方便的为一个已有的类添加属性或者方法,而不需要笨拙的去继承他。 - 2 posing
可以让一个类的对象动态的以其他类行为去执行,也许可以理解成动态replace所有的method(不确定是否可以这么理解) - 3 动态识别
比较常见的动态语言的特性,涉及的点就多了,举个简单的例子,判断一个对象是否是某个类的成员。isKindOfClass: - 4 指标计算
真不知道是什么,查了下台湾人民把指针称为指标。。。。。。。。也许是说指针计算?那就不难理解了吧 - 5 弹性讯息传递
应该确定是湾湾人民写的了,应该就是指方法(method)的动态处理,譬如当你调用一个没有的方法的时候,系统将是再运行时跑出异常而不是编译时给出错误。
- 1 Category
-
缺点1
- 命名空间
写过c#等其他语言的应该比较清楚,可以通过命名空间将相同名字的类进行分类,而objc中不得不通过前缀进行区分,这也是为什么苹果的类库都有UIXXX NSXXX等统一前缀了。然而Swift已经去除这种前缀的命名。
- 命名空间
- 不支持运算符重载
- 3)不支持多重继承
- 4)使用动态运行时类型,所有的方法都是函数调用,所以很多编译时优化方法都用不到。(如内联函数等),性能低劣。
-
-
6.问题:关于nil,Nil和 null和NSNull的区别及相关问题?
解释:nil和null从字面意思来理解比较简单,nil是一个对象,而NULL是一个值,我的理解为nil是将对象设置为空,而null是将基本类型设置为空的。nil是一个对象指针为空,Nil是一个类指针为空,NULL是基本数据类型为空。这些可以理解为nil,Nil, NULL的区别吧。
nil:指向一个对象的空指针
Nil:指向一个类的空指针
NULL:指向其他类型(如:基本类型、C类型)的空指针
NSNull:通常表示集合中的空值 -
7.问题:Objective-C的内省(Introspection)用法小结
-
介绍:内省是对象揭示自己作为一个运行时对象的详细信息的一种能力。这些详细信息包括对象在继承树上的位置,对象是否遵循特定的协议,以及是否可以响应特定的消息等等。NSObject协议和类定义了很多内省方法,用于查询运行时信息,以便根据对象的特征进行识别。
-
1、isKindOfClass:Class
检查对象是否是那个类或者其继承类实例化的对象
-
2、isMemberOfClass:Class
检查对象是否是那个类但不包括继承类而实例化的对象
-
3、respondToSelector:selector
检查对象是否包含这个方法
-
4、conformsToProtocol:protocol
检查对象是否符合协议,是否实现了协议中所有的必选方法。
-
-
-
8.问题:iOS控制器的生命周期
-
9.问题:【object-c】iOS中有哪些回调机制,并作简单的比较。(问的就是代理、通知和Block)
- 1、目标动作对:当两个对象之间有比较紧密的关系时,如视图控制器与其下的某个视图。
- 2、代理:也叫委托,当某个对象收到多个事件,并要求同一个对象来处理所有事件时。委托机制依赖于某个协议定义的方法来发送消息。
- 3、通告机制:当需要多个对象或两个无关对象处理同一个事件时。
- 4、Block:适用于回调只发生一次的简单任务。
-
10.问题:UIButton与UITableView的层级结构
-
UIButton为:
UIButton > UIControl > UIView > UIResponder > NSObject
-
UITableView为:
UITableView > UIScrollView > UIView > UIResponder > NSObject
-
-
11.问题:手写代码UI,xib和StoryBoard间的的优劣
-
1、代码UI:
- 优点:代码UI可以说具有最好的代码重用性。缺点:但是代码手写UI的劣势同时也是最明显的,慢,代码量大。
-
2、Xibs:
- 优点:相对于代码,使用IB和xib文件来组织UI,可以省下大量代码和时间,从而得到更快的开发速度。缺点: 但是维护不方便。
-
3、StoryBoard:
- 优点:优点跟XIB一样。但它可视性更强,层级一目了然。缺点:多人合作开发,容易产生冲突。而且界面多逻辑复杂的时候SB界面看起来有点凌乱,层级关系看起来反而更加复杂。一般界面超过5个以上我都采用纯代码去创建控制器。
-
抉择:没有唯一的标准,看个人习惯,视具体情况具体分析,一般界面比较固定使用XIB或SB,其他界面使用纯代码,一些View可自定义XIb实现控件的复用。
-
github
项目 | 简介 |
---|---|
MGDS_Swif | 逗视视频直播 |
MGMiaoBo | 喵播视频直播 |
MGDYZB | 斗鱼视频直播 |
MGDemo | n多小功能合集 |
MGBaisi | 高度仿写百思 |
MGSinaWeibo | 高度仿写Sina |
MGLoveFreshBeen | 一款电商App |
MGWeChat | 小部分实现微信功能 |
MGTrasitionPractice | 自定义转场练习 |
DBFMDemo | 豆瓣电台 |
MGPlayer | 一个播放视频的Demo |
MGCollectionView | 环形图片排布以及花瓣形排布 |
MGPuBuLiuDemo | 瀑布流--商品展 |
MGSlideViewDemo | 一个简单点的侧滑效果,仿QQ侧滑 |
MyResume | 一个展示自己个人简历的Demo |
GoodBookDemo | 好书 |
-
2、逗视:逗你玩的直播App,可下载试玩
看下效果