1.@synthesize和@dynamic的区别
在声明property属性后,有2种实现选择
@synthesize
编译器期间,让编译器自动生成getter/setter方法。
当有自定义的存或取方法时,自定义会屏蔽自动生成该方法
@dynamic
告诉编译器,不自动生成getter/setter方法,避免编译期间产生警告
然后由自己实现存取方法
或存取方法在运行时动态创建绑定:主要使用在CoreData的实现NSManagedObject子类时使用,由Core Data框架在程序运行的时动态生成子类属性
2.如果一个网络请求类可能用到多次,可不可以用单例设计模式实现?
这个请求类只是将不同的request请求作为参数传递到后方的服务接口,需要每一个请求都new一个专门的对象来处理吗?现在我每一个请求都new了一个对象来调后端服务接口,但考虑到请求数量很多,pv很大,所以看看能不能实现单例。
用单例主要是想节省内存资源,这个类主要是接受用户的不同请求调用后端接口返回不同的数据,不过实现单例不知道会不会出现其他的问题。。。
~~对于接受请求的地方可以统一处理,然后把参数封装一层 ,扔给service,具体怎么处理需要根据业务来
如果用单例,你是想每次通过请求的参数 赋值么,如果不是,每次吧这个实例用了之后赋值为NULL
这个只针对的是接收请求的地方吧,最多就多消耗一些资源,别的方面不会有多大的影响的,实现单例的时候最好考虑下多线程
3.初学iOS,刚看到控件的strong&weak问题,如果答的不对还请指正。首先有一点,在OC中,如果对象没有强引用,就会被自动释放,那么为什么控件还可以设为weak?
1. 从storyboard或者xib上创建控件,在控件放在view上的时候,已经形成了如下的引用关系,以UIButton为例:UIViewController->UIView->subView->UIButton然后你为这个UIButton声明一个weak属性@property(nonatomic,weak) IBOOutlet UIButton *btn;
相当于xib/sb对这个Button是强引用,你声明的属性对它是弱引用。2.手动创建控件a). 将控件声明成strong@property(nonatomic,strong) UIButton *btn;
那么你在实现这个控件时只需这样:
_btn = [[UIButton alloc]init];
[self.view addSubview:_btn]
b). 将控件声明成weak@property(nonatomic,weak) UIButton *btn;
那么你在实现这个控件时需要这样:
UIButton *button = [[UIButton alloc]init];
_btn = button;
[self.view addSubview:_btn];
最近看的黑马iOS视频上给的建议的是:1.如果用Stroyboard拖线,用weak2.如果自定对象,用strong(但我还是习惯用weak暂时=_=),其实不管声明的属性是强引用还是弱引用,在控制器消失的时候,这个属性消失,View消失,subViews消失,控件也就消失了。
之前专门搜过相关的问题,贴上来:IBOutlet的属性一般可以设为weak是因为它已经被view引用了,除非view被释放,否则IBOutlet的属性也不会被释放,另外IBOutlet属性的生命周期和view应该是一致的,所以IBOutlet属性一般设为weak。可参考如下:
From a practical perspective, in iOS and OS X outlets should be defined as declared properties. Outlets should generally be weak, except for those from File’s Owner to top-level objects in a nib file (or, in iOS, a storyboard scene) which should be strong. Outlets that you create will therefore typically be weak by default, because:Outlets that you create to, for example, subviews of a view controller’s view or a window controller’s window, are arbitrary references between objects that do not imply ownership.The strong outlets are frequently specified by framework classes (for example, UIViewController’s view outlet, or NSWindowController’s window outlet).
简单的说,如果IBOutlet对象是nib/sb scene的拥有者(File’s owner)所持有的对象,那么很显然拥有者必须“拥有”对象的指针,因此属性应设置为strong。而其他的IBOutlet对象的属性需要设置为weak,因为拥有者并不需要“拥有”他们的指针。举例来说,UIViewController的view属性是strong,因为controller要直接拥有view。而添加到view上的subviews,作为IBOutlet只需要设置为weak就可以了,因为他们不是controller直接拥有的。直接拥有subviews的是controller的view,ARC会帮助管理内存。紧接着,文档里又提到:
Outlets should be changed to strong when the outlet should be considered to own the referenced object:As indicated previously, this is often the case with File’s Owner—top level objects in a nib file are frequently considered to be owned by the File’s Owner.You may in some situations need an object from a nib file to exist outside of its original container. For example, you might have an outlet for a view that can be temporarily removed from its initial view hierarchy and must therefore be maintained independently.
第一种情形前面已经解释过了,对于第二种,通俗点将,就是controller需要直接控制某一个subview并且将subview添加到其他的view tree上去。单纯从ARC的角度思考,用weak也是很显然的:因为subview添加到view上时,view会“拥有”subview。当然,给IBOutlet属性设置为strong也没有错,“纠结谁对谁错“的问题可能需要上升到模式或者编码习惯的问题,已经超出本文的范围。
取消hits请求:App Transport Security Settings下Allow Arbitrary Loads置yes
enable bit code 置YES
子类实现父类方法,可以用在封装上面
父类确定时机,调用自己的实例方法,子类重写该方法
iOS_Copy到底什么时候用?
A:
在OC里面有个值对象的概念,当你新定义一个属性是值对象时就应该用copy来修饰。那么都什么对象是值对象呢?
值对象: 指封装了基本值(属于 C 数据类型)且提供与该值相关的服务的对象。值对象以对象形式表示标量类型。Foundation 框架向您提供了以下类(这些类产生对象,用于字符串、二进制数据、日期与时间、数字以及其他值):
NSString和NSMutableString , NSData和NSMutableData , NSDate , NSNumber , NSValue
B:
当一个指针执行的对象属性值发生改变时,不影响另一个对象,那么需要分配两个不同的内存地址,也就是说,我们就不可以采用retain关键字了,而是要采用copy 关键字,因为copy关键字会在复制时重新创建一个新的对象。
这里再提一下 : Copy:建立一个索引计数为1的对象,在赋值时使用传入值的一份拷贝。
(扩展:深拷贝[内存]和浅拷贝[指针]最大区别是什么?:“主要看子类对象的地址是否一致”)
深拷贝和浅拷贝的理解?
总结:深拷贝拷贝的是内容,浅拷贝拷贝的是指针。深拷贝和浅拷贝最大的区别就是子类对象的地址是否改变,如果子类对象的地址改变那么就是深拷贝。
详细解释:
浅层复制(copy):只复制指向对象的指针,而不复制引用对象本身。通过对象的指针来访问这个对象----只赋值地址
深层复制(mutableCopy):复制引用对象本身---再创建一个对象
意思就是有个A对象,复制一份后得到A_copy对象后,对于浅复制来说,A和A_copy指向的是同一个内存资源,复制的只不过是是一个指针,对象本身资源还是只有一份,那如果我们对A_copy执行了修改操作,那么发现A引用的对象同样被修改,这其实违背了我们复制拷贝的一个思想。深复制就好理解了,内存中存在了两份独立对象本身。//当修改A时,A copy不变。
我们在声明一个NSString属性时,对于其内存相关特性,通常有两种选择(基于ARC环境):strong与copy。那这两者有什么区别呢?什么时候该用strong,什么时候该用copy呢?让我们先来看个例子。
示例
我们定义一个类,并为其声明两个字符串属性,如下所示:
1
2
3
4 @interface TestStringClass ()
@property (nonatomic, strong) NSString *strongString;
@property (nonatomic, copy) NSString *copyedString;
@end
上面的代码声明了两个字符串属性,其中一个内存特性是strong,一个是copy。下面我们来看看它们的区别。
首先,我们用一个不可变字符串来为这两个属性赋值,
1
2
3
4
5
6
7
8 - (void)test {
NSString *string = [NSString stringWithFormat:@"abc"];
self.strongString = string;
self.copyedString = string;
NSLog(@"origin string: %p, %p", string, &string);
NSLog(@"strong string: %p, %p", _strongString, &_strongString);
NSLog(@"copy string: %p, %p", _copyedString, &_copyedString);
}
其输出结果是:
1
2
3origin string: 0x7fe441592e20, 0x7fff57519a48
strong string: 0x7fe441592e20, 0x7fe44159e1f8
copy string: 0x7fe441592e20, 0x7fe44159e200
我们要以看到,这种情况下,不管是strong还是copy属性的对象,其指向的地址都是同一个,即为string指向的地址。如果我们换作MRC环境,打印string的引用计数的话,会看到其引用计数值是3,即strong操作和copy操作都使原字符串对象的引用计数值加了1。
接下来,我们把string由不可变改为可变对象,看看会是什么结果。即将下面这一句
1NSString *string = [NSString stringWithFormat:@"abc"];
改成:
1NSMutableString *string = [NSMutableString stringWithFormat:@"abc"];
其输出结果是:
1
2
3origin string: 0x7ff5f2e33c90, 0x7fff59937a48
strong string: 0x7ff5f2e33c90, 0x7ff5f2e2aec8
copy string: 0x7ff5f2e2aee0, 0x7ff5f2e2aed0
可以发现,此时copy属性字符串已不再指向string字符串对象,而是深拷贝了string字符串,并让_copyedString对象指向这个字符串。在MRC环境下,打印两者的引用计数,可以看到string对象的引用计数是2,而_copyedString对象的引用计数是1。
此时,我们如果去修改string字符串的话,可以看到:因为_strongString与string是指向同一对象,所以_strongString的值也会跟随着改变(需要注意的是,此时_strongString的类型实际上是NSMutableString,而不是NSString);而_copyedString是指向另一个对象的,所以并不会改变。
结论
由于NSMutableString是NSString的子类,所以一个NSString指针可以指向NSMutableString对象,让我们的strongString指针指向一个可变字符串是OK的。
而上面的例子可以看出,当源字符串是NSString时,由于字符串是不可变的,所以,不管是strong还是copy属性的对象,都是指向源对象,copy操作只是做了次浅拷贝。
当源字符串是NSMutableString时,strong属性只是增加了源字符串的引用计数,而copy属性则是对源字符串做了次深拷贝,产生一个新的对象,且copy属性对象指向这个新的对象。另外需要注意的是,这个copy属性对象的类型始终是NSString,而不是NSMutableString,因此其是不可变的。
这里还有一个性能问题,即在源字符串是NSMutableString,strong是单纯的增加对象的引用计数,而copy操作是执行了一次深拷贝,所以性能上会有所差异。而如果源字符串是NSString时,则没有这个问题。
所以,在声明NSString属性时,到底是选择strong还是copy,可以根据实际情况来定。不过,一般我们将对象声明为NSString时,都不希望它改变,所以大多数情况下,我们建议用copy,以免因可变字符串的修改导致的一些非预期问题。
关于字符串的内存管理,还有些有意思的东西,可以参考NSString特性分析学习。
我先说下你两个代码的区别,第一个,当button 从试图移除之后不会释放,因为有强引用类型指向它,所以如果不再次释放一下,这个引用计数就是1
第二个,如果从父试图移除,这个button就直接释放了,因为是弱引用,弱引用不对引用计数造成影响
何时使用的问题,如果一个对象在某段时间中反复加载,而你又不希望每次加载都要重新alloc 的话,那就strong,strong 保证对此对象保持一个强引用,对于这个对象,只要有1个strong引用的话,那它就不会释放,当然多个strong同时作用于它也不会释放。
如果一个对象在某段时间只会加载一次,并且加载之后确定不再使用了,那就可以使用weak,这样当其他原因导致引用计数减1(比如 removefromsuperview)的时候,此对象就自动释放了。无需再在delloc 里面再release一次,但你要保证释放之后确实不再使用此对象,否则将导致错误
其实strong和retina的作用有些像,只不过strong 和weak是在arc里面引入的,他俩算是一对儿, 对应关系有点类似 retiam 和assign