零碎知识总结清单-1
1.一个完整单例的实现
参考苹果系统代码,单例往往通过一个share或者是default名字的类方法来创建。
+ (instancetype)shareInstance
{
Tools *instance = [[self alloc] init];
return instance;
}
保证类是一个单例(只有一份地址)的保证是在类里面定义一个静态变量来存储单例对象:static Tools *_instance = nil;
在我们创建一个对象的时候调用的方法是init,或者是copy。
所有的init(不管是init还是iniitwithFrame等其他自定义初始化方法)都会调用allocWithZone方法,所以我们可以在allocWithZone方法里面使用dispatch_once_t去控制这个变量的创建方法只会调用一次(只会创建一次):
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
// 以下代码在多线程中也能保证只执行一次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [[super allocWithZone:zone] init];
});
return _instance;
}
所有的copy(不管是mutableCopy还是copy)都会调用一个***copyWithZone方法,所以我们可以在copyWithZone方法里面之间返回静态变量属性去控制这个变量的创建方法只会调用一次(只会创建一次),但是值得注意的是,所有自己创建的类都需要遵循<NSCopying, NSMutableCopying>这两个协议:
- (id)copyWithZone:(NSZone *)zone{
//不用担心这一步变量会不会为空,因为只要你能复制,就说明你已经创建过这个变量了
return _instance;
}
- (id)mutableCopyWithZone:(NSZone *)zone
{
//不用担心这一步变量会不会为空,因为只要你能复制,就说明你已经创建过这个变量了
return _instance;
}
只要按照上面几个步骤,那么一个单例类就基本实现了,但是考虑到部分项目可能会是MRC环境,下面添加一段代码兼容:
- (oneway void)release
{
// 为保证整个程序过程中只有一份实例, \
在这个方法中什么都不做
}
- (instancetype)retain
{
return _instance;
}
- (NSUInteger)retainCount
{
// return 1;
// 注意: 为了方便程序员之前沟通, 参考苹果系统一般情况下不会在单例中返回retainCount = 1
// 而是返回一个比较大得值
return MAXFLOAT;
}
为了方便开发,下面共享一个单例宏定义的链接,方便大家去使用。
githubdemo地址
2.如何跳转到AppStore,并且展示自己的应用:
NSString *appid = @"725xxxxxx”;
NSString * nsStringToOpen = [NSString stringWithFormat: @"http://itunes.apple.com/gb/app/yi-dong-cai-bian/id%@?mt=8", appid];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:nsStringToOpen]];
3.退出键盘的两种方式
resignFirstResponder
当叫出键盘的那个控件(第一响应者)调用这个方法时,就能退出键盘
endEditing
只要调用这个方法的控件内部存在第一响应者,就能退出键盘
4.换个角度认识UILabel
UILable是iPhone界面最基本的控件,主要用来显示文本信息。
常用属性和方法有:
// 1、创建
CGRect rect =CGRectMake(100, 200, 50, 50);
UILabel *label =[[UILabel alloc] initWithFrame:rect];
// 2、text 设置和读取文本内容,默认为nil
label.text= @”文本信息”; 设置内容
NSLog(@”%@”,label.text); 读取内容
// 3、textColor 设置文字颜色,默认为黑色
lable.textColor =[UIColor redColor];
// 4、font 设置字体大小,默认17
label.font= [UIFont systemFontOfSize:20]; 一般方法
label.font= [UIFont boldSystemFontOfSize:20]; 加粗方法
label.font= [UIFont fontWithName:@"Arial"size:16]; 指定
// 字体的方法 还有⼀一种从外部导入字体的方法。
// 5、textAlignment 设置标签文本对齐方式。
label.textAlignment= NSTextAlignmentCenter; 还有
NSTextAlignmentLeft、NSTextAlignmentRight.
// 6、numberOfLines 标签最多显示行数,如果为0则表示多行。
label.numberOfLines =2;
// 7、enabled 只是决定了Label的绘制方式,将它设置为NO将会使文本变暗,表示它没有激活,这时向它设置颜色值是无效的。
label.enable =NO;
// 8、highlighted 是否高亮显示
label.highlighted =YES;
label.highlightedTextColor= [UIColor orangeColor]; 高亮
// 显示时的文本颜色
// 9、ShadowColor 设置阴影颜色
[labelsetShadowColor:[UIColor blackColor]];
// 10、ShadowOffset 设置阴影偏移量
[labelsetShadowOffset:CGSizeMake(-1, -1)];
// 11、baselineAdjustment 如果adjustsFontSizeToFitWidth属性设置为YES,这个属性就来控制文本基线的行为。
label.baselineAdjustment= UIBaselineAdjustmentNone;
UIBaselineAdjustmentAlignBaselines= 0,默认,文本最上端与中线对齐。
UIBaselineAdjustmentAlignCenters, 文本中线与label中线对齐。
UIBaselineAdjustmentNone,文本最低端与label中线对齐。
// 12、Autoshrink 是否自动收缩
// FixedFont Size 默认,如果Label宽度小于文字长度时时,文字大小不自动缩放
// minimumScaleFactor设置最小收缩比例,如果Label宽度小于文字长度时,文字进行收缩,收缩超过比例后,停止收缩。
// minimumFontSize设置最小收缩字号,如果Label宽度小于文字长度时,文字字号减小,低于设定字号后,不再减小。6.0以后不再使用了。
label.minimumScaleFactor= 0.5;
// 13、adjustsLetterSpacingToFitWidth 改变字母之间的间距来适应Label大小
myLabel.adjustsLetterSpacingToFitWidth= NO;
// 14、lineBreakMode 设置文字过长时的显示格式
label.lineBreakMode= NSLineBreakByCharWrapping;//以字符为显示单位显示,后面部分省略不显示。
label.lineBreakMode= NSLineBreakByClipping;//剪切与文本宽度相同的内容长度,后半部分被删除。
label.lineBreakMode= NSLineBreakByTruncatingHead;//前面部分文字以……方式省略,显示尾部文字内容。
label.lineBreakMode= NSLineBreakByTruncatingMiddle;//中间的内容以……方式省略,显示头尾的文字内容。
label.lineBreakMode= NSLineBreakByTruncatingTail;//结尾部分的内容以……方式省略,显示头的文字内容。
label.lineBreakMode= NSLineBreakByWordWrapping;//以单词为显示单位显示,后面部分省略不显示。
// 15、adjustsFontSizeToFitWidth 设置字体大小适应label宽度
label.adjustsFontSizeToFitWidth= YES;
// 16、attributedText:设置标签属性文本。
NSString *text =@"first";
NSMutableAttributedString*textLabelStr =
[[NSMutableAttributedStringalloc]
initWithString:text];
[textLabelStr
setAttributes:@{NSForegroundColorAttributeName:
[UIColorlightGrayColor], NSFontAttributeName :
[UIFontsystemFontOfSize:17]} range:NSMakeRange(11,
10)];
label.attributedText =textLabelStr;
// 17、竖排文字显示每个文字加一个换行符,这是最方便和简单的实现方式。
label.text = @"请\n竖\n直\n方\n向\n排\n列";
label.numberOfLines =[label.text length];
// 18、计算UIlabel 随字体多行后的高度
CGRect bounds =CGRectMake(0, 0, 200, 300);
heightLabel = [myLabeltextRectForBounds:bounds
limitedToNumberOfLines:20]; 计算20行后的Label的Frame
NSLog(@"%f",heightLabel.size.height);
// 19、UILabel根据字数多少自动实现适应高度
UILabel *msgLabel =[[UILabel alloc]
initWithFrame:CGRectMake(15, 45, 0, 0)];
msgLabel.backgroundColor= [UIColor lightTextColor];
[msgLabelsetNumberOfLines:0];
msgLabel.lineBreakMode= UILineBreakModeWordWrap;
msgLabel.font =[UIFont fontWithName:@"Arial"size:12];
CGSize size =CGSizeMake(290, 1000);
msgLabel.text = @"获取到的deviceToken,我们可以通过webservice服务提交给.net应用程序,这里我简单处理,直接打印出来,拷贝到.net应用环境中使用。";
CGSize msgSie =[msgLabel.text sizeWithFont:fonts
constrainedToSize:size];
[msgLabelsetFrame:CGRectMake(15, 45, 290, msgSie.height)];
// 20、渐变字体Label
UIColor *titleColor =[UIColor colorWithPatternImage:[UIImage
imageNamed:@"btn.png"]];
NSString *title =@"Setting";
UILabel *titleLabel =[[UILabel alloc]
initWithFrame:CGRectMake(0, 0, 80, 44)];
titleLabel.textColor =titleColor;
titleLabel.text =title;
titleLabel.font =[UIFont boldSystemFontOfSize:20];
titleLabel.backgroundColor= [UIColor clearColor];
[self.view addSubview:titleLabel];
[titleLabel release];
// 21、Label添加边框
titleLabel.layer.borderColor= [[UIColor grayColor] CGColor];
titleLabel.layer.borderWidth= 2;
5.UIImage的2种加载方式
//方式一:有缓存(图片所占用的内存会一直停留在程序中)
+(UIImage *)imageNamed:(NSString *)name;//name是图片的文件名
//方式二:无缓存(图片所占用的内存会在一些特定操作后被清除)
+(UIImage *)imageWithContentsOfFile:(NSString *)path
-(id)initWithContentsOfFile:(NSString *)path;//path是图片的全路径
6.UIImageView帧动画相关属性和方法
@property(nonatomic,copy) NSArray*animationImages;
需要播放的序列帧图片数组(里面都是UIImage对象,会按顺序显示里面的图片)
@property(nonatomic)NSTimeInterval animationDuration;
帧动画的持续时间
@property(nonatomic)NSInteger animationRepeatCount;
帧动画的执行次数(默认是无限循环)
-(void)startAnimating;
开始执行帧动画
-(void)stopAnimating;
停止执行帧动画
-(BOOL)isAnimating;
是否正在执行帧动画
7.原子性 和非原子性
atomic -----原子性---- 默认nonatomic ----非原子性
原子性 :默认这个属性是为了保证程序在多线程下,编译器会自动生成自旋锁代码,避免该变量的读写不同步问题,提供多线程安全,即多线程中只能有一个线程对它进行访问。注意:
1.atomic原子性指的是一个操作不可以被CPU中途暂停,然后再调度。即不能被中断,要么就执行完,要么就不执行2.atomic是自旋锁,当上一线程没有执行完毕的时候(被锁住),下一个线程会一直等待(不会进入睡眠状态),当上衣线程任务执行完毕,下一线程立即执行。它区别于互斥锁,互斥锁在等待的时候,会进入睡眠状态,当被上一线程执行完毕后,会被唤醒,然后再执行。3.atomic只给setter方法上锁,getter不会加锁4.atomic需要消耗大量的资源,执行效率低
非原子性
nonatomic:非原子性,非线程安全,多个线程可以同时对其进行访问,使用该属性编译器会少生成加锁代码,提高性能和效率,使用频率高,一般都是放弃安全,提高性能。
8.
1.assign 默认
适用于基本数据类型:NSInteger、CGFloat和C数据类型 int、float等
2.strong 对应MRC中的retain
强引用,只有OC对象才能够使用该属性,它使对象的引用计数加1
3.weak
弱引用,只是单纯引用某个对象,但是并未拥有该对象即一个对象被持有无数个弱引用,只要没有强引用指向它,那么它就会被清除释放
4.copy
为减少对上下文的依赖而引入的机制,可以理解为内容的拷贝内容被拷贝后,内存中会有两个存储空间存储相同的内容。指针不是同一个地址
UI控件使用weak的原因:
UI控件之所以可以使用弱指针,是因为控制器有强指针指向UIView UIView 有强指针指向Subviews数组,数组中由强指针指向控件
代理必须是weak,因为代理一般都是指向控制器,会造成循环引用,无法释放,造成内存泄露
关于weak 与assign
在ARC,出现循环引用的时候,必须有一端使用weakweak修饰的对象销毁的时候,指针会自动设置为nil而assign不会,assign可以用于非OC对象,而weak必须用于OC对象
关于copy与strong
NSString、NSArray、NSDictionary常用copy,为什么不用strong?
strong是强引用,指向的是同一个内存地址,copy是内容拷贝,会另外开辟内存空间,指针指向一个不同的内存地址,copy返回的是一个不可变对象,如果使用strong修饰可变对象,那么对象就会有可能被不经意间修改,有时不是我们想要的,而copy不会发生这种意外。
关于ARC下,不显示指定属性关键字时,默认关键字有哪些?
1.基本数据类型:atomic readwrite assign2.普通OC对象: atomic readwrite strong
关于@property的作用
使用@property,编译器会自动为我们添加getter和setter方法
摘自文章
9.description方法重写
description方法是NSObject类的一个实例方法,因此所有的Object-C对象都有description方法。description方法返回的永远是字符串。
description方法的作用是打印对象跟Java里的toString有点类似。对于一个Person类,如果没有重写description方法,NSLog(@“%@”,p),输出的是p的地址,而我们想要的效果是打印出person的成员变量,所以我们可以在Person类里重写description方法。
10. @synthesize和@dynamic区别
在声明property属性后,有2种实现选择
- @synthesize
编译器期间,让编译器自动生成getter/setter方法。
当有自定义的存或取方法时,自定义会屏蔽自动生成该方法 - @dynamic
告诉编译器,不自动生成getter/setter方法,避免编译期间产生警告
然后由自己实现存取方法
或存取方法在运行时动态创建绑定:主要使用在CoreData的实现NSManagedObject子类时使用,由Core Data框架在程序运行的时动态生成子类属性
11.ARC下,不显式指定任何属性关键字时,默认的关键字都有哪些?
atomic,readwrite,strong(对象)/assgin(基本数据类型)。
12.关于深浅拷贝。
able对象进行copy和mutableCopy都是内容复制。
用代码简单表示如下:
[immutableObject copy] // 浅复制
[immutableObject mutableCopy] //深复制
[mutableObject copy] //深复制
[mutableObject mutableCopy] //深复制
13.objc中向一个对象发送消息[obj foo]和objc_msgSend()函数之间有什么关系?
objc_msgSend()是[obj foo]的具体实现。
在runtime中,objc_msgSend()是一个c函数,[obj foo]会被翻译成这样的形式objc_msgSend(obj, foo)。
- 去obj的对应的类中找方法
- 先找缓存,找不到再去找方法列表,
- 再找父类,如此向上传递。
- 最后再找不到就要转发。
14.一个objc对象的isa的指针指向什么?有什么作用?
isa 指的就是 是个什么,对象的isa指向类,类的isa指向元类(meta class),元类isa指向元类的根类。isa帮助一个对象找到它的方法。isa:是一个Class 类型的指针. 每个实例对象有个isa的指针,他指向对象的类,而Class里也有个isa的指针, 指向meteClass(元类)。元类保存了类方法的列表。当类方法被调用时,先会从本身查找类方法的实现,如果没有,元类会向他父类查找该方法。同时注意的是:元类(meteClass)也是类,它也是对象。元类也有isa指针,它的isa指针最终指向的是一个根元类(root meteClass).根元类的isa指针指向本身,这样形成了一个封闭的内循环。