一、Xcode工具配置
1、网络访问配置:
在Info.plist文件中添加App Transport Security Settings->NSAllowsAritraryLoads-> YES
2、iOS10之后权限设置:
同样需要在Info.plist文件中直接添加
Privacy - Media Library Usage Description 访问媒体资料库
Privacy - Bluetooth Peripheral Usage Description 访问蓝牙等系统功能在需要调用的时候都需要进行请求授权操作。
3、以上操作有两种方式可以设置
<1>.直接Xcode打开Info.plist文件直接添加,如图:
<2>.选择Info.plist->右击->Open As->Source Code,如图:
打开之后如下,可以直接在code中添加:
二、设计模式
1、什么事设计模式?
在软件设计⾥,是对通⽤问题的可复⽤的解决⽅案!
2、为什么要用设计模式?
设计模式是⼀系列帮你写出更可理解和易复⽤代码的模板,设计模式帮你创建低耦合的代码以便你不需要费多⼤⼒就可以改变或者替换代码中的组件!
3、设计模式类型有?
<1>.创建型:单例(单态)和抽象工厂
<2>.结构型:模型-视图-控制器,装饰器、适配器,外观和组合模式
<3>.行为型:观察者、备忘录、责任链和命令模式
4、什么时候,如何使⽤,什么样的,设计模式?
<1>.MVC(解偶和)(复⽤-拓展-维护)
Model -View- Controller 模型-视图-控制器model和view之间是相互独⽴的,不知道对⽅的存在;controller负责他们之间的沟通和联系,实现低耦合,从⽽使代码易复⽤,易维护,易拓展
的;控制器的⾏为通过三种技术实现,delegate,targetaction,notification-kvo;
C对M:API
C对V:Outlet
V对C:Target-action, Delegate,Datasource
M对C:Notification,KVO
<2>.单例模式(整个⼯程对象唯⼀/节省资源-全局变量/保持数据)
概念:
核心结构中只包含一个被称为单例的特殊类,用static声明单例对象(全局变量),确保此工程唯一实例对象(且该实例易于外界访问),对象的实例变量和属性的生命周期是整个工程开始和结束,目的是为数据保存共享,注意多线程条件下加锁,避免多线程同时创建单例!(如果需要多次调用对象的属性保存添加数据,就用单例,而普通对象重复创建无法保存长期数据)
优点:
a.创建对象alloc浪费系统资源和时间 ,单例节省资源时间;
b.多模块访问同一变量,单例中则访问容易,数据保存共享,避免多模块相互传递风险和复杂;
c.唯一全局实例对象;
缺点:
单例模式使得对象变成了全局的,降低了每个单独模块的灵活性;
典型的系统单例
- UIApplication(应用程序实例)
- NSNotificationCenter(消息中心)
- NSFileManager(文件管理)
- NSUserDefaults(系统单例)
- NSURLCache(请求缓存)
- NSHTTPCookieStorage(应用程序cookies池)
获取APPDelegate
AppDelegate *app = (AppDelegate *)[UIApplication sharedApplication].delegate;
单例举例
+(MyUserInfo *)sharedInstance{
static MyUserInfo *userInfo = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken,^(void) {
userInfo = [[self alloc] initialize];
});
return userInfo;
}
static HttpRequestManager *manager = nil;
+(HttpRequestManager *)shareManager{
@synchronized(self){
if (manager == nil) {
manager = [[HttpRequestManager alloc] init];
}
}
return manager;
}
3、观察者模式(通知和KVO-类间传消息和值/解偶和)(对应MVC中
Model-Controller⽤Notification和kvo)
<1>.KVC/KVO(键值编码-批量复制/键值观察)
KVC主要用于批量赋值,有setValue:@"" forKey:@""
和valueForKey
两种方法分别对应setter和getter方法
Model *model = [[Model alloc]init];
[model setValue:string forKey:key]; //key为model的属性 string为赋值
给对象的属性赋值时使用:
User* user = [[User alloc] init];
[user setValue:@"张三" forKey:@"name"]
[user setValue:@"65" forKey:@"weight"];
如KVO的对象属性值发生变化,就会通知做相应的操作:
[user addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:NULL];
变化后处理函数:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
…
}
通知NSNotification(跨类传消息和值,消息发送者和接收者完全不知道对⽅,完全解偶和;可以创建多个观察者,消息具有⼲播性质,不需要时注意向通知中⼼注销观察者)
//发送通知
[[NSNotificationCenter defaultCenter] postNotificationName:@"postData" object:saveImageArray];
//接收通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(PostImage:) name:@"postData" object:nil];
//接收通知实现方法
-(void)PostImage:(NSNotification*) notification{
//接收到消息后实现内容
}
//移除通知中⼼
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"postData" object:nil];
通知实现原理/KVO实现原理
通知原理是接收端把接收函数注册到通知中心数组中,发送端发送数据就直接调用之前接收端注册函数,NSNotification是同步方式;KVO是对所关心的属性对象添加观察者,当属性值发生变化时会得到通知,我们可以对变化做相应的处理。
4、代理模式(回调-多继承-解偶和)(对应MVC中View-Controller ⽤Delegate或Datasource)
<1>.协议:制订协议,定义方法;谁遵守协议,谁实现方法;
<2>.代理:往往结合协议,设置代理,代理调用协议方法;遵守代理,实现代理协议方法;相当于A类在B类的方法实现内容和返回值;
<3>.步骤:
- 定义协议,设置方法;
- 设置代理,代理调用协议方法;
- 遵守协议,接受代理,代理实现协议方法;
.h文件中设置协议方法
#import <UIKit/UIKit.h>
// 协议方法
@protocol ReplyInputViewDelegate <NSObject>
-(void)clickSenderReplyButton:(UIButton *)sender;
@end
// 设置代理
@property (nonatomic,strong) id<ReplyInputViewDelegate>delegate;
.m中实现
-(void)clickSenderButton:(UIButton *)sender{
if (self.delegate &&[self.delegate respondsToSelector:@selector(clickSenderReplyButton:)]) {
[self.delegate clickSenderReplyButton:sender];
}
}
在控制器中药遵循代理,并实现方法:
方法和协议方法区别(类和类之间,协议不是类却相当于类)
a.⽅法⼀般只能在⼀个类中实现,协议⽅法的优势就在于此⽅法可以在任意类中实现后回调,协议⽅法实现相对整个类是独⽴模块,达到了解偶和;类中继承⼀个类就具有这个类的⽅法可以重构,⽽不能在另外继承就是单继承;⽽通过协议就继承了协议⽅法,相当于重构了⽅法,实现类似多继
承;
b.协议实现部分多继承功能(遵守协议就相当于继承了协议得⽅法),遵守协议后有@optional可选实现、@required必实现的⽅法,协议就是规范接⼝的;代理是⼀种设计模式,当⼀个类的某些功能⾃⼰不去做,需要由任何类来实现;
5、简单工厂模式
blocks(代替部分协议功能-接⼝-回调)
blocks代替部分协议代理功能,使⽤简单,不需要太多@protocol定义接⼝,主要实现接⼝,反向传值,回调的代码!
typedef NSString *(^loggerBolck)(NSString *) ;//定义
//实现
loggerBolck blocks = ^(NSString *str){
...
};
NSString *allstr = @"allstr";
NSString *str = @"str";
str = blocks(allstr); //调⽤
NSString *(^loggerBolck)(NSString *) ;
loggerbolck = ^(NSString *str){
...
};
NSString *allstr = @"allstr";
NSString *str = @"str";
str = loggerbolck(allstr);
NSString *(^loggerbolck)(NSString *)= ^(NSString *str){
...
};
NSString *allstr = @"allstr";
NSString *str = @"str";
str = loggerbolck(allstr);
Block注意点
blocks在类中做属性要⽤copy(⽆论arc和mrc) //保留blocks⽣命周期,copy不⽤retain,要注意release,否则就autorelease
__weak typeof(self) weakSelf = self;//把⾃⼰设置位弱引⽤
//__weak TCPClient *weakSelf = self; blocks⾥调⽤self时要设成弱引⽤对象,避免循环引⽤;防⽌在block中⽤到self时把self对象retain, 造成内存泄露;
typedef void(^SendMessage)(MessageObject*); //定义block
__weak TCPClient *weakSelf = self; //self设置为弱引⽤
//实现blocks
SendMessage sendMessage = ^(MessageObject *messageObejct){
NSString *sendString = [NSString stringWithFormat:@"%@",[messageObejct convertToString]];
NSData *sendData = [sendString dataUsingEncoding:NSUTF8StringEncoding];
[weakSelf.socketClient writeData:sendData withTimeout:-1 tag:0];
[weakSelf.socketClient readDataWithTimeout:-1 tag:0];
};
self.sendMessage (messageObject); //调⽤blocks
注:小白第一次写,如有错误欢迎批评指正,一起成长。