5.1 微博 (ok) 好友列表(no ) 好友对话(ok),团购(ok) 再敲一遍javascript
5.3: 汤姆猫,传智猜图的逻辑,缩放(ok),轮播(待研究),英雄列表,汽车展现从新敲php
5.4: 把之前作的思路理一理;html
5.5: 预习一下;java
ios校招:ios
主要是c,c++ (不多有问ios的,项目问的很简单,只有网易问的是iOS的)c++
智力题:1-100之间的怎么样的找一个数最快;git
c,c++问的是算法,数据结构;程序员
找工做的帖子;分享找工做;web
面试不多问UI 问多线程_retian _ 内存管理面试
GCD 和NSOperation
编码规范??良好的
qq好友列表的headerView和团购的headerView有什么区别
qq好友列表的相似于加在组的最开头,和加入cell的形式相似
团购加在:头部就至关于加个工具条
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <UIKit/UIResponder.h>
#import <UIKit/UIInterface.h>
#import <UIKit/UIKitDefines.h>
#import <UIKit/UIAppearance.h>
#import <UIKit/UIDynamicBehavior.h>
#import <UIKit/NSLayoutConstraint.h>
UI基础笔记
无** 通常知识点
*** 重点
***** 重难点 编码规范存在的问题: == * 空格,别人阅读方便
UI笔记
按钮可以显示lable和图片是应为按钮内部有UIlable,UIImageView//不是UIView
因此能够显示图片和文字
按钮有normal 和highlight 还有其余diasble;
字典表明数据,根据名称找到数据,适合存储大规模的数据.
字典的缺点:经过字符串类型的key取值容易写错,写错了key编译器不会报错;
模型:存放数据,继承自NSObject比较纯洁的对象;
建立一个类(即模型)MJApp.h+MJApp.m;只用来放数据,比较纯洁;
上述类成为模型类;
12个字典转化为12个模型,//每一个字典中有两对数据;
在模型对象中声明两个属性Name,和icon存储数据;
存储的每一个数据是一个字典;name
自定义构造方法都是返回:Id类型,是自定义类型;//intancetype
UI基础笔记
0416:UI 基础
IOS 4.0 iphone,开发高峰期
ios6.0真正的是多任务运行,界面是
1.IBAction:
1> 能保证方法能够连线
2> 至关于void
2.IBOutlet:
1> 能保证属性能够连线
3.常见错误
setValue:forUndefinedKey:]: this class is not key value coding
错误缘由是:连线出问题了
4.Xcode5开始的一些建议
把用于连线的一些方法和属性声明在.m文件的类扩展中,保证了封装性,私有的;
5. frame\center\bounds
1> frame:能修改位置和尺寸
2> center:能修改位置
3> bounds:能修改尺寸(x\y通常都是0)相对于本身:
0404
identifier:com.baidu,cn.itcast,公司域名
name名字中不能出现中文;
prefix
入口是main函数,
UIView--画板
UIViewController====画家;先建立UIController再画板,画家管理画板
IBAction 至关于void告诉编译器这个是能够连线的
控件使用@property weak
显示字符串的的控件必定有text的属性,text的方法
第一响应者:当前和谁交互谁就是第一响应者
[self.view endEditing:YES];
self.view不当第一响应者 //view 里面包含有UILable UIview UIButton 至少这三种
//这三种都不当第一响应者
/*self问题总结*/
XiaoMing 类
建立xiaoming 对象;
小明类中有name,age,delegate 个属性;
sick方法是XiaoMing类中定义方法
-(void)sick
{
NSLog(@"生病了");
[_delegate lookSickWithName:_name andAge:_age];
//_name=self.name _age=self.age,此处是xiaoming这个对象调用
//name的get方法不是,self不表明_delegate这个对象,[]这不算一个方法
//self调用当前的方法;
[_delegate lookSickWithXiaoMing:self];//此方法若是不实现就会崩溃
}
self关键字表明谁?
对象调用self就表明对象
类名调用方法,self就表明那个类
self处在那个类文件中,self就表明那个文件中,直接使用self能访问所在类文件中的方法和
属性,在类中就表明类对象,在类方法中就表明类;
controlviewer类中的对象系统本身建立的,隐藏的!
其实,每当显示一个新界面时,首先会建立一个新的UIViewController对象,而后建立一个对应的
全屏UIView,UIViewController负责管理这个UIView UIViewController就是UIView的大管家,
负责建立、显示、销毁UIView,负责监听UIView内部的事件,负责处理UIView与用户的交互
UIViewController内部有个UIView属性,就是它负责管理的UIView对象 ,监听按钮:
@property(nonatomic,retain) UIView *view;//因此能够self.view
//计算器中的所谓的self就是这个view吗,不是这个,self是NJControlView*的对象;
//self.view指的是contrller的子空间下属的view包含的加进去的全部子控件;
//self.text1.此处的self点的覆盖的范围的吗?
//view中的全部子空间都不当响应者了
连线的多种方式?
1.从代码拖到界面上
2.从界面拖到代码
3.从control到界面
1>UIViw全部控件的父控件;
2>frame:控件相对于父类的坐标位置,
3>center:也是以父控件做为参考点
4>bounds:以本身为参考点
self.tupian.frame.origin.x-=10;//错误修改x的值的方法;
CGRect tem=self.tupian.frame; 1>保存原值;
tem.origin.y-=30; 2>修改某一个值
self.tupian.frame=tem; 3>修改的值总体重赋
能够得出一个结论:UI界面上的每个元素都是一个对象,好比:
一张图片是一个UIImageView对象
一段文字是一个UILabel对象//+ =
文本输入,键盘输入:UITexTFeild
一只按钮是一个UIButton对象//文字,图片,响应事件
为了方便开发者开发出强大的功能,苹果提供了各类各样的框架
UIKit - 建立和管理应用程序的用户界面
QuartzCore -提供动画特效以及经过硬件进行渲染的能力
CoreGraphics -提供2D绘制的基于C的API
CoreLocation -使用GPS和WIFI获取位置信息
MapKit -为应用程序提供内嵌地图的接口
AVFoundation – 音频处理//等等
在.m中声明的方法是私有方法,外界没法直接访问,保证了封装性
int num2 = [self.number2.text intValue];//强制类型装换,self表明.
Perosn *p =(Perosn *)stu;//此处也是强制类型转换,stu原本是Student类型的,强转后转化为Person类型的
疑问:子类是能够强制转化为父类!
屏幕上能看得见摸得着的东西就是UIView,好比屏幕上的按钮、文字、图片
通常翻译叫作:视图\控件\组件
UIButton、UILabel、UITextField都继承自UIView
每个UIView都是一个容器,能容纳其余UIView(好比右图中的整个键盘是一个UIView,里面容纳不少
小格子的数字UIView)
严格来说,下图箭头所指的应该是一个UIViewController对象(手机下方的viewcontriller条),
里面白色的界面仅仅是UIViewController内部的UIView属性(整个白屏,什么都不建时的白屏);
****
综合分析,能够得出程序的简单运行流程是怎么样的?
1>读取Main.storyboard文件
2>建立箭头所指的MJViewController对象
3>根据storyboard文件中描述建立MJViewController的UIView对象
4>将UIView对象显示到用户眼前
如今已经知道:应该由MJViewController来监听“计算”按钮的点击
换句话说,MJViewController应该提供一个方法出来,当用户点击“计算”按钮时,就调用这个方法来
通知MJViewController按钮被人点了MJViewController就在这个方法中实现想作的任何事情,好比
计算2个文本输入框内值的和
IBAction
从返回值角度上看,做用至关于void
只有返回值声明为IBAction的方法,才能跟storyboard中的控件进行连线
IBOutlet
只有声明为IBOutlet的属性,才能跟storyboard中的控件进行连线
resignFirstResponder//辞职当第一响应者;
当叫出键盘的那个控件(第一响应者)调用这个方法时,就能退出键盘
[self.view endEditing:BOOL];
只要调用这个方法的控件内部存在第一响应者,就能退出键盘
可见,确实须要常常修改控件状态
那如何去修改控件的状态呢?方法很简单
每个UI控件都是一个对象//万物皆对象,万物截指针
修改UI控件的状态,其实就是修改控件对象的属性
好比修改UILabel显示的文字,就修改UILabel对象的text属性便可
好比修改UIImageView显示的图片,就修改UIImageView对象的image属性便可
不难想到,每个UI控件确定都有不少属性,好比:
UIProgressView进度条控件有progress属性(进度值)
UILabel和UITextField都有text属性(显示文字)
UITextField 输入文本
虽然,每个UI控件都有 本身的独特属性,可是有些属性是每一个UI控件都具有的,
好比每个UI控件都有本身的位置和尺寸、都有本身的父控件、子控件。因而,全部的UI控件
最终都继承自UIView,UI控件的公共属性都定义在UIView中,好比:
frame :位置和尺寸
center :中心点位置
****
@property(nonatomic,readonly) UIView *superview;
得到本身的父控件对象//父控件只有一个
@property(nonatomic,readonly,copy) NSArray *subviews;
得到本身的全部子控件对象//子空间有不少
@property(nonatomic) NSInteger tag;//
控件的ID\标识,父控件能够经过tag来找到对应的子控件
@property(nonatomic) CGAffineTransform transform;
控件的形变属性(能够设置旋转角度、比例缩放、平移等属性)
@property(nonatomic) CGRect frame;
控件所在矩形框在父控件中的位置和尺寸(以父控件的左上角为坐标原点)
@property(nonatomic) CGRect bounds;
控件所在矩形框的位置和尺寸(以本身左上角为坐标原点,因此bounds的x\y通常为0)
//bound也有x,y,w,h 只是相对于本身的来讲因此x,y通常都为0;
@property(nonatomic) CGPoint center;
控件中点的位置(以父控件的左上角为坐标原点)
//本身的位置是以中点到父控件的边缘位置
****
若是发现经过代码没法修改控件的位置或者尺寸时,应该去掉storyboard里面的autolayout功能,
这是自iOS6开始出现的特性顾名思义,autolayout是用来自动布局的,用来束缚控件的位置和尺寸。
去掉这个功能,控件的位置和尺寸就再也不有一些固定的束缚。
1>normal(普通状态)
默认状况(Default)
对应的枚举常量:UIControlStateNormal
2>highlighted(高亮状态)
按钮被按下去的时候(手指还未松开)
对应的枚举常量:UIControlStateHighlighted
3>disabled(失效状态,不可用状态)
若是enabled属性为NO,就是处于disable状态,表明按钮不能够被点击
对应的枚举常量:UIControlStateDisabled
设置按钮在不一样状态下的背景图片
(为了保证高亮状态下的图片正常显示,必须设置按钮的type为custom)
经过如下属性能够修改控件的位置
frame.origin
center
经过如下属性能够修改控件的尺寸
frame.size
bounds.size
实际上,UIButton自带了不少种不一样的样式
在用代码建立按钮的同时指定按钮样式
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
UIButtonTypeCustom:无类型,按钮的内容须要自定义
UIButtonTypeDetailDisclosure:
UIButtonTypeInfoLight:
UIButtonTypeInfoDark:
UIButtonTypeContactAdd:(添加一个加号)
计算器总结:
1>拖控件
2>controlviewer.m中声明空间的属性,(私有保证封装)
3>controlviewer.h 中声明方法,.m中实现方法,而且 拖线,全部的都要拖线
4>方法中或者字符串的值,字符串装换到int 再输出到显示上
+ (NSBundle *)mainBundle;//此处返回的是NSBoudle型的对象;不是返回一个类,返回的对象调用pathfor
我的理解字典:字典也是一种数组类型,只是其中更具key的值就能够找到value的值,key -value一一对应;
字典中存放的方法:
dic {
1 = one;
12 = onew;
13 = onewe;
}
UIButton* //下面的方法如何去分析,UIButton中如何去找font//用多了就会了?
由于UIButton有font的属性,既然是属性,就须要用对象调用,因此须要对象,对象涉及到get和set方法,
字体返回为UIFont 到UIfont中看看哪些返回UIFont的方法;
****//手动添加button中的字体
downloadBtn.titleLabel.font=[UIFont systemFontOfSize:12];
//代码添加的控件的层次,结构关系,Xcode能够看到吗?
看不到,由于代码编译,连接后才能展示 ;
//+++++++**********++++++++**********---重点代码
---------------------------------------------------------------------------------------------------
添加代码?
for (int index=0; index<self.apps.count; index++) {//self.apps放回的是一个NSArray;计算NSArray.count
// 3.1.建立1小框框----------------------------
//建立一个大的UIView;UIView和UIImageView的区别,
UIView是UIImageView 的父类;
UIView是
UIView*appView=[[UIView alloc]init]; //+++++++**********++++++++**********
// 设置背景色
appView.backgroundColor=[UIColor cyanColor];
// 3.2.计算框框的位置
// 计算行号和列号
int row=index/totalColumns;
int col=index%totalColumns;
// 计算x和y
CGFloat appX=marginX+col*(appW+marginX);
CGFloat appY=marginY+row*(appH+marginY);
//设置Frame的大小和位置
appView.frame=CGRectMake(appX, appY, appW, appH);
//3.3添加框框到控制器
[self.view addSubview:appView]; //此处的view是表明(UIView*); //+++++++**********++++++++**********
// 有个view的get方法
//3.4UIView中添加内部小控件
//3.4.0index位置对应的应用信息
// **** 数组的位置转化为字典;
NSDictionary*appInfo=self.apps[index];//apps声明的是一个数组的属性;对应位置的数组的转化为对应位置的字典;
//添加图片----------------------------
//建立+大小+增长+++++++++++
UIImageView*iconView=[[UIImageView alloc]init]; //+++++++**********++++++++**********
CGFloat iconW=45;
CGFloat iconH=45;
CGFloat iconX=(appW-iconW)*0.5;
CGFloat iconY=0;
iconView.frame=CGRectMake(iconX, iconY, iconW, iconH);
//添加图片****** 取得字典中icon对应的图片;
iconView.image=[UIImage imageNamed:appInfo[@"icon"]];//+++++++**********++++++++**********
//建立好的子控件添加
[appView addSubview:iconView];
//添加名字----------------------------
//建立+大小+增长+++++++++++
UILabel*nameLable=[[UILabel alloc]init];
CGFloat nameX=0;
CGFloat nameY=iconY+iconH;
CGFloat nameW=appW;
CGFloat nameH=20;
nameLable.frame=CGRectMake(nameX, nameY, nameW, nameH);
//添加名字******
nameLable.text=appInfo[@"name"]; //+++++++**********++++++++**********
nameLable.font=[UIFont italicSystemFontOfSize:13];
nameLable.textColor=[UIColor darkGrayColor];
nameLable.textAlignment=NSTextAlignmentCenter; //+++++++**********++++++++**********
//建立好的子控件添加
[appView addSubview:nameLable];//向UIView对象中增长子控件;
//添加下载按钮----------------------------
//建立+大小+增长+++++++++++
UIButton*downloadBtn=[[UIButton alloc]init];
CGFloat downloadX=12;
CGFloat downloadY=nameY+nameH;
CGFloat downloadH=20;
CGFloat downloadW=appW-2*downloadX;
downloadBtn.frame=CGRectMake(downloadX, downloadY, downloadW, downloadH);
//建立图片对象
UIImage*normalImage=[UIImage imageNamed:@"buttongreen"]; //+++++++**********++++++++**********
UIImage*highImage=[UIImage imageNamed:@"buttongreen_highlighted"]; //+++++++**********++++++++**********
//将建立的图片对象设置为背景
[downloadBtn setBackgroundImage:normalImage forState:UIControlStateNormal];//+++++++**********++++++++**********
[downloadBtn setBackgroundImage:highImage forState:UIControlStateHighlighted];//+++++++**********++++++++**********
//设置状态的下载;
[downloadBtn setTitle:@"下载" forState:UIControlStateNormal];//+++++++**********++++++++**********
//设置字体
downloadBtn.titleLabel.font=[UIFont systemFontOfSize:13];//+++++++**********++++++++**********
//建立好的子控件添加
[appView addSubview:downloadBtn];
}
-----------------------------------------------------------------------------------------------------------------
------------------------------------------
MJApp.h文件中模型的头文件中
@property (nonatomic, copy) NSString *name;
/**
* 图标
*/
@property (nonatomic, copy) NSString *icon;
/**
* 经过字典来初始化模型对象
*
* @param dict 字典对象
*
* @return 已经初始化完毕的模型对象
*/
- (instancetype)initWithDict:(NSDictionary *)dict;
+ (instancetype)appWithDict:(NSDictionary *)dict;
------------------------------------------
MJApp.m 中
@implementation MJApp
- (instancetype)initWithDict:(NSDictionary *)dict
{
if (self = [super init]) {//使用%@打印
//字典中name键值对应的名字如:节奏大师赋值给模型的name,模型中声明有name 的get方法;
self.name = dict[@"name"];//self.name = 节奏大师
//字典中icon键值对应的名字如:icon_05赋值给模型的icon,模型中声明有icon的 get方法;
self.icon = dict[@"icon"];//self.icon = icon_05
}
return self;(self 表明MJApp*对象)
}
+ (instancetype)appWithDict:(NSDictionary *)dict
{
return [[self alloc] initWithDict:dict];//返回MJApp对象的地址
}
@end
------------------------------------------
//0326应用管理模型使用: MJViewController.m文件中
#import "MJViewController.h"
#import "MJApp.h"
@interface MJViewController ()
/** 存放应用信息 */
@property (nonatomic, strong) NSArray *apps;
@end
@implementation MJViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// 设置图片
iconView.image = [UIImage imageNamed:appInfo.icon];
// 3.4.2.添加名字-------------------------------------
nameLabel.text = appInfo.name;//nameLabel.text加载的是字符串.
}
- (NSArray *)apps//---------------字典数组转化为模型的方法:+++++++**********++++++++**********
{
if (_apps == nil) {
// 初始化
// 1.得到plist的全路径
NSString *path = [[NSBundle mainBundle] pathForResource:@"app.plist" ofType:nil];
// 2.将路径中的plist文件加载成字典数组
NSArray *dictArray = [NSArray arrayWithContentsOfFile:path];//建立的究竟是字典仍是你数组仍是字典数组,是字典仍是数组看Root处是字典仍是数组;
// 3.将dictArray里面的全部字典转成模型对象,放到新的数组中
NSMutableArray *appArray = [NSMutableArray array];//建立一个可变数组;
for (NSDictionary *dict in dictArray) {//遍历字典数组
// 3.1.建立模型对象
// MJApp *app = [[MJApp alloc] initWithDict:dict];
MJApp *app = [MJApp appWithDict:dict];
// 3.2.添加模型对象到前面定义的可变数组中
[appArray addObject:app];//字典数组-模型-可变数组中?只是借助模型(这个类中的)appWithDict将字典
//转化为模型,
}
// 4.赋值
_apps = appArray;
}
return _apps;
}
3.使用xib封装一个自定义view的步骤 // (下面的方法在代码中是如何实现的);
1> 新建一个继承UIView的自定义view,假设类名叫作(MJAppView)
//MJAppView.xib的文件;
2> 新建一个MJAppView.xib文件来描述MJAppView内部的结构
//里面加UILable,UIImageView,UIButton在一个xib局部界面中;
3> 修改UIView的类型为MJAppView真实类型
//UILabel *nameLabel = (UILabel *)[appView viewWithTag:20];即代码中的强制类型装换;
4> 将内部的子控件跟MJAppView进行属性连线
/
5> MJAppView提供一个模型属性
MJApp.h MJApp.m 一个是模型的两个数据;
6> 重写模型属性的set方法,由于在set方法中能够拿到外界传递的模型数据
7> 把模型数据拆开,分别设置数据到对应的子控件中
8> 补充:提供一个建立MJAppView的类方法,将读取xib文件的代码屏蔽起来
@end
//代码加载xib的方法:
for (int index = 0; index<self.apps.count; index++) {//+++++++**********++++++++**********
NSBundle *bundle = [NSBundle mainBundle];
// 读取xib文件(会建立xib中的描述的全部对象,而且按顺序放到数组中返回)//+++++++**********++++++++**********
NSArray *objs = [bundle loadNibNamed:@"MJAppView(省略xib后缀)" owner:nil options:nil];//MJAppView=MJAppView.xib//+++++++**********++++++++**********
UIView *appView = [objs lastObject];//+++++++**********++++++++**********
// 3.2.添加view
[self.view addSubview:appView];
// 3.3.设置frame
int row = index / totalcolumns;
int col = index % totalcolumns;
// 计算x和y
CGFloat appX = marginX + col * (appW + marginX);
CGFloat appY = 30 + row * (appH + marginY);
appView.frame = CGRectMake(appX, appY, appW, appH);
// 3.4.设置数据
MJApp *app = self.apps[index];
// 3.4.1.图片
// UIImageView *iconView = appView.subviews[0];
UIImageView *iconView = (UIImageView *)[appView viewWithTag:10];
父类强制转化为子类
iconView.image = [UIImage imageNamed:app.icon];//模型中的app.icon返回的是字符串型的,只是不会打印@" ";
2014-04-17 19:56:34.787 01-应用管理[30319:70b] app.icon = icon_00
2014-04-17 19:56:34.787 01-应用管理[30319:70b] app.name = 每天酷跑
// 3.4.2.名称
// UILabel *nameLabel = appView.subviews[1];
UILabel *nameLabel = (UILabel *)[appView viewWithTag:20];//强制类型转换viewWithTag返回的是UIView型的,因此须要强转;
nameLabel.text = app.name;//字符串传给一个文本,文本text的属性方法返回的是一个NSString型的;
}
--------------------------------------------------------------------------------------------------------------
0326笔记整理
1.纯代码方式实现九宫格
* 一个格子一个格子添加
* 使用for循环添加
2.字典转模型
* 什么是模型
* 好处分析
* 将字典转换为模型
* 模型提供字典转模型的构造方法
3.使用xib文件
* 用来描述九宫格
* 用来描述中间的提示信息
4.封装
* 纯代码的封装
* xib的封装
//使用xib和模型完成九宫格的思路:
1>新建xib文件,添加局部空间,设置tag,方便之后使用;
2>
QQ好友列表设计思路:
1>获取plist数据必须有模型建模型,好友列表的模型是:plist=2个字典+friends数组(有n个字典,字典有:name,icon,intro,online属性);
1.1 friend模型: *friends; online; NSString *name;
-(instancetype)initWithDict:(NSDictionary *)dict
{
if (self=[super init]) {
[self setValuesForKeysWithDictionary:dict];
}
return self;
}
1.2 friendGroup模型:name,icon,intro,online
-(instancetype)initWithDict:(NSDictionary *)dict//一次转化一个模型
{
if (self=[super init])
{
//注入全部的属性 三个属性转化为字典
[self setValuesForKeysWithDictionary:dict];//此处的self打印仍是数组和两个模型
//建立,遍历,转化,添加,赋值 处理特殊的属性
//下面的是补充转化,二次处理
NSMutableArray*models=[NSMutableArray arrayWithCapacity:self.friends.count];
//取出self.frends数组中的每一个字典转化,没经历下面的遍历转化以前,frends数组中存的是N个字典,遍历后frends中
存放的是模型地址
for (NSDictionary*dict in self.friends) {
MJFriend*friend=[MJFriend friendWithDict:dict];
[models addObject:friend];//medels是一个数组,转化后存放4个模型的数组
}
self.friends=models;//models 是模型数组,MJFriend中friend是转化后的模型数组:里面存放有不少单个模型
}//打印看下
//返回的是一组模型;
return self;//至此self打印是一个地址,完全封装为一个模型;从新打印[self setValuesForKeysWithDictionary:dict],里面是10个模型地址;
}
2>都是:tableViewcell,是使用自定义的cell,因此必需要tableViewcell;
2.1里面拖UITableViewController,
2.2MJViewController : UITableViewController
2.3UITableViewController的类名为MJViewController ;
2.4里面有cell须要用到的数据:friend*
3>MJFriendCell类: MJFriendCell 继承 UITableViewCell //对应于管理XIB的文件
3.1方法cellWithTableView:根据tableView返回一个cell(建立出列,返回)
3.2MJFriend *对象,重写set方法为friend设置属性数据,每一个好友的头像,签名,状态信息
4>MJHeaderView类: MJHeaderView 继承 UITableViewHeaderFooterView
4.1专门用来添加头部视图:在头部视图中(contentView中)添加btn(包含imageView和settitle)和nameLabel就能够完成显示功能
4.2设置位置,状况,imageView的选装和防止变形
4.3 [self.btn addTarget:self action:@selector(headerClick) forControlEvents:UIControlEventTouchUpInside];
响应事件,并做相应的处理
-(void)headerClick 0428的代码最后一节课;
{
self.group.opened=!self.group.isOpen;
if ([self.delegate respondsToSelector(返回BOOL):@selector(headerViewDidClick:)]) //判断方法headerViewDidClick:是否实现
[self.delegate headerViewDidClick:self];//若是实现就让headerView的代理 去调用headerViewDidClick这个方法,同时把本身传进出;
}
}
4.4headerViewDidClick中reload方法,在UITableView中,UITableView 继承 UIScrollView,若是在MJHeaderView类中是没法
调用reload方法的,因此通知:UITableView代办,通知=代理,
声明一个协议,协议中声明有方法,申明代理:
4.4.1//声明一个协议
@protocol MJHeaderViewDelegate <NSObject>
4.4.2//协议中声明有方法
- (void) headerViewDidClick:(MJHeaderView*)headerView;
@end
@interface MJHeaderView : UITableViewHeaderFooterView
4.4.3//申明代理
@property(nonatomic,weak) id <MJHeaderViewDelegate> delegate;
4.4.4//代理创建关系
viewForHeaderInSection中header.delegate=self;
4.4.5//实现协议中的方法
5>控制器:设置数据源方法,和代理新方法
1>多少组用到数据源,设计字典转模型;
2>每组多少行涉及,单个模型,属性
3>设置cell的属性
3.1:建立cell须要一个独立的类,保存建立cell的方法,cellWithTableView,还有为cell设置具体详细信息
3.2获取模型数据
3.3利用得到的模型和属性,为cell赋值;
self.btn.imageView.transform=CGAffineTransformMakeRotation(M_PI_2);旋转
self.btn.imageView.transform=CGAffineTransformIdentity;恢复位置
btn.contentEdgeInsets=UIEdgeInsetsMake(0,20, 0, 0); // 设置label和imageview之间的距离
// 设置lable和imageView之间的间距 btn.imageEdgeInsets
btn.titleEdgeInsets=UIEdgeInsetsMake(0, 20, 0, 0);
self.btn.imageView.contentMode=UIViewContentModeCenter;
//超出的部分不剪切
self.btn.imageView.clipsToBounds=NO;
#pragma mark-旋转功能
//当视图添加到别的视图就会被调用,
-(void)didMoveToSuperview
{
if (self.group.isOpen)
{
self.btn.imageView.transform=CGAffineTransformMakeRotation(M_PI_2);
}else
{
self.btn.imageView.transform=CGAffineTransformIdentity;
}
//当视图被修改的时候就会调用这个方法,通常在这个方法中布局子控件
- (void)layoutSubviews
{
#warning 必定要调用父类的方法
[super layoutSubviews];
//设置点击按钮的button的frame
self.btn.frame = CGRectMake(0, 0, 320, 44);
//设置nameLable的frame
CGFloat lableY = 0;
NSLog(@" = %@\n",NSStringFromCGRect(self.bounds));
CGFloat lableH = self.bounds.size.height;
CGFloat lableW = 50;
CGFloat lableX =self.bounds.size.width-lableW-10;
self.nameLable.frame=CGRectMake(lableX, lableY, lableW, lableH);
NSLog(@"layoutSubviews\n");
}
打开关闭分组
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
//取出对应组的模型
MJFriendGroup*group=self.groups[section];
//group 模型,frinds存放好友的模型,
// NSLog(@"numberOfRowsInSection = %d\n",group.friends.count);
//friends数组中朋友的个数
return group.isOpen==NO ? 0 : group.friends.count;
}
1>老师讲的之后都是重点
2>面试的代码须要手写,几乎没有上机的
3>80%问项目:
思路,难点,用到的知识,怎么解决问题的,难点如何克服的.
1.Xcode自带头文件的路径
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/
Developer/SDKs/iPhoneSimulator7.1.sdk/System/Library/Frameworks/UIKit.framework/Headers
2.修改了系统自带头文件后,Xcode会报错,须要清除缓存
解决方案:删掉下面文件夹的缓存便可(aplle是电脑的用户名)
/Users/aplle/资源库/Developer/Xcode/DerivedData
或者
/Users/aplle/Library/Developer/Xcode/DerivedData
使用字典容易写错
Key若是写错了,编译器不会有任何警告和报错,形成设错数据或者取错数据
使用模型的好处
所谓模型,其实就是数据模型,专门用来存放数据的对象,用它来表示数据会更加专业
模型设置数据和取出数据都是经过它的属性,属性名若是写错了,编译器会立刻报错,所以,保证了数据的正确性
使用模型访问属性时,编译器会提供一系列的提示,提升编码效率
app.name = @"Jack”;
NSString *name = app.name;
的坏处
通常状况下,设置数据和取出数据都使用“字符串类型的key”,编写这些key时,编译器不会有任何友善提示,须要手敲
dict[@"name"] = @"Jack";
NSString *name = dict[@"name"];
手敲字符串key,key
字典转模型的过程最好封装在模型内部
模型应该提供一个能够传入字典参数的构造方法
- (instancetype)initWithDict:(NSDictionary *)dict;
+ (instancetype)xxxWithDict:(NSDictionary *)dict;
instancetype在类型表示上,跟id同样,能够表示任何对象类型
instancetype只能用在返回值类型上,不能像id同样用在参数类型上
instancetype比id多一个好处:编译器会检测instancetype的真实类型
Xib文件能够用来描述某一块局部的UI界面
Xib文件的加载
方法1
//存放到数组中,数组中又用不少元素;
NSArray *objs = [[NSBundle mainBundle] loadNibNamed:@"MJAppView" owner:nil options:nil];
这个方法会建立xib中的全部对象,而且将对象按顺序放到objs数组中
(若是xib如右图所示,那么objs数组中依次会有3个对象:1个UIView、1个UIButton、1个UISwitch)
方法2
bundle参数能够为nil,默认就是main bundle
UINib *nib = [UINib nibWithNibName:@"MJAppView" bundle:[NSBundle mainBundle]];
NSArray *objs = [nib instantiateWithOwner:nil options:nil];
在开发阶段,面向开发者的是xib文件; 当把应用装到手机上时,xib文件就会转为nib文件
要想随意调整xib中view的尺寸,首先要设置size为Freeform
xib文件就会转为nib文件
xib文件和storyboard 区别:
xib文件就会转为nib文件
1>共同点:
都用来描述软件界面
都用Interface Builder工具来编辑
2>不一样点
Xib是轻量级的,用来描述局部的UI界面
Storyboard是重量级的,用来描述整个软件的多个界面,而且能展现多个界面之间的跳转关系
若是一个view内部的子控件比较多,通常会考虑自定义一个view,把它内部子控件的建立屏蔽起来,不让外界关心
外界能够传入对应的模型数据给view,view拿到模型数据后给内部的子控件设置对应的数据
经常使用方法?
1>
- (void)setTitle:(NSString *)title forState:(UIControlState)state;
设置按钮的文字
2>
- (void)setTitleColor:(UIColor *)color forState:(UIControlState)state;
设置按钮的文字颜色
3>
- (void)setImage:(UIImage *)image forState:(UIControlState)state;
设置按钮内部的小图片
4>
- (void)setBackgroundImage:(UIImage *)image forState:(UIControlState)state;
设置按钮的背景图片
5>
设置按钮的文字字体(须要拿到按钮内部的label来设置)
btn.titleLabel.font = [UIFont systemFontOfSize:13];
6>
- (NSString *)titleForState:(UIControlState)state;
得到按钮的文字
7>
- (UIColor *)titleColorForState:(UIControlState)state;
得到按钮的文字颜色
8>
- (UIImage *)imageForState:(UIControlState)state;
得到按钮内部的小图片
9>
- (UIImage *)backgroundImageForState:(UIControlState)state;
得到按钮的背景图片
0418QQ图片错误;
Cannot find executable for CFBundle 0x8bbea80 </Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator7.0.sdk/System/Library/AccessibilityBundles/CertUIFramework.axbundle> (not loaded)
对象都是类建立出来的;
15:08边走边转,覆盖
- (IBAction)move:(UIButton *)sender {
CGAffineTransform transform = self.headBtn.transform;
switch (sender.tag) {
case 1: // 上
transform = CGAffineTransformTranslate(transform, 0, -10);
break;
case 2: // 右
transform = CGAffineTransformTranslate(transform, 10, 0);
break;
case 3: // 下
transform = CGAffineTransformTranslate(transform, 0, 10);
break;
case 4: // 左
transform = CGAffineTransformTranslate(transform, -10, 0);
break;
}
self.headBtn.transform = transform;
}
- (IBAction)headClick {
self.headBtn.transform = CGAffineTransformIdentity;
}
- (IBAction)scale:(UIButton *)sender {
CGAffineTransform transform = self.headBtn.transform;
switch (sender.tag) {
case 5: // 放大
transform = CGAffineTransformScale(transform, 1.2, 1.2);
break;
case 6: // 缩小
transform = CGAffineTransformScale(transform, .8, .8);
break;
}
self.headBtn.transform = transform;
}
- (IBAction)rotate:(UIButton *)sender {
CGAffineTransform transform = self.headBtn.transform;
switch (sender.tag) {
case 7: // 左旋转
transform = CGAffineTransformRotate(transform, -M_PI_4);
break;
case 8: // 右旋转
transform = CGAffineTransformRotate(transform, M_PI_4);
break;
}
self.headBtn.transform = transform;
}
15:30旋转边走边转边转
命名规范.lable结尾
- (IBAction)move:(UIButton*)sender {//此处不能用id 用id没法实现
[UIView beginAnimations:nil context:nil];//必须一块儿使用
[UIView setAnimationDuration:3];//设置时间,没此行就是默认的时间
CGPoint temp=self.iconBtn.center;
switch (sender.tag) {
case 10:
temp.y-=60;
break;
case 20:
temp.y+=60;
break;
case 30:
temp.x-=60;
break;
case 40:
temp.x+=60;
break;
}
self.iconBtn.center=temp;
[UIView commitAnimations];//提交动画;
}
bounds的使用:
- (IBAction)small {
// 1.取出原有属性
// CGRect tempFrame = self.iconBtn.frame;
CGRect tempBounds = self.iconBtn.bounds;//和frame 的差很少
// 2.修改临时属性
tempBounds.size.width -= 50;
tempBounds.size.height -= 50;
// 3.覆盖原有属性
self.iconBtn.bounds = tempBounds;
}
center的使用;
- (IBAction)move:(UIButton *)sender {
// 1.取出原有属性
// CGRect tempFrame = self.iconBtn.frame;
// command + control + e
CGPoint tempCenter = self.iconBtn.center;
// 2.修改临时属性
// 偏移位
NSInteger offset = 150;
// 3.覆盖原有属性
// self.iconBtn.frame = tempFrame;
self.iconBtn.center = tempCenter;
}
7.监听按钮点击
--------------------------------------------------------------------------------
代码建立界面
----------------------------------------
// NJViewController.m
#import "NJViewController.h"
@interface NJViewController ()
@end
@implementation NJViewController
// 控制器的view加载完毕以后就会自动调用这个方法
- (void)viewDidLoad
{
[super viewDidLoad];
// 1.建立按钮
UIButton *btn = [[UIButton alloc] init];
// 3.设置按钮的frame
btn.frame = CGRectMake(100, 100, 100, 100);
btn.backgroundColor = [UIColor redColor];
// 4.设置背景图片
// 4.1建立图片(若是图片是png格式能够省略扩展名)
UIImage *image = [UIImage imageNamed:@"btn_01"];
// 4.2设置默认状态背景图片
[btn setBackgroundImage:image forState:UIControlStateNormal];
UIImage *imageHigh = [UIImage imageNamed:@"btn_02"];
[btn setBackgroundImage:imageHigh forState:UIControlStateHighlighted];
// 5.设置文字
[btn setTitle:@"摸我啊" forState:UIControlStateNormal];
[btn setTitle:@"摸你妹" forState:UIControlStateHighlighted];
// 6.设置文字颜色
[btn setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
[btn setTitleColor:[UIColor blueColor] forState:UIControlStateHighlighted];
// 7.监听按钮点击
/*
addTarget: 哪一个对象来监听事件就把这个添加给谁
action:事件发生后调用什么方法
forControlEvents:事件类型
sel中的方法,若是是监听的btn 就会将btn当作参数传进去
*/
此处是懒加载,
SEL sel = @selector(btnOnClick);
[btn addTarget:self action:sel forControlEvents:UIControlEventTouchUpInside];
// 2.添加按钮到view上
[self.view addSubview:btn];
// 建立添加按钮
// 建立系统提供类型的按钮不用设置位置和大小
UIButton *btn2 = [UIButton buttonWithType:UIButtonTypeContactAdd];
// 添加到view
[self.view addSubview:btn2];
}
- (void)btnOnClick
{
NSLog(@"btnOnClick");
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
--------------------------------------------------------------------------------
//公共使用的常量提出来 设一个变量赋值;
self.previousBtn.enabled=(self.index=0 ? NO :YES);//不行
self.previousBtn.enabled=(0==self.index ? NO :YES);//不行
NSString*fileName=[NSString stringWithFormat:@"drink_%02d.jpg",i];
UIImage*image=[UIImage imageWithContentsOfFile:@"fileName"];无缓存储的
NSLog(@"%@ \n",fileName);
UIImage*image=[UIImage image:@"fileName"];有缓存 占用空间大;
覆盖,view里面的东西有讯息,,storyboard,里面有顺序,会覆盖.不可能把button加到UIimageView里面,
/** */
//
#pragma
0419计划安排:
1.先看今天的代码整理下笔记,;
2.不懂的看下视屏幕,
3.重点代码敲一下,本身重复作老实讲的项目
4.看下昨天的代码:真理下笔记;
5.预习下后天,老后天上课的内容!
//== =之间的使用:必须0==index?:no,yes 不要 index=0?no,yes
字典:保存数据, 经过键取
数据模型:保存数据
// 专门用来保存数据的对象称之为数据模型
// 数据模型就是继承NSObject的一个类
*/
4.1建立模型对象
/*
NJApp *app = [[NJApp alloc] init];
app.name = dict[@"name"];
app.icon = dict[@"icon"];
*/
NJApp *app = [[NJApp alloc] initWithDict:dict];
应用管理封装本身敲中uiLABle 里还有UIview objes中
应用管理封装2,李明杰:封装是怎么样的过程;
//桃木猫
#pragma mark - 喝奶点击事件
- (IBAction)drink {
/*
// self.tomImageView.image = [UIImage imageNamed:@"drink_00.jpg"];
// 0判断是否正在执行动画
if ([self.tomImageView isAnimating]) {
return;
}
// 1.建立图片对象
// 1.1定义数组保存图片对象
NSMutableArray *images = [NSMutableArray array];
for (int i = 0; i <= 80; i++) {
// 1.2获取图片名称
NSString *fileName = [NSString stringWithFormat:@"drink_%02d.jpg", i];
// NSLog(@"%@", fileName);
// 1.3经过图片名称建立图片对象
UIImage *image = [UIImage imageNamed:fileName];
// 1.4添加图片对象到数组
[images addObject:image];
}
// UIImage *image = [UIImage imageNamed:@""]
// 2.赋值图片数组给UIImageViwe
self.tomImageView.animationImages = images;
// 4.设置动画重复次数
self.tomImageView.animationRepeatCount = 1;
// 5.设置动画时间
self.tomImageView.animationDuration = images.count * 0.05;
// 3.启动动画4
[self.tomImageView startAnimating];
*/
[self runAnimationWithFileCount:80 andFileName:@"drink"];
}
- (IBAction)knock {
[self runAnimationWithFileCount:80 andFileName:@"knockout"];
}
- (IBAction)leftFoot:(id)sender {
[self runAnimationWithFileCount:29 andFileName:@"footLeft"];
}
#pragma mark - 播放动画
- (void)runAnimationWithFileCount:(NSInteger)count andFileName:(NSString *)name
{
// 0判断是否正在执行动画
if ([self.tomImageView isAnimating]) {
return;
}
// 1.建立图片对象
// 1.1定义数组保存图片对象
NSMutableArray *images = [NSMutableArray array];
for (int i = 0; i <= count; i++) {
// 1.2获取图片名称
NSString *fileName = [NSString stringWithFormat:@"%@_%02d.jpg", name, i];
// NSLog(@"%@", fileName);
// 1.3经过图片名称建立图片对象
// 图片对象被覆盖后没有释放的缘由:
// imageNamed: 自动缓存
// UIImage *image = [UIImage imageNamed:fileName];
// imageWithContentsOfFile: 没有缓存
// OfFile: 全路径
// 获取最主要的资源包
NSBundle *bundle = [NSBundle mainBundle];
// 获取图片的全路径
NSString *fullPath = [bundle pathForResource:fileName ofType:nil];
UIImage *image = [UIImage imageWithContentsOfFile:fullPath];
// 1.4添加图片对象到数组
[images addObject:image];
}
// UIImage *image = [UIImage imageNamed:@""]
// 2.赋值图片数组给UIImageViwe
self.tomImageView.animationImages = images;
// 4.设置动画重复次数
self.tomImageView.animationRepeatCount = 1;
// 5.设置动画时间
// 动画持续时间
CGFloat delay = images.count * 0.05;
self.tomImageView.animationDuration = delay;
// 3.启动动画
[self.tomImageView startAnimating];
// self.tomImageView.animationImages = nil;
/*
SEL: 要执行的方法
withObject:调用方法的时候传递的参数
afterDelay:多少秒后执行
谁调用performSelector方法就会在afterDelay秒后执行谁的SEL方法而且传递一个withObject参数
*/
三秒以后文件中的对象执行clearCache:方法,传递的参数为nil
// [self performSelector:@selector(clearCache:) withObject:nil afterDelay:3];
//self.tomImageView这个属性 在延时以后执行setAnimationImages:这个方法,传递一个nil给他;
setAnimationImages:是系统自动生成的;
[self.tomImageView performSelector:@selector(setAnimationImages:) withObject:nil afterDelay:delay + 1];
}
#pragma mark - 清空数组
- (void)clearCache:(NSString *)str
{
// NSLog(@"clearCache = %@", str);
self.tomImageView.animationImages = nil;
// [self.tomImageView setAnimationImages:nil];
}
@end
0418笔记
// 谁触发事件就会把谁看成参数传递过来
// 参数的做用:区分按钮
//- (IBAction)login:(UIButton *)sender {
// NSLog(@"%@", sender);
//}
if (_imageData == nil) {
// arrayWithContentsOfFile接收的不是文件名称,而是文件的全路径
// abc.txt
// /user/apple/desktop/abc.txt
// OfFile:都是要求传入全路径
// NSBundle : 表明一个文件夹
// mainBundle: 程序的主要资源文件夹
// /Users/apple/Library/Application Support/iPhone Simulator/7.1/Applications/5134E673-89EA-4D2B-AAC1-097594A7C8D9/06-图片浏览器.app
// 之后在开发中,建立plist文件必定不要命名为info.plist
NSBundle *bundle = [NSBundle mainBundle];
NSString *fullPath = [bundle pathForResource:@"imageData" ofType:@"plist"];
_imageData = [NSArray arrayWithContentsOfFile:fullPath];
}
//老师作传智猜图:如何构思的?如何思考的??
图片浏览器的思路??(100字 ):
1>设置属性,
2>监听按钮;
3>按钮被点击的时候:响应函数里 经过属性将相关的序号,图片,说明输出到,设置的属性里;
汤姆猫??:
1>监听按钮,设置UIView的属性,接受动画
2>设置数组,循环接受动画,使用for循环,
3>接受到的数组图片,使用系统的动画函数,播放动画;
九宫格思路:
??
猜图思路:
固定的用story,动态的用代码
@2x.png,.png同一张
view只是展现图片,效率高
button点击和展现;
修改工程名称;
inset设置内边距
disable just image
preferredStatusBarStyle 一敲就有继承的系统就有
枚举:枚举开头,
button不可用:enable=NO;
有dictionary 转化为模型
if (self=[super init]) 首先调用[super init],调用父类的初始化方法,初始化之后,再返回一个
调用这个方法的对象的地址,赋值是为了return self,return [super init];验证,
MJQuestion*question=self.question[self.index];
btn下一题能够连线两次,属性和action 一个响应点击,一个获取这个按钮的属性;
cover.alpha=0.0;
设置透明:1.彻底透明
self.view 表明控制器的view, self.answerBtn.frame.Size
把控制view 的btn子视图带到控制器view最前面
[self.view bringSubviewToFront:self.iconBtn];
autolayout,勾选,btn控件就不能改变大小
autosize subviews 勾选 子控件的大小随父控件的大小变化
两个连线
view
属性中不要用,用NSMutableArray避免外面修改
UI调用set方法通常的都是set开头, 调用get方法,直接敲
一个按钮能够拖多跟线,一个属性,一个响应;
cover.frame=self.view.frame;
建父控件的时候为何是 view,view最纯洁什么都不干;也能够用其余的控件装子控件;
UITableView 继承UIScrollView,把一个东西拖到里面就能够滚;
viewDidLoad 程序启动就会
setv
字典转模型一行是四行;
属性名和 字典的key必须和模型的属性名如出一辙;
取出每一个字典的值赋值给属性名变量
id 类型是指针 不恩能是22;
@22 把22包装为指针;
@22 kvc会解析这个;
@"22" 会自动装换类型;
kvc字典转模型
取值 赋值
模型转字典
iPad iPhone 名字不能错
forkeypath 属性 的属性,属性,赋值
setValue:只能给属性赋值;
forkey少用 用forkeypath
kvc的,装换,性能不是很高;
kvc经过字符串类型的键赋值,可能写错,编译时不会写错,运行的时候会报错;
kvo 键值监听
须要用self是用全局,的变量, 不须要用self 的是局部的变量;
重写构造方法:if(self=[superinit])
调用父类的构造方法,返回一个子类的对象;
view比较纯洁的view 能够容纳其余的控件;
imageView 放在scrollview的子控件能够拖:须要告诉滚动范围;代码才能实现滚动的范围;
不能滚动;
1>没设置滚动范围
2>scrollenabe=no;
3>imageView的自动布局要去掉,不然没法拖动
4>userInterfaction;
viewDidLoad表明方法已经加载程序启动
self.scrollView.contentInset=UIedgeInsetMake: UIedgeInset是结构体在 设置的时候直接
把结构体的名称加一个make 就行;
scrollView
scrollinset:设置滚动的外边距;
inset在button中设置内边距;
图:
conetntSize的x值是相对与内容的内边距来算的,不是以inset的边距来算的;
CGrectMak
传智电台:
1>分三部分:上中下:
pt 点坐标:五个按钮:
scollview的协议以scollview为开头
14:45??三种设置滚动范围;
代理的应用场景:用途必背:
监听思想:A(viewController)对象想监听B对象,就将A(viewController)对象设为B对象的代理;
通知思想:A(viewController)对象想通知B对象,就将A(viewController)对象设为B对象的代理;
15:22代理大白话思想重看
分页原理:自动更具scrollView的宽度分页,须要设置参数;
nstimer只能放在主线程中,viewDidLoad中是主线程;
for (NSDictionary *dict in dictArray) {
NJQuestion *question = [NJQuestion questionWithDict:dict];
[models addObject:question];
}
遍历dictArray中的每一个数组元素,再将每一个元素转化为模型,将转化后的没个模型放在models中;
若是UIScrollView没法滚动,多是如下缘由:
1>没有设置contentSize
2>scrollEnabled = NO
3>没有接收到触摸事件:userInteractionEnabled = NO
4>没有取消autolayout功能(要想scrollView滚动,必须取消autolayout)
@property(nonatomic) CGPoint contentOffset;(.外面的因此off set 远离设置的范围)
这个属性用来表示UIScrollView滚动的位置
@property(nonatomic) CGSize contentSize;(size )
这个属性用来表示UIScrollView内容的尺寸,滚动范围(能滚多远)
@property(nonatomic) UIEdgeInsets contentInset; (inset 设置外边距)
这个属性可以在UIScrollView的4周增长额外的滚动区域
@property(nonatomic) BOOL bounces;
设置UIScrollView是否须要弹簧效果
@property(nonatomic,getter=isScrollEnabled) BOOL scrollEnabled;
设置UIScrollView是否能滚动
@property(nonatomic) BOOL showsHorizontalScrollIndicator;
是否显示水平滚动条
@property(nonatomic) BOOL showsVerticalScrollIndicator;
是否显示垂直滚动条
开始拖拽时调用 :scrollViewWillBeginDragging
具体滚动到某个位置时,调用scrollViewDidScroll:方法 DidScroll已经滚到
用户中止拖拽时,
调用scrollViewDidEndDragging:willDecelerate:方法
设置UIScrollView的id<UISCrollViewDelegate> delegate代理对象
设置minimumZoomScale :缩小的最小比例
设置maximumZoomScale :放大的最大比例
让代理对象实现下面的方法,返回须要缩放的视图控件
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView;
跟缩放相关的其余代理方法
开始缩放的时候调用
- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view
正在缩放的时候调用
- (void)scrollViewDidZoom:(UIScrollView *)scrollView
只要将UIScrollView的pageEnabled属性设置为YES,UIScrollView会被分割成多个独立页面,里面的内容就能进行分页展现
通常会配合UIPageControl加强分页效果,UIPageControl经常使用属性以下
一共有多少页
@property(nonatomic) NSInteger numberOfPages;
当前显示的页码
@property(nonatomic) NSInteger currentPage;
只有一页时,是否须要隐藏页码指示器
@property(nonatomic) BOOL hidesForSinglePage;
其余页码指示器的颜色
@property(nonatomic,retain) UIColor *pageIndicatorTintColor;
当前页码指示器的颜色
@property(nonatomic,retain) UIColor *currentPageIndicatorTintColor;
NSTimer叫作“定时器”,它的做用以下
在指定的时间执行指定的任务
每隔一段时间执行指定的任务
调用下面的方法就会开启一个定时任务
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget
selector:(SEL)aSelector
userInfo:(id)userInfo
repeats:(BOOL)yesOrNo;
每隔ti秒,调用一次aTarget的aSelector方法,yesOrNo决定了是否重复执行这个任务
经过invalidate方法能够中止定时器的工做,一旦定时器被中止了,就不能再次执行任务。只能再建立一个新的定时器才能执行新的任务
- (void)invalidate;
注意点:字典中的key必须和模型的属性名称如出一辙 才能使用KVC方法;
注意:不要滥用kvc
由于kvc要把字符串类型的属性名称和值转换后才能赋值,因此性能不是很高
还有一点,由于kvc是经过字符串类型的键去查找对应的属性进行赋值,因此有可能写错,可是写错后在编译时不会报错, 只会在运行时报错
应用场景:
经常使用于字典和模型的相互转换
*/
- (instancetype)initWithDict:(NSDictionary *)dict
{
if (self = [super init]) {
之前的字典转模型;
/*
self.answer = dict[@"answer"];
self.icon = dict[@"icon"];
self.title = dict[@"title"];
self.options = dict[@"options"];
*/
// KVC能够经过一个字符串的key给属性赋值
// 取出dict字典中key为@"answer"的值 ,赋值给self的名字叫作answer的属性
/*
[self setValue:dict[@"answer"] forKeyPath:@"answer"];
[self setValue:dict[@"icon"] forKeyPath:@"icon"];
[self setValue:dict[@"title"] forKeyPath:@"title"];
[self setValue:dict[@"options"] forKeyPath:@"options"];
*/
// 注意点:字典中的key必须和模型的属性名称如出一辙
使用KVC后一行代码搞定,KVC 本身会转化为响应的代码;
[self setValuesForKeysWithDictionary:dict];
[self setValue:dict[@"an"] forKeyPath:@"an"];
*/
}
return self;
}
KVC
// 能够给p对象的属性的属性赋值
[p setValue:@"mini" forKeyPath:@"iPad.model"];
// 只能给p对象的属性赋值
// [p setValue:@"mini" forKey:@"iPad.model"];
[super viewDidLoad];
CGFloat lastY=self.lastBtn.frame.origin.y+self.lastBtn.frame.size.height+10;
//移动的距离
self.scrollView.contentSize= CGSizeMake (0, lastY);
//移动上下的边缘
//离上下的间距,不会回缩.上下有工具条
self.scrollView.contentInset=UIEdgeInsetsMake(44, 0, 64, 0);
更改电台出来初始位置,下移;
// 1.取出原来的值
CGPoint tempOffset = self.scrollView.contentOffset;
// 2.修改之前的位置
/tempOffset.y = -40;
// 3.覆盖之前的offset
self.scrollView.contentOffset = tempOffset;
传智电台组成:
1>上面的view条320*45;
2>中间的scrollView 滑动
3>最下面的view条 320*60;
- (void)viewDidLoad
{
[super viewDidLoad];
// 设置滚动范围
self.scrollview.contentSize = self.imageView.image.size;
// 1.设置代理对象
self.scrollview.delegate = self;
//---------------------------------------------
UIScrollView中 声明了协议: @protocol UIScrollViewDelegate;
,UIScrollView的属性delegaet遵照UIScrollViewDelegate这个协议(以下所示);
@property(nonatomic,assign) id<UIScrollViewDelegate>delegate;
将控制器对象传给delegate,delegate和控制器对象指同一对象,在控制器中实现协议中的方法
,那么scrollview就可使用控制器实现的方法完成必定的功能,UIScrollView的属性delegate
和控制器指向同一地址,控制器实现了,就至关于本身实现了同样,直接使用;
//---------------------------------------------
/*
代理应用场景:
1. 监听思想:当A对象想监听B对象的变化的时候,就可让A对象成为B对象的代理
2. 通知思想:当B对象发生了变化的时候想通知A对象,就可让A对象成为B对象的代理
*/
// 设置缩放的最小和最大比例
self.scrollview.minimumZoomScale = 0.2f;
self.scrollview.maximumZoomScale = 2.0f;
}
// 3.实现协议中的方法
// 开始缩放的时候调用, 要求返回scrollview中须要缩放的控件
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
NSLog(@"开始缩放");
return self.imageView;
}
缩放过程当中调用
- (void)scrollViewDidZoom:(UIScrollView *)scrollView
//{
// NSLog(@"正在缩放");
//}
/**
* 缩放结束时调用
*
* @param scrollView 当前的scrollview
* @param view 被缩放的view
* @param scale 缩放的比例
*/
//- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale
//{
// NSLog(@"缩放结束");
// NSLog(@"view = %@, scale = %.1f", view, scale);
//}
UITableView须要一个数据源(dataSource)来显示数据
UITableView会向数据源查询一共有多少行数据以及每一行显示什么数据等
没有设置数据源的UITableView只是个空壳
凡是遵照UITableViewDataSource协议的OC对象,均可以是UITableView的数据源
调用数据源的下面方法得知一共有多少组数据
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
调用数据源的下面方法得知每一组有多少行数据
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
调用数据源的下面方法得知每一行显示什么内容
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
UITableView的每一行都是一个UITableViewCell,经过dataSource的tableView:cellForRowAtIndexPath:方法来初始化每一行
UITableViewCell内部有个默认的子视图:contentView,contentView是UITableViewCell所显示内容的父视图,可显示一些辅助指示视图
辅助指示视图的做用是显示一个表示动做的图标,能够经过设置UITableViewCell的accessoryType来显示,默认是UITableViewCellAccessoryNone(不显示辅助指示视图),其余值以下:
UITableViewCellAccessoryDisclosureIndicator
UITableViewCellAccessoryDetailDisclosureButton
UITableViewCellAccessoryCheckmark
还能够经过cell的accessoryView属性来自定义辅助指示视图(好比往右边放一个开关)
@protocol UITableViewDataSource<NSObject>
@required
2>每组多少行
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
3>每组每行显示什么内容
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
@optional
1>有多少组
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView; // Default is 1 if not implemented
4>设置头部标题
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section; // fixed font style. use custom view (UILabel) if you want something different
5>设置尾部标题
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section;
// Editing
// Individual rows can opt out of having the -editing property set for them. If not implemented, all rows are assumed to be editable.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath;
// Moving/reordering
// Allows the reorder accessory view to optionally be shown for a particular row. By default, the reorder control will be shown only if the datasource implements -tableView:moveRowAtIndexPath:toIndexPath:
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath;
// Index
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView; // return list of section titles to display in section index view (e.g. "ABCD...Z#")
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index; // tell table which section corresponds to section title/index (e.g. "B",1))
// Data manipulation - insert and delete support
// After a row has the minus or plus button invoked (based on the UITableViewCellEditingStyle for the cell), the dataSource must commit the change
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath;
// Data manipulation - reorder / moving support
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath;
@end
禁止用户交互:使按钮不能点:
//英雄展现设计思路:
0>搭接面,拖属性,加plist文件
1>建模新,属性:name.icon,intro
2>模型初始化
3>重写get写函数将字典数组里的数据转化为模型
3.1>字典转模型函数:
3.2>两种方法
4>只有一组
5>有一共有多少行:
6>设置cell中的数据:
6.1>取模型数据
6.2>根据模型数据设置cell的值:
7>设置行高
//团购界面思路
1>界面搭建:添加一个tableView,plist文件,图片
2>创建xib文件:由于团购网站的样式同样 能够复用,而微博是不能够复用的
3>创建管理xib的类:为了保证封装性,不用viewWithtag的方式拿到xib中的子控件,创建管理xib的类,设置属性
并拖线来,管理xib中的属性; Table View Cell,xib,xib管理类三者的名字同样;
4> 为了加载plist文件创建模型
5>为了将控制器设置为代理须要拖线,将数据源和控制器拖线创建联系
6> 1) 设置每一行cell的高度,
2)隐藏状态栏,
3)数据的懒加载,加载plist
4)数据源方法
5)一共有多少行数据
6)每一行显示怎样的cell---建立cell 给cell传递模型
不能拖线,不能更名字,团购网站本身敲://是由于管理xib的类不是继承与xib中的默认类,没创建联系;
story归controller管
xib 归响应的类管,不必定添加到controller
lable.center=CGPointMake(160, 240);//位置center易算
lable.backgroundColor=[UIColor redColor];
[self.superview addSubview:lable]; /找父控件
09:41主图层??
lable.layer.masksToBounds=YES;//子头层是否剪切到母涂层的大小,边缘一致;
0943
??什么意思?0945
lable.layer.cornerRadius=10;//两个配合使用
lable.layer.masksToBounds=YES;//设置子图层的边角,剪边角,边角变圆
lable.clipsToBounds=YES;
代码里面父子关系不稳定
custom 的下面修改xib名字的tg,xib的名字不能改,继承关系错了
展现表格使用tableView,要展现数据须要数据源;遵照数据源协议
数据源方法什么过后调用? 数据源显示以前调用
1204两种设置行高的方法;row.height,相同的行高设置的方法,不一样的行高
static 局部变量只开辟一次存储空间
xib封装的读取与赋值的过程:-------------------------------1)xib转化为appview 类
1>调用appView方法从xib中加载局部界面
NJAppView *appView = [NJAppView appView];
appView.delegate = self;// 设置控制器为appview的代理
+ (instancetype)appView
{
// 获取最主要的资源文件夹
NSBundle *bundle = [NSBundle mainBundle];
// nib == xib
// 读取xib中的文件(会建立xib中描述的全部对象,而且按照顺序放到数组中)
NSArray *objcts = [bundle loadNibNamed:@"NJAppView" owner:nil options:nil];
// UIView *appView = objcts[0];
NJAppView *appView = [objcts lastObject];
// NJAppView xib中是什么类型,objcts就是什么类型
return appView;//NJAppView继承UIView
}
2>.设置数据:.apps方法将字典中的字典转化模型放在数组中存储起来, --------2)取出每个模型数据
//取出模型数组中的每个模型数据:
NJApp *appInfo = self.apps[i];
- (NSArray *)apps
{
if (_apps == nil) { // 未初始化
// 1.获取最主要资源包
NSBundle *bundle = [NSBundle mainBundle];
// 2.获取plist全路径
NSString *fullPath = [bundle pathForResource:@"app" ofType:@"plist"];
// 3.加载应用信息
NSArray *dictArray = [NSArray arrayWithContentsOfFile:fullPath];
// 4.字典转模型
NSMutableArray *models = [NSMutableArray arrayWithCapacity:dictArray.count];
for (NSDictionary *dict in dictArray) {
// 4.1建立模型对象
NJApp *app = [NJApp appWithDict:dict];
// 4.2将模型对象存储到数组中
[models addObject:app];
}
_apps = models;
}
return _apps;
}
3>.appInfo的get方法将 上一步中取得的模型数据,赋给xib中的nameLable和iconImageView中的模块
appView.appInfo = appInfo;-------------------3)将模型数据赋给appview 类的属性
- (void)setAppInfo:(NJApp *)appInfo
{
// 固定写法
_appInfo = appInfo;
// 设置头像
self.iconImageView.image = [UIImage imageNamed:_appInfo.icon];
// 设置名称
self.nameLabel.text = _appInfo.name;
}
//方法在NJappVIew中只有NJAppView的对象才能调用
- (IBAction)downloadClick {
// NSLog(@"点击了下载");
self.download.enabled = NO;
// self表明NJAppView,通知代理我被点击了,同时把NJAppView传给控制器是
[self.delegate appViewClickBtn:self];
}
1>xib中的一个按钮被点击了;
2>xib中被点击的按钮(downLaod)进行连线,只有连线了才能够监听这个按钮;
3>被点击的事件,xib的管理类MJAPPView最清楚本身的子控件被点击,保证封装,将点击事件通知代理:
通知控制器,
4>控制器收到被点击的事件后,在控制器上加弹框:
[self.view addSubview:label];
执行动画:透明从0.0--0.6花一秒钟的时间,通过0.5秒后,动画消失,消失时间持续1秒钟;
[UIView animateWithDuration:1 animations:^{
label.alpha = 0.6;
} completion:^(BOOL finished) {
[UIView animateWithDuration:1 delay:0.5 options:UIViewAnimationOptionCurveLinear animations:^{
label.alpha = 0.0;
} completion:^(BOOL finished) {
[label removeFromSuperview];
}];
}];
@interface MJTgCell : UITableViewCell//要继承系统的UITableViewCell作一个扩展;
xib转换为代码:
自定义的至关于MJTgCell这个类;
开发中字符串展现int 方便显示;
当系统的cell没法知足需求的时候,就须要自定义cell,在系统自带的cell上作一些加强;
自定义cell
1>xib固定的界面
2>纯代码(界面不固定,微博)
tableview cell 子空间contentView(必须放在这里面),专门tableview cell
定义一个类管理一个xib文件
1>xib与管理类名称相同
2>管理类是xib的class类的根类:
继承:在继承的基础上既要知足要求,又要扩张一些功能,因此我要继承与他,
hidden 成对出现,30分钟:
团购网站思路:
1>数据懒加载
2>设置行高,设置状态栏
3>每一行显示怎么样的cell:
调用:
建立cell,在建立的时候没传入一个tableView对象就返回一个cell
建立cell,先从缓存池中出,不为空建立.
4>给cell传模型数据
get 方法懒加载,得到模型数组,set方法将传入的模型,写入cell的各个属性;
5>
+ (instancetype)headerView
{
return [[[NSBundle mainBundle] loadNibNamed:@"NJHeaderView" owner:nil options:nil] lastObject];
}
// 经过xib建立的view不会调用这个方法,只有经过代码建立的时候才会调用这个方法
//- (id)init{}
// 经过xib建立view的时候会调用下列方法
- (void)awakeFromNib
{
NSLog(@"醒了");
// 拿到scrollview设置图片
}
控件的命名规则?
// 控件协议名称以控件名称 + Delegate
@protocol NJFooterViewDelegate <NSObject>
对象A内部发生了一些事情,想通知对象B
对象B想监听对象A内部发生了什么事情
对象A想在本身的方法内部调用对象B的某个方法,而且对象A不能对对象B有耦合依赖
对象A想传递数据给对象B
以上状况,结果都同样:对象B是对象A的代理(delegate)
先搞清楚谁是谁的代理(delegate)
定义代理协议,协议名称的命名规范:控件类名 + Delegate
定义代理方法
代理方法通常都定义为@optional
代理方法名都以控件名开头
代理方法至少有1个参数,将控件自己传递出去
设置代理(delegate)对象 (好比myView.delegate = xxxx;)
代理对象遵照协议
代理对象实现协议里面该实现的方法
在恰当的时刻调用代理对象(delegate)的代理方法,通知代理发生了什么事情
(在调用以前判断代理是否实现了该代理方法)
好友列表和微博思路:0425
1>viewDidLoad
2>prefersStatusBarHidden
A>//懒加载plist-数组-(字典转message模型,message模型set进入messageFrame模型,messageFrame模型组合成数组)
3> 数据源方法 ,使用懒加载返回frame模型的个数;决定行数
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.messageFrames.count;
}
4>-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 1.建立cell,传入tableview就能够将子控件建立和初始化;
MJMessageCell *cell = [MJMessageCell cellWithTableView:tableView];
// 2.使用懒加载get方法给建立和初始化的cell传递模型
//根据传入的模型设置:时间,头像和正文,以及frame属性 在cell使用setMessageFrame方法中设置,无返回值
cell.messageFrame = self.messageFrames[indexPath.row];
// 3.返回设置号头像和正文时间的cell
return cell;
}
5>- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{ //调用懒加载的方法给frame模型对象传递单个messageFrames模型
MJMessageFrame *mf = self.messageFrames[indexPath.row];
//根据传入的模型数据,get得到MJMessageFrame对象中set的cellHeight属性;此属性在色调方法中根据字数来设定;
return mf.cellHeight;
}
@end
0427:qq聊天布局的结构:
storyBorad:tableView 和文本输入框背景图片,三个按钮
QQ好友事项方法:
一:
定义分类(两组,扩充两个方法):
分类是在已有类的基础上扩展一些新的类,增长了得到能够随意拉伸不变形的图片
返回:能够随意拉伸不变形的图片,返回字符串所占用的尺寸
定义方法:
@interface NSString (Extension)
- (CGSize)sizeWithFont:(UIFont *)font maxSize:(CGSize)maxSize;
@end
定义: MJMessageCell类 继承自UITableViewCell
方法:
cellWithTableView cell的建立<缓存池>
initWithStyle: 对建立的cell初步初始化:设下图像正文的格式,字体,里面无准确的内容
setMessageFrame: 传入一个MessageFrame,MessageFrame中有message属性,经过get
message属性的方法得到message的模型(无frame)
二
MJMessage类中
属性:聊天内容
发送时间
信息的类型
是否隐藏时间
方法:传入字典就能够返回一个模型
messageWithDict:(NSDictionary *)dict
- (instancetype)initWithDict:(NSDictionary *)dict
MJMessageFrame类中
属性:头像的frame,时间的frame,正文的frame ,cell的高度,单个初级数据模型message
方法:- (void)setMessage:(MJMessage *)message
传入message(单个模型数据)能够计算:
1.时间 _timeF
2.头像 _iconF
3.正文 _textF
4.cell的高度 cellheight
三
控制器中有@interface MJViewController () <UITableViewDataSource, UITableViewDelegate, UITableViewDelegate, UITextFieldDelegate>
数据源方法和代理;
属性: ;NSDictionary *autoreply; NSMutableArray *messageFrames;
UITableView *tableView; 拖线-设置代理,通知代理作事
UITextField *inputView; 拖线-设置代理,通知代理作事
viewDidLoad:
1.表格的设置
去除分割线
2.监听键盘的通知
3.设置文本框左边显示的view
永远显示
懒加载:得到模型数据,将模型数据和数据的frame(内部新增长一些属性,在setMessage中设置)包装成:messageFrames,
数据源方法:1>建立,初始化,填数据,返回cellHeight;
autoreply:自动播放方法,返回的数组(plist转化而来);
发送一条消息:
- (void)addMessage:(NSString *)text发送的文本 type:(MJMessageType)type(发送的类型);
1.数据模型
设置数据模型的时间
看是否须要隐藏时间
2.frame模型
建立mf对象
MJMessageFrame *mf = [[MJMessageFrame alloc] init];
//对象中添加单个模型数据
mf.message = msg;
//含有单个模型数据和相关扩充功能的mf对象加到数组中;
[self.messageFrames addObject:mf];
// 3.刷新表格
[self.tableView reloadData];
// 4.自动滚动表格到最后一行
* 根据本身发的内容取得自动回复的内容
本身发的内容
- (NSString *)replayWithText:(NSString *)text
#pragma mark - 文本框代理
/**
* 点击了return按钮(键盘最右下角的按钮)就会调用
*/
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
// 1.本身发一条消息
// 2.自动回复一条消息
// 3.清空文字
// 返回YES便可
}
/**
* 当键盘改变了frame(位置和尺寸)的时候调用
*/
- (void)keyboardWillChangeFrame:(NSNotification *)note
{ // 设置窗口的颜色
// 0.取出键盘动画的时间
// 1.取得键盘最后的frame
// 2.计算控制器的view须要平移的距离
// 3.执行动画
}];
}
控制器中的新方法代码:
- (void)viewDidLoad
{
[super viewDidLoad];
// 1.表格的设置
// 去除分割线
self.tableView.backgroundColor = [UIColor colorWithRed:235/255.0 green:235/255.0 blue:235/255.0 alpha:1.0];
self.tableView.allowsSelection = NO; // 不容许选中
self.tableView.delegate = self;
// 2.监听键盘的通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil];
// 3.设置文本框左边显示的view
self.inputView.leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 8, 0)];
// 永远显示
self.inputView.leftViewMode = UITextFieldViewModeAlways;
self.inputView.delegate = self;
}
做用:
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
数据源方法:
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
// 退出键盘
[self.view endEditing:YES];
}
>-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath//建立cell初步初始化--
代理方法:- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
MJMessageFrame *mf = self.messageFrames[indexPath.row];
return mf.cellHeight;
}
/**
* 当开始拖拽表格的时候就会调用
*/
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
// 退出键盘
- (void)addMessage:(NSString *)text type:(MJMessageType)type
// 1.数据模型
MJMessage *msg = [[MJMessage alloc] init];
msg.type = type;
msg.text = text;
// 设置数据模型的时间
NSDate *now = [NSDate date];
NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
fmt.dateFormat = @"HH:mm";
// NSDate ---> NSString
// NSString ---> NSDate
// fmt.dateFormat = @"yyyy-MM-dd HH:mm:ss";
// 2014-08-09 15:45:56
// 09/08/2014 15:45:56
msg.time = [fmt stringFromDate:now];
// 看是否须要隐藏时间
MJMessageFrame *lastMf = [self.messageFrames lastObject];
MJMessage *lastMsg = lastMf.message;
msg.hideTime = [msg.time isEqualToString:lastMsg.time];
_messageFrame = messageFrame;
//取得message模型
MJMessage *message =self.messageFrame.message;
self.messageFrame=也是右边传过来的:(上层代码)
0427:QQ列表
如何改textField 的圆角
答:label.alpha = 0.0;
// label 图层(主图层)
label.layer.cornerRadius = 10;
// 设置超出主图层的子图层的边界自动剪切掉
label.clipsToBounds = YES;
09:23注意点;
2>系统自带的cell特色?
默认的状态:一个图像,一个button.
有的状态:有lable, imageView,button
1> 搭接面运行;
2>一进来3.5村,
3>字典转模型
4>数据源方法:
保存数据的模型不须要继承;
09:36枚举的命名规范
1>懒加载
2>初步建立cell,初步初始化;
09:08不能用tableViewController?
若是直接使用tableViewController,自动连好了tableView的数据源和代理;
在QQ列表之类的:里面上半部分是tableView,下面是Button,因此不能用TableViewer;
下面须要加view保存按钮(三个图片按钮)
09:11技巧,修改坐标的技巧,本身领悟;
09:12(添加到xcode图片的地方)ios7的图片不出来,修改jason文档,在四个的里面添加名字;fileName
在storyBoard中,imageView不能在上面放控件;代码中能够建立图像上面添加控件;
imageView继承UIview能够添加控件
@2X的时候像素是68*68,在Xcode里面真实的是34*34(xcode);button里的图片:若是添加到image中
图片不会拉升,添加到background中,图片会拉伸;
0952若应用,用强引用引用着他
1>获取屏幕的宽度:
1041计算屏幕的最大宽度和高度?
去掉分割线:两种:seperate添加函数:
tableview上放有cell,tableView上放有不少cell;
让tableView的某一行不能选?
在tableView的storyBoard的selction(没法选,单选,多选);
让button里面的数据显示多行,改storyBoard,;改按钮的圆角:在button的borderstyle里面
biatton里有image和lable
如何设置button内边距? conetnInset
如何自动换行?numberoflines=0
拉伸函数?
ios五如何解决平铺;
拉伸的方法:
先放一个Button,Button里面有一个lable,lable里面放置 有文字,Button的背景加一个图片让图片的某一点拉升,拉伸函数有几种;
通知:发布者:名称接受者
15:46nil接受通知,表明谁均可以接受;监听通知,通知消失后,注册监听后,对象消失后,必定销毁监听;
note.info的做用?
能够打印出键盘的信息
NSLog(@"notoinfo = %@\n",note.info);
如何改键盘的return为send?
在storyBoard里面的修改returnKey,变为send
对于崩的程序,如何肯定在哪里崩了?
// 2.frame模型
//建立mf对象
MJMessageFrame *mf = [[MJMessageFrame alloc] init];
//对象中添加单个模型数据
mf.message = msg;
//含有单个模型数据和相关扩充功能的mf对象加到数组中;
[self.messageFrames addObject:mf];
// 3.刷新表格
[self.tableView reloadData];
// 4.自动滚动表格到最后一行
NSIndexPath *lastPath = [NSIndexPath indexPathForRow:self.messageFrames.count - 1 inSection:0];
[self.tableView scrollToRowAtIndexPath:lastPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
- (void)setMessageFrame:(MJMessageFrame *)messageFrame(右边传过来的)
单例模式:
在内存中只分配一次存储空间:不少对象能够一应用他;
readOnly 在一个.h文件中声明为只读(只有get方法,没有set方法)的在他的.m文件中是能够经过直接赋值的,不能使用set方法赋值.
如何设置:
条件断点:循环中让断点停在某个地方;处于某个特定的状态中止;
断点忽略-在断点处 edit breakpoint;
点击控制台:print description;
异常断点:在断点异常的左下角中,点+,选择:Symbolic Breakpont :在Symbol中输入:objc_exception_throw
po 对象不存在时打印为nil;
print打印基本的数据类型;
info symbol 0xffdd;
调试的时候:某一点有问题,查找某一点有关的全部代码,一个个的检查;
放在message.m中:
/**
* 根据文本计算文本占用的宽高
*
* @param str 要计算的文本
* @param font 文本的字体和大小
* @param maxSize 文本最大能占用的宽高
*/
CGSize textSize = [self sizeWithString:message.text font:NJTextFont maxSize:maxSize]; self表明messageFrame的对象;经过self调用;
//传入一个字符串,用一个对象调用
- (CGSize)sizeWithString:(NSString *)str font:(UIFont *)font maxSize:(CGSize)maxSize
{
NSDictionary *dict = @{NSFontAttributeName : font};
CGRect rect = [str boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:dict context:nil];
return rect.size;
}
/**
* 根据文本计算文本占用的宽高
*
* @param str 要计算的文本
* @param font 文本的字体和大小
* @param maxSize 文本最大能占用的宽高
*/直接使用message.text调用;
CGSize textSize = [message.text sizeWithFont:NJTextFont maxSize:maxSize];
- (CGSize)sizeWithFont:(UIFont *)font maxSize:(CGSize)maxSize
{
NSDictionary *dict = @{NSFontAttributeName : font};
CGRect rect = [self boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:dict context:nil];
return rect.size;
}
#pragma mark - 转换拉伸图片方法:留出1*1的空间被拉,也能够直接(h,w,h,w)留0.000001;
+ (UIImage *)resizableImage:(NSString *)name
{
// 建立一张图片
UIImage *image = [self imageNamed:name];
// 制做指定范围能够拉伸的图片
CGFloat w = image.size.width * 0.5;
CGFloat h = image.size.height * 0.5;
UIImage *resizeImage = [image resizableImageWithCapInsets:UIEdgeInsetsMake(h - 1, w - 1, h, w) resizingMode:UIImageResizingModeStretch];
return resizeImage;
}
根据文字宽高的计算公式计算出文字的size,size的宽高属性加上间距就能够得出button的宽高,也就是计算出文字的frame,
设置的背景和button是一块儿的,内部的文字和button有间距,button 的frame是根据文字的size来设置的;
:
button上有文字:设置button的宽高,在设置button内部,文字的
// 3.正文frame
CGFloat contentY = iconY;
// 计算文本宽高,宽度150;
CGSize maxSize = CGSizeMake(150, MAXFLOAT);
// 文本实际占用的宽高
// CGSize textSize = [self sizeWithString:message.text font:NJTextFont maxSize:maxSize];
CGSize textSize = [message.text sizeWithFont:NJTextFont maxSize:maxSize];
// 计算button的宽高
CGFloat contentW = textSize.width + NJEdgeInset * 2;
CGFloat contentH = textSize.height + NJEdgeInset * 2;
CGFloat contentX = 0;
if (NJMessageTypMe == message.type) {// 本身发
contentX = iconX - padding - contentW;
}else
{
contentX = CGRectGetMaxX(_iconF) + padding;
}
_contentF = CGRectMake(contentX, contentY, contentW, contentH);
- (void)setMessageFrame:(NJMessageFrame *)messageFrame
{
_messageFrame = messageFrame;
// [self settingData];
// [self settingFrame];
NJMessage *message = self.messageFrame.message;
// 1.设置时间
self.timeView.text = message.time;
self.timeView.frame = messageFrame.timeF;
// 2.设置头像
// 根据发送类型获取头像图片的名称
NSString *iconName = (NJMessageTypMe == message.type ? @"me" : @"other");
self.iconView.image = [UIImage imageNamed:iconName];
self.iconView.frame = messageFrame.iconF;
// 3.设置textView(即button)设置文字;
[self.textView setTitle:message.text forState:UIControlStateNormal];
//给textView设置frame,get和set方法
self.textView.frame = messageFrame.contentF;
// 设置背景图片
if (NJMessageTypMe == message.type) { // 本身发 蓝色
// 普通图片
//利用已封装好的方法给button设置一个只有中间1*1的地方能够拉伸的头像;
[self.textView setBackgroundImage:[UIImage resizableImage:@"chat_send_nor"] forState:UIControlStateNormal];
// 高亮图片
}else
{
// 白色图片
[self.textView setBackgroundImage:[UIImage resizableImage:@"chat_recive_nor"] forState:UIControlStateNormal];
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
// NSLog(@"send按钮被点击了 %@",textField.text);
// 1.添加模型数据
// 1.1建立数据模型
NJMessage*ms=[[NJMessage alloc]init];
ms.text=textField.text;
// 1.2根据数据模型建立frame模型
NJMessageFrame*mf=[[NJMessageFrame alloc]init];
// 1.3将frame模型添加到messageFrames中
mf.message=ms;
// [NJMessageFrame
// 2.刷新表格
[self.tableView reloadData];
return YES;
}
- (void)keyboardWillChange:(NSNotification *)note
{
// NSLog(@"键盘弹出了");
// 让输入框随着键盘移动就OK
// NSLog(@"%@", note.userInfo);
// 1. 取出键盘移动结束后的Y值
CGRect rect = [note.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
// 键盘弹出后的Y值
CGFloat keyboardY = rect.origin.y;
// 键盘的高度( 输入框要移动的距离)
CGFloat transformY = keyboardY - self.view.frame.size.height;
// NSLog(@"%.1f", transformY);
// 2.取出键盘弹出须要的时间
CGFloat duration = [note.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
// 3.修改输入框位置
[UIView animateWithDuration:duration animations:^{
self.inputView.transform = CGAffineTransformMakeTranslation(0, transformY);
}];
}
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
// NSLog(@"被拖拽了");
[self.view endEditing:YES];
}
{
[super viewDidLoad];
// 设置tableView的背景颜色
self.tableView.backgroundColor = [UIColor lightTextColor];
// 设置tableview不能选中
self.tableView.allowsSelection = NO;
// 注册监听键盘位置改变的通知
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
//注册通知的监听器,有UIKeyboardWillChangeFrameNotification事件时时,self是监听器
通知中心(NSNotificationCenter)提供了方法来注册一个监听通知的监听器(Observer)
- (void)addObserver:(id)observer selector:(SEL)aSelector name:(NSString *)aName object:(id)anObject;
/*observer:监听器,即谁要接收这个通知-----self
aSelector:收到通知后,回调监听器的这个方法,而且把通知对象当作参数传入keyboardWillChange:
aName:通知的名称。若是为nil,那么不管通知的名称是什么,监听器都能收到这个通知
anObject:通知发布者。若是为anObject和aName都为nil,监听器都收到全部的通知*/
[center addObserver:self(监听器) selector:@selector(keyboardWillChange:(回调的方法)) name:UIKeyboardWillChangeFrameNotification(通知的名称) object:nil(nil表明监听器能够收到全部的对象)];//
/*self 控制器对象*/
// 监听文本输入框召唤出来的键盘的发送按钮的点击
// 设置文本输入框代理
上述方法是键盘的,下面
self.inputTextField.delegate = self;设置代理作下面的事情;scroolView滚动时调用,滚动时让键盘结束编辑;
/* - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
// NSLog(@"被拖拽了");
[self.view endEditing:YES];
}*/
}
#pragma mark - 键盘位置发生改变时调用
- (void)keyboardWillChange:(NSNotification *)note
{
// NSLog(@"键盘弹出了");
// 让输入框随着键盘移动就OK
// NSLog(@"%@", note.userInfo);
// 1. 取出键盘移动结束后的Y值
CGRect rect = [note.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
// 键盘弹出后的Y值
CGFloat keyboardY = rect.origin.y;
// 键盘的高度( 输入框要移动的距离)
CGFloat transformY = keyboardY - self.view.frame.size.height;
// NSLog(@"%.1f", transformY);
// 2.取出键盘弹出须要的时间
CGFloat duration = [note.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
// 3.修改输入框位置
[UIView animateWithDuration:duration animations:^{
self.inputView.transform = CGAffineTransformMakeTranslation(0, transformY);
}];
}
某个控件出不来:
1.frame的尺寸和位置对不对
2.已经出来了,没显示正确的内容,赋值出错,误觉得没出来;
2.hidden是否为YES
3.有没有添加到父控件中
4.alpha 是否 < 0.01
5.被其余控件挡住了
6.父控件的前面5个状况
但凡init建立的控件frame都是0;1448?必须在layOutSubviews中设置frame,init里面不能设置frame;
layOutSubviews,必定要记住;
frame修改了会调用:-(void)layOutSubviews
.m文件中声明的弱引用的属性
@property (nonatomic, weak) UIImageView *iconView;
{
//在此处不能:self.timeView=[UILable alloc ]init] self.timeView中的timeView属性是weak的即若应用,在建立的
后就会释放,使用新建立的默认是强引用;
UILabel *timeView = [[UILabel alloc] init];
timeView.textAlignment = NSTextAlignmentCenter;
timeView.font = [UIFont systemFontOfSize:13];
[self.contentView addSubview:timeView];
self.timeView = timeView;//右边的timeView是强指针,左边的是弱指针,至关于有两个指针指着timeView,那么timeView就不会消失
}
0428:QQ好友列表;
老师的面试题?
如何解决移动(键盘和输入条)不一致:动做不一致;
使控制器(包含tableView和输入buttton)参见0427代码总体移动;
widow 继承UiView window子控件是控制器view
Nslog(@"%@",self.view.superView)打印父控件;
如何解决黑色?
更改UIWindow的颜色,使UIwindow的颜色和view的背景颜色一致;
0923代码运行-第一份代码;
差异:键盘输入框调出,有输入框管理;
添加数据:改懒加载de NSArray 为NSMutableArray;
如何操做tableView滚到最后一条?
- (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)(此处是枚举能够进去看下什么)scrollPosition animated:(BOOL)animated;滚到哪一行,在UITableView
发送完如何清空输入框?:
self.inputView.text=nil;
改输入框线的位置:
leftView,(添加一次:在viewdeload);
更改显示模式leftViewMode的模式:代码?
如何获取当前时间:NSDate;
NSDate*date=[NSDate date];//返回当前时间;
NSLog(@"date = %@\n",date+8);//东华区,
时间转字符串;如何输出时间代码(1节)
NSDateFormatter*fm=[NSDateFormatter alloc]init];
fm stringf
时间格式:
判断是否须要时间:
取出上一条,-数组的最后一条消息;
判断时间是否相等
静态单元格;
若是运行结果与预期不同
有缓存:
删模拟器软件,再clean;
tableViewController添加步骤?(xib相似)
1>NJViewController 继承与UItableVIewcontroller,
2>删掉strory的controllerViewor 从新拖一个UItableVIewcontroller,
3>更改UItableVIewcontroller的class名位NJViewController
tableViewController加,改继承,改类;
tableViewController已经实现了代理数据源方法不用拖线
改group就是分组;
修改模式:tableVIew-static
把cell设置为静态的;
设置静态设置成怎么样就是怎么样的;
stattic-cell(basic stytle)--设置image
下一级设置lable;
tableView group分组,设置组数(界面中);
静态单元格用在设置等不变的地方;能够在界面中修改行高;
0>建立tableViewController (步骤);
1>好友列表
2>建立两个模型:MJFRiendGroup;mjFrend
属性:frends,name ,online
mjFrend属性:四个属性;(pilst文件决定)
3>字典转模型
两个方法传字典返回模型;
//注册全部的属性,frends中存放的仍是字典;
对frends数组进行转换;
mjFrend中提供两个方法将字典转换为模型
kvc转换的是字典,须要将字典转模型
所有是tableView 拖一个tableView;
4>实现数据源方法:
4.1>多少组;
4.2>每一组有多少数据;numberof
4.2.1.取出对应租的模型
4.2.2.返回当前组中有多少好友;
4.2.3.只写一句,再把cell打上标记@ abc,自动建立
4.2.3.1 建立模型,取出对应组的组模型;
4.2.3.2 取出组对应行的模型
4.2.3.3用对应租的模型为cell赋值;
14:08打印bounds?
UITableView
5>去处状态栏
//6>头部标题,取得对应组的模型
怎么找方法?分组的标题上放按钮;
1>显示分组,调用数据源的方法,因为在头部标题中须要能够点的view,有一个返回nsStringd的相似的方法,不对;
2>因为须要视图是UIView的再到代理中找是否有返回UIView,名称相似的方法;
6>添加头部视图view(解决性能)
下面的封装,继承与tableViewcell的类;
1.headerView中添加按钮
建立添加到contentView
2.添加lable
建立添加lable
return cell
3.设置数据;
UIButton里面有添加加好按钮的方法:buttonwith...
设置分组的头部视图数据;
一个视图不显示:
NSLog(@"<#name#> = %@\n",NSStringFromCGrect);
QQ好友列表
对齐方式:
1>content内容对其方式;左对齐?代码 contentMode
2>设置内边距,不要太靠左代码 inset
3>设置lable和imageView的距离:
展开:能够点击,监听响应---
实现监听函数:(不必定非得)
-(void)layOutSubviews
#warning 必定须要调用父类的方法
{
[super layOutSubViews];
}
旋转:修改iamge的transform;
16:02展开与还原;
在init
设置视图的高度16:10两种方式:统一设,每一个分步设
经过cell的高度的两种方式:
如何偷图片?展现类的app,720度旋转
docments 或者library
1>image
2>拿到image,托图片到资源
3>设默认图片;
4>拖动的时候从新设置一张图片
5>设置图片容器
建立触摸事件:平移的手势管理器
self表明self的某个方法(viewDidLoad)
让imageView能够和用户交互;
6>定义变量,当前是第几张;切换图片
经过手势管理器获取在平模上的坐标
图片不显示:删掉从新添加;
代理和通知的区别?
打印bounds和frame的值
NSLog(@"%@", NSStringFromCGRect(view.bounds));
* 但凡在iOS中,init方法建立出来的控件frame/bounds都是0
UITableViewCell
@property (nonatomic, readonly, retain) UIView *contentView;
UITableViewHeaderFooterView
@interface UITableViewHeaderFooterView : UIView
@property (nonatomic, readonly, retain) UIView *contentView;
没有进入set方法,调用set方法的对象为空;
0428qq头像点击? 0428:-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 为甚么警告?//可能定义cell为另外的类型
+(instancetype)headerWithTableView:(UITableView *)tableView
{ //标记,出列,建立,放回
static NSString *IDH = @"header";
MJHeaderView *header=[tableView dequeueReusableHeaderFooterViewWithIdentifier:IDH];
if (nil == header) {
//若从新建立,是局部变量,执行完就销毁,返回的永远为空
MJHeaderView* header=[[MJHeaderView alloc]initWithReuseIdentifier:IDH];
}
NSLog(@"headerWithTableView\n");
return header;
}
+(instancetype)cellWithTableView:(UITableView*)tableView
{ //标记,出列,建立,放回
static NSString*ID = @"friend";
MJFriendCell* cell = [tableView dequeueReusableCellWithIdentifier:ID ];
if (nil==cell)
{//MJFriendCell* cell,不能从新建立,从新建立会返回为空
cell=[[MJFriendCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
}
return cell;
}
//0426qq
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
MJMessageFrame*mf=self.messageFrames[indexPath.row]; //[[MJMessageFrame alloc]init];
// NSLog(@"%d",mf.cellheight);
MJMessageFrame*mf = [[MJMessageFrame alloc]init]此处不能从新建立,
return mf.cellheight;
}
[btn addTarget:self action:@selector(headerClick) forControlEvents:UIControlEventTouchUpInside];
不须要设代理,不须要设监听,直接能够用;
知识点:
1.若是界面上有不一样视图组成不能使用uitableviewcontroller
2.imageveiw在storyboard中不能添加子控件
3.设置按钮图片若是想要原样显示设置为image便可,若是设置为background会自动拉伸
4.设置uitextfield的背景不能选择样式(border style)
5.经过代码自定义Cell;
3.1.2经过tag获取子控件赋值
UIImageView *iconView = (UIImageView *)[appView viewWithTag:55];
iconView.image = [UIImage imageNamed:appInfo.icon];
// 取出UILabel
UILabel *nameLabel = (UILabel *)[appView viewWithTag:100];
nameLabel.text = appInfo.name;
contentOffset位置修改,大图展现就实现滚动
图片轮播:实现原理??
#import "NJViewController.h"
@interface NJViewController () <UIScrollViewDelegate>
@property (weak, nonatomic) IBOutlet UIScrollView *scrollview;
/**
* 页码
*/
@property (weak, nonatomic) IBOutlet UIPageControl *pageControl;
@property (nonatomic, strong) NSTimer *timer;
@end
@implementation NJViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// 图片的宽
CGFloat imageW = self.scrollview.frame.size.width;
// CGFloat imageW = 300;
// 图片高
CGFloat imageH = self.scrollview.frame.size.height;
// 图片的Y
CGFloat imageY = 0;
// 图片中数
NSInteger totalCount = 5;
// 1.添加5张图片
for (int i = 0; i < totalCount; i++) {
UIImageView *imageView = [[UIImageView alloc] init];
// 图片X
CGFloat imageX = i * imageW;
// 设置frame
imageView.frame = CGRectMake(imageX, imageY, imageW, imageH);
// 设置图片
NSString *name = [NSString stringWithFormat:@"img_0%d", i + 1];
imageView.image = [UIImage imageNamed:name];
// 隐藏指示条
self.scrollview.showsHorizontalScrollIndicator = NO;
[self.scrollview addSubview:imageView];
}
// 2.设置scrollview的滚动范围
CGFloat contentW = totalCount *imageW;
self.scrollview.contentSize = CGSizeMake(contentW, 0);
// 3.设置分页
self.scrollview.pagingEnabled = YES;
// self.pageControl.currentPage = 3;
// 4.监听scrollview的滚动 控制器的对象的地址传给了scrollView的代理的地址
// 控制器对象和scrollView指向同一对象
self.scrollview.delegate = self;
// NSTimer // 定时器 适合用来隔一段时间作一些间隔比较长的操做
/*
NSTimeInterval:多长多件操做一次
target :操做谁
selector : 要操做的方法
userInfo: 传递参数
repeats: 是否重复
*/
// self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(nextImage) userInfo:nil repeats:YES];
[self addTimer];
}
- (void)nextImage
{
// NSLog(@"切换图片");
// 1.获取页码
/*
if (self.pageControl.currentPage == 4) {
self.pageControl.currentPage = 0;
}else
{
// 假设当前是第0页 变成第一页,就会马上把小红点变成第一页
self.pageControl.currentPage++;
}
*/
int page = self.pageControl.currentPage;
if (page == 4) {
page = 0;
}else
{
page++;
}
// 2.滚动scrollview
// CGFloat x = self.pageControl.currentPage * self.scrollview.frame.size.width;
CGFloat x = page * self.scrollview.frame.size.width;
self.scrollview.contentOffset = CGPointMake(x, 0);
}
// scrollview滚动的时候调用
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
NSLog(@"滚动中");
// 计算页码
// 页码 = (contentoffset.x + scrollView一半宽度)/scrollView宽度
CGFloat scrollviewW = scrollView.frame.size.width;
CGFloat x = scrollView.contentOffset.x;
int page = (x + scrollviewW / 2) / scrollviewW;
self.pageControl.currentPage = page;
}
// 开始拖拽的时候fxs
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
// 关闭定时器(注意点; 定时器一旦被关闭,没法再开启)
// [self.timer invalidate];
[self removeTimer];
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
// 开启定时器
[self addTimer];
}
/**
* 开启定时器
*/
- (void)addTimer{
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(nextImage) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
}
/**
* 关闭定时器
*/
- (void)removeTimer
{
[self.timer invalidate];
}
传智电台的做用:
- (void)viewDidLoad
{
[super viewDidLoad];
CGFloat lastY = self.lastBtn.frame.origin.y + self.lastBtn.frame.size.height + 10 /* + 44 */;
// 只要不横向滚动, 宽度能够设置为0
// 设置滚动范围
self.scrollview.contentSize = CGSizeMake(0, lastY);
// 2.为了避免让导航view挡住scrollview
// 设置外边距
self.scrollview.contentInset = UIEdgeInsetsMake(64, 0, 44, 0);
// 设置contentOffset
// 1.取出之前的offset
CGPoint tempOffset = self.scrollview.contentOffset;
// 2.修改之前的位置
tempOffset.y = -64;
// 3.覆盖之前的offset
self.scrollview.contentOffset = tempOffset;
}
大图展现中修改contentOffset的值就能够实现滚动;
图片缩放:只要添加函数就能够完成缩放吗?
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
NSLog(@"开始缩放");
return self.imageView;
}
//缩放过程当中调用
- (void)scrollViewDidZoom:(UIScrollView *)scrollView
{
NSLog(@"正在缩放");
}
/**
* 缩放结束时调用
*
* @param scrollView 当前的scrollview
* @param view 被缩放的view
* @param scale 缩放的比例
*/
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale
{
NSLog(@"缩放结束");
NSLog(@"view = %@, scale = %.1f", view, scale);
}
typedef enum {
MJMessageTypeMe=0,
MJMessageTypeOther
} MJMessageType; 不能定义再累扩展中,MJMessageType不会被发现?
打印frame利器:
NSStringFromCGAffineTransorm(CGAffineTransorm transform)
NSStringFromClass(<#__unsafe_unretained Class aClass#>)
NSStringFrom.....打印frame,size.point.aff,transfrom,
NSStringFromClass(<#__unsafe_unretained Class aClass#>)
NSStringFromCGSize(<#CGSize size#>)
NSStringFromCGPoint(<#CGPoint point#>)
NSStringFromCGAffineTransform(<#CGAffineTransform transform#>)
NSStringFromProtocol(<#Protocol *proto#>)
NSStringFromRange(<#NSRange range#>)
NSStringFromSelector(<#SEL aSelector#>)
NSStringFromUIEdgeInsets(<#UIEdgeInsets insets#>)
NSStringFromUIOffset(<#UIOffset offset#>)
NSStringFromUIOffset(<#UIOffset offset#>)
微博本身敲的错误总结:
1>在左上角显示头像的位置显示VIP是由于,显示头像赋值时,赋给的是vip图标;正文的字体,赋值给时间显示;
2>字体无显示,没有字体的frame:也是赋值frame的时候ok,传智frame的"过桥时"两个frame不是同一个; NSLog(@"打印frame利器:%@",NSStringFromCGRect(self.pictureView.frame));
[NSStrin]
3>图片无显示,前面设置好frame,在最后显示的时候,没有将设置号的值赋值过去,传值环节出问题;
经过打印设置frame的最后一步肯定;
instancetype 和 MJMessageCell的值 不能写错:instancetype不是UITableViewcell,
MJMessageCell 不要写为 uUITableViewcell
+( instancetype)cellWithTableView:(UITableView *)tableView
{
static NSString *ID=@"message";
MJMessageCell *cell=[tableView dequeueReusableCellWithIdentifier:ID];
if (cell == nil) {
cell = [[MJMessageCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
}
return cell;
}
UIImageView *iconView = [[UIImageView alloc]init];
[self.iconView addSubview: iconView];
self.iconView = iconView;
self.iconView.image = [UIImage imageNamed: @"me"];
_iconView.frame =messageFrame.iconF;
NSLog(@" self.iconView.frame = %@\n", NSStringFromCGRect(self.iconView.frame)) ;
NSLog(@"iconframe = %@\n",NSStringFromCGRect(messageFrame.iconF));
打印发现_iconView为nil 为nil说明是上一层的错误, 再找上一层,发现加控件错了;
[self.iconView addSubview: iconView];
QQ发消息中键盘不能移动只是inputView移动到上面,改成view总体移动就解决问题了,view上面有tablView和view,因此让view总体,移动,
一个文本lable在没有写入文字的时候,给文字设置颜色,可能会没显示;或者设置的文字可能不成功; 9o
字典转模型:若是一个plist文件下面
汽车列表:plist=NSString*title + NSArray*cars
- (instancetype)initWithDict:(NSDictionary *)dict
{
if (self = [super init]) {
self.title = dict[@"title"];
NSArray *dictArray = dict[@"cars"];
NSMutableArray *modles = [NSMutableArray arrayWithCapacity:dictArray.count];
for (NSDictionary *dict in dictArray) {
MJCar *car = [MJCar carWithDict:dict];
[modles addObject:car];
}
self.cars = modles;
}
return self;
}
好友列表:plist 两个属性 +NSArray* friends
-(instancetype)initWithDict:(NSDictionary *)dict
{
if (self=[super init])
{
//注入全部的属性 三个属性转化为字典
[self setValuesForKeysWithDictionary:dict];
//建立,遍历,转化,添加,赋值 处理特殊的属性
//下面的是补充转化,二次处理
NSMutableArray*models=[NSMutableArray arrayWithCapacity:self.friends.count];
//取出self.frends数组中的每一个字典转化
for (NSDictionary*dict in self.friends) {
MJFriend*friend=[MJFriend friendWithDict:dict];
[models addObject:friend];//medels是一个数组,转化后存放4个模型的数组
}
self.friends=models;//models 是模型数组,MJFriend中friend是转化后的模型数组:里面存放有不少单个模型
}
//返回的是一组模型;
return self;
}
- (UIView*)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{ //1.建立头部视图
MJHeaderView *header = [MJHeaderView headerWithTableView:tableView];
// header.userInteractionEnabled=YES;
MJFriendGroup *gp = self.groups[section];
header.group=gp;
//设置代理
header.delegate=self;
return header;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
// 1.取出对应的模型
NJCarGroup *cg = self.cars[section];
return cg.title;
}
设置每一行的高度:heightForRow
谁的代理方法用谁开头
刷新是relaod从新加载模型数据;
什么状况下使用tableViewController (只有tableView一种的状况) 和 MJViewController(界面状况比较复杂,不仅tableView一种),怎么区分?
什么状况下用系统自带的cell,什么状况下须要自定义cell
1>相似于微博,QQ发消息,每一个cell的内容都不同的时候,无规律的时候须要自定义cell
2>相似团购,九宫格,自定义cell不能知足,可是数据之间是有规律的状况下使用xib,
3>像汽车品牌展现,英雄展现,QQ好友列表等,系统的subtitle,default,title等模式能够知足的状况下使用系统自带的cell
4>相似传智猜图,上半部分的界面固定使用storyBoard,下半部分的不固定使用代码实现,代码实现较麻烦,比较灵活
建立cell类,为cell赋值等一些操做;
0501KVC的本质:将字典中的键值为dict[@"name"]的对应的value 赋值给建立模型中属性名为name的值;
0501 好友列表中MJFriendGroup中setValuesForKeysForDict 这行=0504好友列表所示?(kvc的名字没有一一对应)
0504 控制器中,btw中设置 btn.titleLable.text she设置了字体和颜色没法显示????区别
0504好友列表的头部视图点击原理待复习,bug待调试
/**
* 当视图的frame被修改的时候就会调用 ?没看见修改frame啊?(是在头部视图建立完成return header 而且设置了数据才调用,建立frame的时候默认有一个建立frame也算改变)
* 通常在这个方法中布局子控件
*/
- (void)layoutSubviews
{
#warning 必定要调用父类的改方法
[super layoutSubviews];
// 1.设置按钮的frame
self.btn.frame = self.bounds;
NSLog(@" = %@\n",NSStringFromCGRect(self.bounds));
// 2.设置label的frame
CGFloat labelY = 0;
CGFloat labelH = self.bounds.size.height;
CGFloat labelW = 50;
CGFloat labelX = self.bounds.size.width - 10 - labelW;
self.nameLabel.frame = CGRectMake(labelX, labelY, labelW, labelH);
}
#pragma mark - 当视图被添加到别的视图中的时候就会调用
- (void)didMoveToSuperview
{
// 修改三角形的旋转角度
// NSLog(@"当前视图被添加到了其它视图中");
// 判断当前组是否展开
if (self.group.isOpened) {
// 展开状态
self.btn.imageView.transform = CGAffineTransformMakeRotation(M_PI_2);
}else
{
// 合拢状态
self.btn.imageView.transform = CGAffineTransformIdentity;
}
}
//通知控制器刷新表格,看下self的代理是否实现了headerViewDidClicked:这个方法,若是实现了这个方法
// 就通知self的代理(指代控制器) 去调用headerViewDidClicked这个方法
if ([self.delegate respondsToSelector:@selector(headerViewDidClicked:)])
{
[self.delegate headerViewDidClicked:self];
}
0504
pickerView 不用设宽高 拖数据源
自带的,连线不须要协议和设代理?相似UITableViewController
随机函数
self.foods.count
正确的:[self.foods count] 错误:self.Foods[0].count self.Foods[0]= [self.foods objectAtIndex 0]
objectAtIndex返回的是id类型的;
1029 1034做业
button里面
1056批量改类名(文件)技巧,变蓝色修改
pickerView设间距:行高高点54;
viewForRow一行出现视野会调用,相似cellforRow
dataPichker 改归属地
中文:model date只显示日期
pick里面有最小时间和最大时间
textField 能够设置键盘的格式(时间选择器)
toolBar只能添加bar button
添加别的自动包装成bar button
barButton是有样式,在ios7无效
flexible 可拉升的;能够移到靠右;
屏幕的动态获取
self
1420的第三个自动拉升\
test 用在单元测试中,include unitytest xcode4中勾选以后才会出选test
prodecuts 文件对于ios是废物
ipone 正,左右,ipone upsde down不支持
pch文件自动去掉nslog
开发:打印日志
打包:打包程序上传到appstore
pch文件:先看下公司是否有自定义的宏 ,nslog
自定义log
DEBUG 宏:(在公司不要使用nslog):(目前不要使用nslog,自定义log );
UIApplication 是应用程序的象征
UIApplication *app = [UIApplication sharedApplication];得到单利对象(程序启动建立的第一个对象);
UIApplication应用级别的操做,用应用A打开应用B,分享;
多个对象同一地址:单例
屡次获取的地址都相同;
设置显示联网状态 看菊花
app.networkActivityIndicatorVisible = YES;
0表明 清除图标右上角的数字 998添加图标数字
app.applicationIconBadgeNumber = 0;
lightContent是白色的字体
app.statusBarStyle = UIStatusBarStyleLightContent;(修改状态栏样式)
[app setStatusBarHidden:YES withAnimation:UIStatusBarAnimationFade];状态栏的动画
app.statusBarHidden = YES(全部的状态栏都会隐藏); 隐藏状态栏:动态的显示修改状态栏:(动态)
// URL : 一个资源的惟一路径
// URL的组成 == 协议头://主机域名/路径
网络资源URL的组成 == http(协议头)://www.baidu.com/1.png
// 本地文件资源URL的组成 == file:///Users/apple/Desktop/1.png(无资源地址,本地)
[app openURL:[NSURL URLWithString:@"http://ios.itcast.cn"]];
使用app打开网页
[app openURL:[NSURL URLWithString:@"http://ios.itcast.cn"]];
打电话
[app openURL:[NSURL URLWithString:@"tel://10086"]];
发短信
[app openURL:[NSURL URLWithString:@"sms://10086"]];
邮件
[app openURL:[NSURL URLWithString:@"Mailto://lnj@126.cn"]];
打开其余的应用程序
default.png 显示完毕,程序启动完毕
程序启动完毕后当即执行的指令:
程序进入后台执行的指令:这个方法一般在这个方法中保存应用信息
程序进入前台执行的方法;
从新获取焦点
即将失去焦点:失去焦点不能使用
iOS程序启动完毕后,建立的第一个视图控件就是UIWindow,接着建立控制器的view,最后将控制器的view添加到UIWindow上,因而控制器的view就显示在屏幕上了
一个iOS程序之因此能显示到屏幕上,彻底是由于它有UIWindow
也就说,没有UIWindow,就看不见任何UI界面
添加UIView到UIWindow中两种常见方式:
- (void)addSubview:(UIView *)view;
直接将view添加到UIWindow中,但并不会理会view对应的UIViewController
\@property(nonatomic,retain) UIViewController *rootViewController;
自动将rootViewController的view添加到UIWindow中,负责管理rootViewController的生命周期
经常使用方法
- (void)makeKeyWindow;
让当前UIWindow变成keyWindow(主窗口)
- (void)makeKeyAndVisible;
让当前UIWindow变成keyWindow,并显示出来
window view
谁是爸
1648 之间的关系,强应用,
只要有强引用使用对象,对象就不会释放,有强指针指着他;
hosring 文本换行或者特殊的字符youcompleteme插件,在vim中添加自动代码补全的功能;
创建一个工程后,会在Supporting files文件夹下看到一个“工程名-Info.plist”的文件,该文件对工程作一些运行期的配置,很是重要,不能删除
在旧版本Xcode建立的工程中,这个配置文件的名字就叫“Info.plist”
项目中其余Plist文件不能带有“Info”这个字眼,否则会被错认为是传说中很是重要的“Info.plist”
项目中还有一个InfoPlist.strings的文件,跟Info.plist文件的本地化相关
常见属性(红色部分是用文本编辑器打开时看到的key)
Localiztion native development region(CFBundleDevelopmentRegion)-本地化相关
Bundle display name(CFBundleDisplayName)-程序安装后显示的名称,限制在10-12个字符,若是超出,将被显示缩写名称
Icon file(CFBundleIconFile)-app图标名称,通常为Icon.png
Bundle version(CFBundleVersion)-应用程序的版本号,每次往App Store上发布一个新版本时,须要增长这个版本号
Main storyboard file base name(NSMainStoryboardFile)-主storyboard文件的名称
Bundle identifier(CFBundleIdentifier)-项目的惟一标识,部署到真机时用到
项目的Supporting files文件夹下面有个“工程名-Prefix.pch”文件,也是一个头文件
pch头文件的内容能被项目中的其余全部源文件共享和访问
通常在pch文件中定义一些全局的宏
在pch文件中添加下列预处理指令,而后在项目中使用Log(…)来输出日志信息,就能够在发布应用的时候,一次性将NSLog语句移除(在调试模式下,才有定义DEBUG)
#ifdef DEBUG
#define Log(...) NSLog(__VA_ARGS__)
#else
#define Log(...) /* */
#endif
设置应用程序图标右上角的红色提醒数字
@property(nonatomic) NSInteger applicationIconBadgeNumber;
设置联网指示器的可见性
@property(nonatomic,getter=isNetworkActivityIndicatorVisible) BOOL networkActivityIndicatorVisible;
若是想利用UIApplication来管理状态栏,首先得修改Info.plist的设置
全部的移动操做系统都有个致命的缺点:app很容易受到打扰。好比一个来电或者锁屏会致使app进入后台甚至被终止
还有不少其它相似的状况会致使app受到干扰,在app受到干扰时,会产生一些系统事件,这时UIApplication会通知它的delegate对象,让delegate代理来处理这些系统事件
delegate可处理的事件包括:
应用程序的生命周期事件(如程序启动和关闭)
系统事件(如来电)
内存警告
… …
[self.foods[component] count]计算二维数组中某个一维数组的个数
/ 3.让pickerview主动选中某一行某一列
[self.pickerView selectRow:newRow inComponent:component animated:YES];
// 经过代码让pickerview选中某一行不会调用代理的didSelectRow方法
// 4.手动调用didSelectRow方法(更改lable的文字)
[self pickerView:nil didSelectRow:newRow inComponent:component];
/**
pch文件的做用:
1.存放一些全局的宏(整个项目中都用得上的宏)
2.用来包含一些所有的头文件(整个项目中都用得上的头文件)
3.能自动打开或者关闭日志输出功能
*/
#import <Availability.h>
#ifndef __IPHONE_5_0
#warning "This project uses features only available in iOS SDK 5.0 and later."
#endif
// 写在__OBJC__里面的代码被全部的.m 和 .mm文件共享
// 之后全部和OC相关的东西都方法__OBJC__里面#ifdef __OBJC__ #endif 里面有嵌套
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#define NUMBER 55
#import "NJPerson.h"
#ifdef DEBUG
#define NJLog(...) NSLog(__VA_ARGS__)
#else
#define NJLog(...)
#endif
#endif
// 写在__OBJC__外面的代码被全部的文件共享 里面外面怎么区分?
#define ABC 10
//#import "NJPerson.h"
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
程序启动就执行
self.window.frame = [UIScreen mainScreen].bounds;(bounds从00开始?)
self.window = window;保存,使用强指针指向他,不然是局部变量
MjOneViewController *one = [[MjOneViewController alloc] init];
// [self.window addSubview:one.view];
self.window.rootViewController = one;
两种的区别:0921选装,更着转,强弱应用
程序启动
老师笔
MjOneViewController *one = [[MjOneViewController alloc] init];
// [self.window addSubview:one.view];
self.window.rootViewController = one;
一.UIPickerView
1.UIPickerView的常见属性
// 数据源(用来告诉UIPickerView有多少列多少行)
@property(nonatomic,assign) id<UIPickerViewDataSource> dataSource;
// 代理(用来告诉UIPickerView每1列的每1行显示什么内容,监听UIPickerView的选择)
@property(nonatomic,assign) id<UIPickerViewDelegate> delegate;
// 是否要显示选中的指示器
@property(nonatomic) BOOL showsSelectionIndicator;
// 一共有多少列
@property(nonatomic,readonly) NSInteger numberOfComponents;
2.UIPickerView的常见方法
// 从新刷新全部列
- (void)reloadAllComponents;
// 从新刷新第component列
- (void)reloadComponent:(NSInteger)component;
// 主动选中第component列的第row行
- (void)selectRow:(NSInteger)row inComponent:(NSInteger)component animated:(BOOL)animated;
// 得到第component列的当前选中的行号
- (NSInteger)selectedRowInComponent:(NSInteger)component;
3.数据源方法(UIPickerViewDataSource)
// 一共有多少列
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView;
// 第component列一共有多少行
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component;
4.代理方法(UIPickerViewDelegate)
// 第component列的宽度是多少
- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component;
// 第component列的行高是多少
- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component;
// 第component列第row行显示什么文字
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component;
// 第component列第row行显示怎样的view(内容)
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view;
// 选中了pickerView的第component列第row行
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component;
二.UIDatePicker
1.常见属性
// datePicker的显示模式
@property (nonatomic) UIDatePickerMode datePickerMode;
// 显示的区域语言
@property (nonatomic, retain) NSLocale *locale;
2.监听UIDatePicker的选择
* 由于UIDatePicker继承自UIControl,因此经过addTarget:...监听
三.程序启动的完整过程
1.main函数
2.UIApplicationMain
* 建立UIApplication对象
* 建立UIApplication的delegate对象
3.delegate对象开始处理(监听)系统事件(没有storyboard)
* 程序启动完毕的时候, 就会调用代理的application:didFinishLaunchingWithOptions:方法
* 在application:didFinishLaunchingWithOptions:中建立UIWindow
* 建立和设置UIWindow的rootViewController
* 显示窗口
3.根据Info.plist得到最主要storyboard的文件名,加载最主要的storyboard(有storyboard)
* 建立UIWindow
* 建立和设置UIWindow的rootViewController
* 显示窗口
keyWindow:键盘显示的window
让window成为keyWindow(主窗口)
// [self.window makeKeyWindow];并不会显示,只是成为主要window
// 让window成为keyWindow(主窗口)\而且可见
[self.window makeKeyAndVisible];
// self.window = window;(强指针保存,不然局部销毁)
0920平模旋转事件过程
.keyWindow
[UIApplication sharedApplication].keyWindow);获取主UIWindow
主window接受键盘点击
uitextField默认透明
tf.borderStyle = UITextBorderStyleRoundedRect;
ios7以前只有keywindow才能接受键盘输入和触摸
ios7 以后
根控制器
NSLog(@"%@", [UIApplication sharedApplication].windows);
获取全部的window
键盘处在一个独立的window中
获取键盘的view 从而自定义
layoutSubviews
在建立的时候,自动赋值frame,至关于改变了frame因此会调用
1016?
主窗口才能接受键盘
一个window只能有一个跟控制器
控制器常见的建立方式有如下几种
经过storyboard建立,建立,添加
直接建立
MJViewController *mj = [[MJViewController alloc] init];
指定xib文件来建立
MJViewController *mj = [[MJViewController alloc] initWithNibName:@"MJViewController" bundle:nil];
系统建立控制器
控制器的三种建立方式
fiesOwner
里面的class设置为那个控制器(类名),就能够为那个控制器服务,连线fileowner
11:38总结0506 view建立的八种方式
控制器的view 加载;
UINavigationController的使用步骤
初始化UINavigationController
设置UIWindow的rootViewController为UINavigationController
根据具体状况,经过push方法添加对应个数的子控制器
导航条44:20导航栏
导航控制器经过栈的形式管理子控制器
当前看到的是栈顶的控制器
push移开,back 控制器和view 销毁
autolayOut 子控件的不现实,或者结果不对的时候,去掉autolayOUt的沟,不然一个控件移动他会自动布局,影响结果;
导航控制器的栈两种形式
root控制器栈低的控制器
栈顶的.nav topView
放回出栈,前进进栈;
[控制器 popView ]移除栈顶的控制器
根=栈低
pop 出移除 push推入
程序加载完毕:viewDidLoad
self.UINavigationItem.title
返回按钮不是当前的控制器,是有上一个控制器决定,其余的都是当前控制器决定
nav.UINavigationBar.frame 打印frame
1616?为何拖nav
storyBoard 拖线不能往回拖
viewWillUnload 即将销毁的时候调用
viewDidUnload 彻底销毁
配合内存警告使用
// 建立控制器
NJViewController *vc = [[NJViewController alloc] init];
// 添加控制器的view到window上面
// 这种方式很差,不推荐
// [self.window addSubview:vc.view]; view添加后被强引用着,NJViewController的对象会被提早释放
// 设置window的根控制器
self.window.rootViewController = vc;
// 3.显示window
[self.window makeKeyAndVisible];
return YES;
打印方法(当前的window和rootController)
NSLog(@"self.Window = %@\n",self.window);
NSLog(@"rootControl = %@\n",self.window.rootViewController);
建立一个控制器 若是没指定跟控制器,会是默认的白色,即便给控制器的View设置有颜色;
outlet连线
连接folesOwner做用是什么这只self.view
从xib中加载storyBoard 拖两个view 更改xib所属的类名(控制器的类),当有两个view的时候
那个控制器是根控制器,那么就显示根控制器的颜色
storyBoard的本质是将storyBoard转化为代码
// nav.viewControllers == nav.childViewControllers
//经常使用
建立window必须得初始化frame 不然上面的控件不显示,或者不起做用
遍历出UIView中的全部子控件;并将遍历的结果写入文件
- (void)applicationDidBecomeActive:(UIApplication *)application
{
NSString *xml = [self digView:self.window];
[xml writeToFile:@"/Users/wg689/Desktop/ios6.xml" atomically:YES];
}
// 取出window中全部的子控件 以及他们的frame
- (NSString *)digView:(UIView *)view
{
if ([view isKindOfClass:[UITableViewCell class]]) return @"";
// 1.初始化
NSMutableString *xml = [NSMutableString string];
// 2.标签开头
[xml appendFormat:@"<%@ frame=\"%@\"", view.class, NSStringFromCGRect(view.frame)];
if (!CGPointEqualToPoint(view.bounds.origin, CGPointZero)) {
[xml appendFormat:@" bounds=\"%@\"", NSStringFromCGRect(view.bounds)];
}
if ([view isKindOfClass:[UIScrollView class]]) {
UIScrollView *scroll = (UIScrollView *)view;
if (!UIEdgeInsetsEqualToEdgeInsets(UIEdgeInsetsZero, scroll.contentInset)) {
[xml appendFormat:@" contentInset=\"%@\"", NSStringFromUIEdgeInsets(scroll.contentInset)];
}
}
// 3.判断是否要结束
if (view.subviews.count == 0) {
[xml appendString:@" />"];
return xml;
} else {
[xml appendString:@">"];
}
// 4.遍历全部的子控件
for (UIView *child in view.subviews) {
NSString *childXml = [self digView:child];
[xml appendString:childXml];
}
// 5.标签结尾
[xml appendFormat:@"</%@>", view.class];
return xml;
}
0508预习笔记
在恰当的时刻,使用perform方法执行对应的Segue
[self performSegueWithIdentifier:@"login2contacts" sender:nil];?
// Segue必须由来源控制器来执行,也就是说,这个perform方法必须由来源控制器来调用
利用performSegueWithIdentifier:方法能够执行某个Segue(继续==线对象),完成界面跳转
若是点击某个控件后,须要作一些判断,也就是说:知足必定条件后才跳转到下一个界面,建议使用“手动型Segue”
接下来研究performSegueWithIdentifier:sender:方法的完整执行过程
[self performSegueWithIdentifier:@“login2contacts” sender:nil(/*同对象*/)];
// 这个self是来源控制器
1>找到线,新建 2>设置来源和目标
根据identifier去storyboard中找到对应的线,新建UIStoryboardSegue对象
设置Segue对象的sourceViewController(来源控制器)
新建而且设置Segue对象的destinationViewController(目标控制器)
跳转的步骤:
1>准备,建立对象
调用sourceViewController的下面方法,作一些跳转前的准备工做而且传入建立好的Segue对象
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender(/*同对象*/);
// 这个sender是当初performSegueWithIdentifier:sender:中传入的sender
2>开始跳转
调用Segue对象的- (void)perform;方法开始执行界面跳转操做
3>取得导航控制器
取得sourceViewController所在的UINavigationController
4>压栈 完成跳转
调用UINavigationController的push方法将destinationViewController压入栈中,完成跳转
跟UINavigationController(导航控制器)相似
,UITabBarController也能够轻松地管理多个控制器,轻松完成控制器之间的切换,典型例子就是QQ、微信等应用
每一个iOS应用都有本身的应用沙盒(应用沙盒就是文件系统目录),与其余文件系统隔离。应用必须待在本身的沙盒里,其余应用不能访问该沙盒
应用沙盒的文件系统目录,以下图所示(假设应用的名称叫Layer)
模拟器应用沙盒的根路径在: (apple是用户名, 6.0是模拟器版本)
/Users/apple/Library/Application Support/iPhone Simulator/6.0/Applications
// 应用沙盒的结构分析:
1>应用程序包:(上图中的Layer)包含了全部的资源文件和可执行文件
2> Documents:保存应用运行时生成的须要持久化的数据,iTunes同步设备时会备份该目录。例如,游戏应用可将游戏存档保存在该目录
3> tmp:保存应用运行时所需的临时数据,使用完毕后再将相应的文件从该目录删除。应用没有运行时,系统也可能会清除该目录下的文件。iTunes同步设备时不会备份该目录
4> Library/Caches:保存应用运行时生成的须要持久化的数据,iTunes同步设备时不会备份该目录。通常存储体积大、不须要备份的非重要数据
5> Library/Preference:保存应用的全部偏好设置,iOS的Settings(设置)应用会在该目录中查找应用的设置信息。iTunes同步设备时会备份该目录
沙盒根目录:NSString *home = NSHomeDirectory();
Documents:(2种方式)
利用沙盒根目录拼接”Documents”字符串
NSString *home = NSHomeDirectory();
NSString *documents = [home stringByAppendingPathComponent:@"Documents"];
// 不建议采用,由于新版本的操做系统可能会修改目录名
利用NSSearchPathForDirectoriesInDomains函数
// NSUserDomainMask 表明从用户文件夹下找
// YES 表明展开路径中的波浪字符“~”
NSArray *array = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask<表明从用户文件夹下找>, NO<不展开路径的波浪字符>);
// 在iOS中,只有一个目录跟传入的参数匹配,因此这个集合里面只有一个元素
NSString *documents = [array objectAtIndex:0];
0508私人通信录
1>界面搭建
多个控制器,使用导航来管理其余的控制器
2>登录界面(viewController,普通View界面) ,联系人界面(继承UItableView),添加联系人界面(继承View 不能够滚),编辑界面(不能够滚,普通的view),
3>登录界面(viewController,普通View界面),设置rootView(拖view 的线),一个总体就放在view上,(使用view来管理子控件).title(双击头部标题)
4>要得到属性监听->连线,刚开始btn不能点:enable 去掉沟
5>监听方式选择(输入文本框):addTarget通常监听按钮的点击,以及进度条值的改变(无方法), --代理(中没有UItextFieldDelegate中没有监听输入框值改变的方法) --通知
6> [[NSNotificationCenter defaultCenter](建立通知中心) addObserver:self (谁来监听)selector:@selector(textChange(接到通知后执行的操做)) name:UITextFieldTextDidChangeNotification(通知名称) object:self.pwdField(谁发送的通知)(nil表明谁发送均可以接受通知,此处不能写nil,只能接受两个,不是多个的通知)];
UITextFieldTextDidChangeNotification(输入框改变的时候会发出此通知)
7>拖线自动登陆,记住密码
8>登陆作完,作联系人列表,拖下一个界面;
9>数据传递
10>判断是否登陆正确:连线,监听:若是正确
拖不了线===没创建关系:类名
不须要参数就手写代码
alert弹框显示:show一下
弹框:UIActionSheet 1>建立 2>显示:showInView
避免每次输入密码:直接修改代码:输入数据肯定,省得每次输入
btn.enable =YES;表明btn能够用,
placeHolder 输入框提示:(*)必填
暗文 secure
UISwith和按钮同样:
segue:身份,来自哪,去哪;
手动的:控制器拖到控制器(表面上看是View);
自动:控件到控制器
coco4app 加快工做效率
封装:->
/**
* 执行segue后,跳转以前会调用这个方法
* 通常在这里给下一个控制器传递数据
*/
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// 1.取得目标控制器(联系人列表控制器)
UIViewController *contactVc = segue.destinationViewController;
// 2.设置标题
contactVc.title = [NSString stringWithFormat:@"%@的联系人列表", self.accountField.text];
// contactVc.title 等价于 contactVc.navigationItem.title
// contactVc.navigationItem.title = [NSString stringWithFormat:@"%@的联系人列表", self.accountField.text];
}
须要修改cpntroller的类;下一个控制器:的返回上个控制器决定,copy 代码 不会拷贝连线
通知不用须要移除
让键输入框成为第一响应者:就能够当即召唤出键盘
让姓名
stro xib建立的都不会调用init方法
若是对象是NSString、NSDictionary、NSArray、NSData、NSNumber等类型,能够直接用NSKeyedArchiver进行归档和恢复(不能写归档)
不是全部的对象均可以直接用这种方法进行归档,只有遵照了NSCoding协议的对象才能够
NSCoding协议有2个方法:
encodeWithCoder:
每次归档对象时,都会调用这个方法。通常在这个方法里面指定如何归档对象中的每一个实例变量,可使用encodeObject:forKey:方法归档实例变量
initWithCoder:
每次从文件中恢复(解码)对象时,都会调用这个方法。通常在这个方法里面指定如何解码文件中的数据为对象的实例变量,可使用decodeObject:forKey方法解码实例变量
NSString *home = NSHomeDirectory();
// 2.document路径
NSString *docPath = [home stringByAppendingPathComponent:@"Documents"];
// 3.新建数据
// MJPerson *p = [[MJPerson alloc] init];
// p.name = @"rose";
NSArray *data = @[@"jack", @10, @"ffdsf"];
// 1.利用NSUserDefaults,就能直接访问软件的偏好设置(Library/Preferences)
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
// 3.马上同步:保存数据
[defaults synchronize];
发送未识别的消息.没有那个方法(找不到这个方法);
- (IBAction)save {
// 1.新的模型对象
MJStudent *stu = [[MJStudent alloc] init];
stu.no = @"42343254";
stu.age = 20;
stu.height = 1.55;
// 2.归档模型对象
// 2.1.得到Documents的全路径
NSString *doc = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
// 2.2.得到文件的全路径
NSString *path = [doc stringByAppendingPathComponent:@"stu.data"];
// 2.3.将对象归档
[NSKeyedArchiver archiveRootObject:stu toFile:path];
}
- (IBAction)read {
// 1.得到Documents的全路径
NSString *doc = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
// 2.得到文件的全路径
NSString *path = [doc stringByAppendingPathComponent:@"stu.data"];
// 3.从文件中读取MJStudent对象
MJStudent *stu = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
NSLog(@"%@ %d %f", stu.no, stu.age, stu.height);
}
/**
* 将某个对象写入文件时会调用
* 在这个方法中说清楚哪些属性须要存储
*/
- (void)encodeWithCoder:(NSCoder *)encoder
{
[encoder encodeObject:self.no forKey:@"no"];
[encoder encodeInt:self.age forKey:@"age"];
[encoder encodeDouble:self.height forKey:@"height"];
}
/**
* 从文件中解析对象时会调用
* 在这个方法中说清楚哪些属性须要存储
*/
- (id)initWithCoder:(NSCoder *)decoder
{
if (self = [super init]) {
// 读取文件的内容
self.no = [decoder decodeObjectForKey:@"no"];
self.age = [decoder decodeIntForKey:@"age"];
self.height = [decoder decodeDoubleForKey:@"height"];
}
return self;
} extern
父页面是tableViewceller,父父页面是navigationer,子页面 tableViewceller,父子页面之间没连线的时候,子页面的tableViewcontroll是没法显示导航条的标题的
英文的时候能够本地化里面修改,sh
导航上添加按钮:经过代码
tableView从新显示:两个步骤:
1>增长模型
2>刷新表格
3>持久化数据
每一个Cell 有 contenTView =图像+text +text
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
/*
// 1.没有xib和storyboard的状况(默认会建立一个空白色view)
NJOneViewController *one = [[NJOneViewController alloc] init];
one.view.backgroundColor = [UIColor redColor];
*/
/*
// 2.经过storyboard建立(会去storyboard中建立剪头指向的view)
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Test" bundle:nil];
NJOneViewController *one = [storyboard instantiateInitialViewController];
*/
/*
// 3.指定xib的状况(去xib中建立files onwner 的view属性链接的view)
NJOneViewController *one = [[NJOneViewController alloc] initWithNibName:@"Demo" bundle:nil];
*/
/*
// 4.有同名xib的状况 (自动加载同名的xib,建立xib中files onwner 的view属性链接的view)
NJOneViewController *one = [[NJOneViewController alloc] init];
*/
/*
// 5.有同名xib的状况,xib名称是去掉controller的状况 ((自动加载去掉controller的xib,建立xib中files onwner 的view属性链接的view)
NJOneViewController *one = [[NJOneViewController alloc] init];
*/
// 6.若是重写了控制器的loadview方法,就不会自动去加载xib
//NJOneViewController.xib
NJOneViewController *one = [[NJOneViewController alloc] init];
/*
//7.若是重写了控制器的loadview方法,就不会自动建立storyboard中剪头指向的view
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Test" bundle:nil];
NJOneViewController *one = [storyboard instantiateInitialViewController];
*/
// 8.若是重写了控制器的loadview方法, 而且在loadview方法中建立了uiview,就会显示loadview中的uiveiw,不会再去建立其它(xib,storyboard)的veiw
// NJOneViewController *one = [[NJOneViewController alloc] init];
self.window.rootViewController = one;
[self.window makeKeyAndVisible];
return YES;
}
添加tabBar是controller;添加子控制器
控制器包含view
如何验证控制器是否建立:重写生命周期方法
子类都用用到某一个,抽取父类
该继承,改一个就行
从新建立调用:viewDidload
did
- (void)applicationDidBecomeActive:(UIApplication *)application
获取焦点,程序可用,能够点
tabBar 控制器 封装导航控制器
导航栏,由栈顶控制器管理
返回上一个控制器决定
hideTabar 设置那个界面的tabarbtn的属性
跟控制器不能hideTabar
14:30修改?
不显示,删掉数据源:为0; 导航会执行默认的方法
model 遮盖,盖住原来的控制器
toot展现的控制器,虽然说显示two,root仍是 one
弱指针 一建立就是放
strong 只要我在,你得在,在其余的地方还可使用
weak 避免我销毁了,你还不销毁,形成内存泄露
归档:
- (IBAction)saveBtnClick:(id)sender {
// 建立对象
NJPerson *p = [[NJPerson alloc] init];
p.name = @"lnj";
p.age = 29;
p.height = 1.75;
// 获取目录
NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSLog(@"docPath = %@\n",docPath);
NSString *filePath = [docPath stringByAppendingPathComponent:@"arc.xxoo"];
NSLog(@"filePath = %@\n",filePath);
// 保存自定义对象(归档)
[NSKeyedArchiver archiveRootObject:p toFile:filePath];
}
- (IBAction)readBtnClick:(id)sender {
// 获取目录
NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *filePath = [docPath stringByAppendingPathComponent:@"arc.xxoo"];
// 解归档
NJPerson *p = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
NSLog(@"%@, %d, %.1f", p.name, p.age, p.height);
}
私人通信录:键盘文字改变的时候,让添加姓名的按钮变为可用,涉及通知:addtarget :代理,通知三种办法;
self.nameField addTarget:self(添加到当前控制器) action:执行的操做 forControlEvents:<#(UIControlEvents)#>(什么事件,)
当self.nameField
//addTarget:通常用于监听按钮的点击 以及进度条值的改变
// self.nameField addTarget:self action:@selector() forControlEvents:UIControlEvent
// self.nameField.delegate = self;
// 经过通知监听UITextfield的改变
/*
addObserver: 谁来监听
selector: 通知发生的时候调用什么方法
name:通知名称
object:谁发送的通知
注意:object不能写nil, 由于若是是nil只要是UITextField发生改变都会调用textChange方法, 而咱们指向帐号和密码输入框发生改变的时候才调用
*/
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChange) name:UITextFieldTextDidChangeNotification object:self.nameField];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChange) name:UITextFieldTextDidChangeNotification object:self.pwdField];
@property(nonatomic,assign) id<UITextFieldDelegate> delegate;
- (void)textFieldDidBeginEditing:(UITextField *)textField; // became first responder
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string; // return NO to not change text
{
代理不行
}
通知的使用:
1>若是继承于UIControl :使用addTarget(看下里面是否有)
2>看一下UITextFiled中有没有方法
3>看下通知:NSUITextField,通知名称:UITextField
//只要经过xib或者stotyBoard建立的cell都会调用这个方法
- (void) awakeFromNib
// 当控件的frame被修改就会调用
- (void)layoutSubviews
{
0511 qua2d
形上下文(Graphics Context):是一个CGContextRef类型的数据
图形上下文的做用
保存绘图信息、绘图状态
决定绘制的输出目标(绘制到什么地方去?)
(输出目标能够是PDF文件、Bitmap或者显示器的窗口上)
相同的一套绘图序列,指定不一样的Graphics Context,就可将相同的图像绘制到不一样的目标上
Quartz2D提供了如下几种类型的Graphics Context:
Bitmap Graphics Context
PDF Graphics Context
Window Graphics Context
Layer Graphics Context
Printer Graphics Context
layer控件能显示就由于这个
如何利用Quartz2D自定义view?(自定义UI控件(由于有layer))
如何利用Quartz2D绘制东西到view上?
1> 首先,得有图形上下文,由于它能保存绘图信息,而且决定着绘制到什么地方去
2>其次,那个图形上下文必须跟view相关联,才能将内容绘制到view上面 联系点 Layer Graphics Context(创建联系bug点)
自定义view的步骤
新建一个类,继承自UIView(bug点)
实现- (void)drawRect:(CGRect)rect方法 只有这个方法得到Layer Graphics Context ,而后在这个方法中
取得跟当前view相关联的图形上下文
绘制相应的图形内容
利用图形上下文将绘制的全部内容渲染显示到view上面
为何要实现drawRect:方法才能绘图到view上?
由于在drawRect:方法中才能取得跟view相关联的图形上下文
drawRect:方法在何时被调用?
当view第一次显示到屏幕上时(被加到UIWindow上显示出来)
调用view的setNeedsDisplay或者setNeedsDisplayInRect:时
Quartz2D的API是纯C语言的
Quartz2D的API来自于Core Graphics框架
数据类型和函数基本都以CG做为前缀
CGContextRef
CGPathRef
CGContextStrokePath(ctx);
……
在drawRect:方法中取得上下文后,就能够绘制东西到view上
View内部有个layer(图层)属性,drawRect:方法中取得的是一个Layer Graphics Context,所以,绘制的东西实际上是绘制到view的layer上去了
View之因此能显示东西,彻底是由于它内部的layer
建立类继承UIView 同时storyBoard中更改类名
// 1.得到图形上下文 typedef struct CGContext *CGContextRef;
CGContextRef ctx = UIGraphicsGetCurrentContext()不须要星??
2>起点终点
3>上下文输出;
绘图和颜色的线的类型一致
// set : 同时设置为实心和空心颜色
// setStroke : 设置空心颜色
// setFill : 设置实心颜色
图形填充得边缘
1140?小细节
数码取色器
#define MJColor(r, g, b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1.0]
.0没有没颜色
图形上下文:
获取图形上下文
上下文栈结束的地方
quas2dX
加班,复用性不好,模拟;传感器,物联网gps定位;
ios leader ui 网络多线程,基本的(技术);工具类经常使用的东西,cto 主要技术负责人;那个模块细节的问题;ui改动需求,细节问题,需求
社交,网络多线程,实际的价值; 前期:ui高级 高级最后的 关于细节的问题,项目,新浪微博,细节的东西,
工具类封装;座位的事;本身组团;//本身
填充在剪切以后调用
自定义UIImageView
png 浏览器;搜图片
NSTimer 定时的更新数据;
CADisplayLink 更新动画的时候调用,一秒调用60次;
arc中经过C语言建立的函数,若是函数中保存create,retain,copy 必须调用release;
CGContextRef ctx =CGPathCreateMutable();须要释放内存
0512彩票
导航控制器copy viewControllers
1>资源
2>图标 application
3>去掉玻璃球prerender ,使其扁平化 勾选去掉玻璃花效果(删去程序,点文件夹再沟),IOS5以前在配置文件中加一个行见0512的彩票视频
4>lanch 上面下面的黑,改Jasonios7 让其有四村的图片;
5>启动去掉状态栏 去掉沟,启动时全屏 general里面,
6>导航控制器设置根控制器
7点击的时候隐藏下面的工具条hidden
- (void)setHighlighted:(BOOL)highlighted
{
//重写这个方法让按钮normal - highlight(使这个为瞬态) -disable
// [super setHighlighted:YES];//设置按钮为高亮状态
}
系统ios6
设置状态栏颜色0935,如何看??只能经过application,
ios 6 适配
状态栏的设置批量在主题里面设置;
guide -- 经验-- UTransition??
1038看文档??如何分析??
strory 里面勾选界面
+initia
1156如何调bug
sdk 7.1 才能调用ios7 的方法;
编译器适配:
#ifdef _
else
shift 等比例缩放
ios6 00 与 ios7 00 1433总结 结构 器之间???
st里面的上下扩展,修改了相对的0点
在ios7 6 垂直方向都不变
scollView 作穿透 :不是scroolView 的时候,直接都去掉沟
UIStoryboard 里面也能够拉,strch 只有imageView能够拉伸
你
class 懒加载 小写的class
1>代码优化:使某些不能够点击
2>
指向函数:
block 本质是内敛函数,初学能够理解为宏定义,在编译的时候能够替换宏名
block使用copy
=1113以前的没听打电话去了;
建立xib 的时候须要制定重用的标示;'
xib和peng 不须要后缀
拖con了特殊cell inset
item =row
maskToBounds
#import "MJSettingItem.h"
@implementation MJSettingItem
+(instancetype)itemWithIcon:(NSString *)icon title:(NSString *)title destVc:(Class)destVc
{
#warning item仍是self
//建立item,使用self能够item???
MJSettingItem *item = [[self alloc] init];
item.icon = icon ;
item.title = title ;
item.destVc = destVc;
return item;
}
NSProxy.h
class
Returns self (the class object). 返回本身,返回类对象
+ (Class)class
Return Value 这是类方法 返回类对象
@property(nonatomic,assign) Class destVc; class 类方法>
一个界面对应一个控制器
loadView 装载的时候,直接复制webView 重写loadView
0920为何要强转
控制器包装成导航控制器
父类对象指向子类须要强转
JavaScript 写对几条就编译几条
1015使用javascript
typeof (10) = int 动态的获取某个变量的类型
typeof self;
- (void)viewDidLoad
{
[super viewDidLoad];
// 把self变成弱指针
// __unsafe_unretained 修饰的若是对象释放了, 变量依然指向释放前的地址
// __unsafe_unretained NJShareViewController *unRetainSelf = self;
// __weak 修饰的若是对象释放了, 变量自动指向nil
// __weak NJShareViewController *unRetainSelf = self;
__weak typeof(self) unRetainSelf = self;//获取self的类型
// int a = 5;
// typeof(100) b = 5;
// Do any additional setup after loading the view.
NJSettingItem *item0 = [NJSettingArrowItem itemWithIcon:nil title:@"新浪微博" destVc:nil];
NJSettingItem *item1 = [NJSettingArrowItem itemWithIcon:nil title:@"短信分享" destVc:nil];
item1.option = ^{
if (![MFMessageComposeViewController canSendText]) return;
MFMessageComposeViewController *vc = [[MFMessageComposeViewController alloc] init];
// 设置短信内容
vc.body = @"吃饭了没?";
// 设置收件人列表
vc.recipients = @[@"10010", @"123456"];
// 设置代理
vc.messageComposeDelegate = unRetainSelf;
// 显示控制器
[unRetainSelf presentViewController:vc animated:YES completion:nil];
sel.age = 10;
// _age = 10;
// self->_age = 10;
};
0519触摸
当前的控制器有group;
NJSettingGroup *group = [[NJSettingGroup alloc] init];
@property (nonatomic, strong) NSArray *items;
group.items = @[item0, item1, item2];(数组strong)
item2.option = ^{ // 设置代理
vc.mailComposeDelegate = self;}(这个中又有self 组成强应用的闭环)
在iOS中不是任何对象都能处理事件,只有继承了UIResponder的对象才能接收并处理事件。咱们称之为“响应者对象”
UIApplication、UIViewController、UIView都继承自UIResponder,所以它们都是响应者对象,都可以接收并处理事件
UIResponder内部提供了如下方法来处理事件
触摸事件
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
加速计事件
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event;
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event;
- (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event;
远程控制事件
- (void)remoteControlReceivedWithEvent:(UIEvent *)event;
UIView是UIResponder的子类,能够覆盖下列4个方法处理不一样的触摸事件
一根或者多根手指开始触摸view,系统会自动调用view的下面方法
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
一根或者多根手指在view上移动,系统会自动调用view的下面方法(随着手指的移动,会持续调用该方法)
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
一根或者多根手指离开view,系统会自动调用view的下面方法
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
触摸结束前,某个系统事件(例如电话呼入)会打断触摸过程,系统会自动调用view的下面方法
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
提示:touches中存放的都是UITouch对象
触摸:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
touchesBegan->touchesMoved->touchesEnded(必须的过程)
当用户用一根触摸屏幕时,会建立一个与手指相关联的UITouch对象
mutiple touch 勾选 支持多点触摸
一个手指对应一个touch对象
// 当前触摸点
CGPoint current = [touch locationInView:superView];//self];
// 上一个触摸点
CGPoint previous = [touch previousLocationInView:self];
为何不精准??
一次完整的触摸过程,会经历3个状态:
触摸开始:- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
触摸移动:- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
触摸结束:- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
触摸取消(可能会经历):- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
4个触摸事件处理方法中,都有NSSet *touches和UIEvent *event两个参数
一次完整的触摸过程当中,只会产生一个事件对象,4个触摸方法都是同一个event参数
若是两根手指同时触摸一个view,那么view只会调用一次touchesBegan:withEvent:方法,touches参数中装着2个UITouch对象
若是这两根手指一前一后分开触摸同一个view,那么view会分别调用2次touchesBegan:withEvent:方法,而且每次调用时的touches参数中只包含一个UITouch对象
根据touches中UITouch的个数能够判断出是单点触摸仍是多点触摸
NSString经过代码建立
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setup];
}
return self;
}
//经过文件建立
- (id)init(O_O)?WithCoder:(NSCoder *)aDecoder
{
if (self = [super initWithCoder:aDecoder]) {
[self setup];
}
return self;
}
事件传递面试cha,子控件没有实现touchBegin方法,会将事件传递给父控件
什么是响应者链条
应用场景
怎么响应的??
面试常考?????响应者链条视频面试常考
UIGestureRecognizer是一个抽象类,定义了全部手势的基本行为,使用它的子类才能处理具体的手势
这个类不能建立对象
代理名称:UI ,方法去掉UI
美术,图书故宫,汽车,快用苹果助手 显示包内容:那图片
搜简历 看简历,企业帐号,看简历的帐号
夏国华:2011ios开发
什么是响应者链条:由响应者组成的链条
什么是响应者:继承UIrespond的对象
如何响应:本身是否是控制器的view ?(本身问本身的问题,响应者的方法:三个触摸的方法;可以响应就是实现了touch的三个方法) 不是 传给父控件,是 传给控制器
父控件或控制器没有实现触摸响应的事件,继续上传,直到找不到那么就丢弃
响应者的应用场景:在子控件中让父控件也响应触摸事件,在子控件的方法中调用父控件的触摸方法,而且把子空间传上去;
触摸事件的传递:从父控件传到子控件,如何找到最合适的控件来处理事件?
本身是否能接收触摸事件?
触摸点是否在本身身上?
从后往前遍历子控件,重复前面的两个步骤
若是没有符合条件的子控件,那么就本身最适合处理
UISwipeGestureRecognizer *swipGesture1 = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipView:)];
添加监听事件:会将swipGesture当作参数传给swipView 的参数
autoLayout 去掉才会出现:自动边缘四周的画面
//----------代理传值方法总结------------代理传值方法总结----------代理传值方法总结-------------
//这里的btn点击了,调用代理执行方法把btn做为参数,btn.tag
//传给实现代理的对象在代理对象中拿到这个tag的值进行一些操做
// NJTabBar.m文件
- (void)btnOnClick:(UIButton *)btn
{
// -1.通知代理
if ([self.delegate respondsToSelector:@selector(tabBar:from:to:)]) {
[self.delegate tabBar:self from:self.currentSelectBtn.tag to:btn.tag];
}
// NJTabBar.h文件
@class NJTabBar;
@protocol NJTabBarDelegate <NSObject>
- (void)tabBar:(NJTabBar *)tabBar from:(NSInteger)from to:(NSInteger)to;
@end
@interface NJTabBar : UIView
@property (nonatomic, weak) id<NJTabBarDelegate> delegate;
@end
#import "NJTab BarController.h"
NJTabBarController.m 文件 遵照代理代理:
@interface NJTabBarController ()<NJTabBarDelegate>
#pragma mark - NJTabBarDelegate //实现这个代理方法
- (void)tabBar:(NJTabBar *)tabBar from:(NSInteger)from to:(NSInteger)to
{
// 切换子控制器
self.selectedIndex = to;
}
//-------代理传值方法总结--------代理传值方法总结-------------代理传值方法总结-----------------
子类继承父类先调用子类的方法再调用父类的方法(若是子类中有函数调用super的方法会去父类中调用父类的方法)
UIView先绘制在图层上,系统将图层显示在屏幕上
layer.contents =(id) [UIImage imageNamed:@"12"].CGImage;
UIView和CALayer的选择
经过CALayer,就能作出跟UIImageView同样的界面效果
既然CALayer和UIView都能实现相同的显示效果,那究竟该选择谁好呢?
其实,对比CALayer,UIView多了一个事件处理的功能。也就是说,CALayer不能处理用户的触摸事件,而UIView能够
因此,若是显示出来的东西须要跟用户进行交互的话,用UIView;若是不须要跟用户进行交互,用UIView或者CALayer均可以
固然,CALayer的性能会高一些,由于它少了事件处理的功能,更加轻量级
每个UIView内部都默认关联着一个CALayer,咱们可用称这个Layer为Root Layer(根层)
全部的非Root Layer,也就是手动建立的CALayer对象,都存在着隐式动画
什么是隐式动画?
当对非Root Layer的部分属性进行修改时,默认会自动产生一些动画效果
而这些属性称为Animatable Properties(可动画属性)
列举几个常见的Animatable Properties:
bounds:用于设置CALayer的宽度和高度。修改这个属性会产生缩放动画
backgroundColor:用于设置CALayer的背景色。修改这个属性会产生背景色的渐变更画
position:用于设置CALayer的位置。修改这个属性会产平生移动画
返回按钮由上一个控制器决定;在上一个控制器setback,
CAPropertyAnimation的子类
属性解析:
fromValue:keyPath相应属性的初始值
toValue:keyPath相应属性的结束值
随着动画的进行,在长度为duration的持续时间内,keyPath相应属性的值从fromValue渐渐地变为toValue
若是fillMode=kCAFillModeForwards和removedOnComletion=NO,那么在动画执行完毕后,图层会保持显示动画执行后的状态。但在实质上,图层的属性值仍是动画执行前的初始值,并无真正被改变。好比,CALayer的position初始值为(0,0),CABasicAnimation的fromValue为(10,10),toValue为(100,100),虽然动画执行完毕后图层保持在(100,100)这个位置,实质上图层的position仍是为(0,0)
// UIView 与图层的关系?
当UIView须要显示到屏幕上时,会调用drawRect:方法进行绘图,而且会将全部内容绘制在本身的图层上,绘图完毕后,系统会将图层拷贝到屏幕上,因而就完成了UIView的显示
换句话说,UIView自己不具有显示的功能,是它内部的层才有显示功能
每个UIView内部都默认关联着一个CALayer,咱们可用称这个Layer为Root Layer(根层)
//view.layer.delegate == view;
//----------------view的完整显示过程-----------------------------
1. view.layer会准备一个Layer Graphics Contex(图层类型的上下文)
2. 调用view.layer.delegate(view)的drawLayer:inContext:,并传入刚才准备好的上下文
3. view的drawLayer:inContext:方法内部又会调用view的drawRect:方法
4. view就能够在drawRect:方法中实现绘图代码, 全部东西最终都绘制到view.layer上面
5. 系统再将view.layer的内容拷贝到屏幕, 因而完成了view的显示
//----------------view的完整显示过程-----------------------------
coreQuatz 库不能重复添加,重复添加汇报连接错误,解决方法:重建工程:从新添加文件代码和UIStoryboardSegue
daima
// 1.建立动画对象
CABasicAnimation *anim = [CABasicAnimation animation];
// 2.设置动画对象
// keyPath决定了执行怎样的动画, 调整哪一个属性来执行动画
anim.keyPath = @"bounds";
// anim.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, 0)];
anim.toValue = [NSValue valueWithCGRect:CGRectMake(0, 0, 200, 200)];
anim.duration = 2.0;
/**让图层保持动画执行完毕后的状态**/
// 动画执行完毕后不要删除动画
anim.removedOnCompletion = NO;
// 保持最新的状态
anim.fillMode = kCAFillModeForwards;
// 3.添加动画
[self.layer addAnimation:anim forKey:nil];
block 封装函数的变化点
- (void)enumerateObjectsUsingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block NS_AVAILABLE(10_6, 4_0);
使用给定的block 执行数组中的对象,从第一个对象执行到最后一个对象,block是应用到每个对象的代码
int stopIndex = 1;
NSArray *array = @[@"张三", @"李四", @"王五", @"赵六"];
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSLog(@"第 %d 项内容是 %@", (int)idx, obj);
if ([@"王五" isEqualToString:obj] || idx == stopIndex) {
*stop = YES;
}
}];
注意,
for (int i = 0; i < 10; ++i) {
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
[self operationAction:@(i)];
}];
[self.myQueue addOperation:op];
}
//----------------block强引用---------------------------------------------------
@property (nonatomic, strong) NSMutableArray *myBlocks;
#pragma mark 将代码改成调用self的方法
int(^sum)(int, int) = ^(int x, int y) {
return [self sum:x y:y];
};
[self.myBlocks addObject:sum];
#pragma mark 对象被释放时自动调用
- (void)dealloc
{
NSLog(@"DemoObj被释放");
}
循环引用的结果就是对象没法被释放!
上述代码:self 强应用myBlaocks ,myBlocks 强引用sum sum强引用self 构成强引用的循环三角形(没法释放)
局部变量默认都是强引用的,离开其所在的做用域以后就会被释放
使用__weak关键字,能够将局部变量声明为弱引用
__weak DemoObj *weakSelf = self;
在Block中引用weakSelf,则Block不会再对self作强引用
int(^sum)(int, int) = ^(int x, int y) {
return [weakSelf sum:x y:y];
};
//----------------block强引用---加上最后一句-<2>解决问题-----------------------------------------------
#warning 注释---******* 3> option被item2强引用 ??????
item2.option = ^{
// 判断当前设备可否发送邮件 ,不能发邮件
if (![MFMailComposeViewController canSendMail]) return;
MFMailComposeViewController *vc = [[MFMailComposeViewController alloc] init];
// 设置邮件主题
[vc setSubject:@"会议"];
// 设置邮件内容
[vc setMessageBody:@"今天下午开会吧" isHTML:NO];
// 设置收件人列表
[vc setToRecipients:@[@"643055866@qq.com"]];
// 设置抄送人列表
[vc setCcRecipients:@[@"1234@qq.com"]];
// 设置密送人列表
[vc setBccRecipients:@[@"56789@qq.com"]];
// 添加附件(一张图片)
UIImage *image = [UIImage imageNamed:@"lufy.jpeg"];
NSData *data = UIImageJPEGRepresentation(image, 0.5);
[vc addAttachmentData:data mimeType:@"image/jepg" fileName:@"lufy.jpeg"];
#warning 注释--- 4> option中的block强引用着当前类(造成强应用闭环)
// 设置代理
vc.mailComposeDelegate = self;
// 显示控制器
[self presentViewController:vc animated:YES completion:nil];
};
#warning 注释---*******1> group(被本类强引用,里面的成员)
NJSettingGroup *group = [[NJSettingGroup alloc] init];
group.items = @[item0, item1, item2];
[self.data addObject:group];
#warning 注释---*******2> items(被group强引)
// 把self变成弱指针
// __unsafe_unretained 修饰的若是对象释放了, 变量依然指向释放前的地址
// __unsafe_unretained NJShareViewController *unRetainSelf = self;
// __weak 修饰的若是对象释放了, 变量自动指向nil
// __weak NJShareViewController *unRetainSelf = self;
<2> __weak typeof(self) unRetainSelf = self;
__block 能够修改block的值 少用:破坏可读性,偶尔性过高,不容许修改快代码中的指针,能够修改快代码中指针的内容,
对象有两个地址:指向对象的地址(两个),对象本省的地址(一个,不能够修改),地址中存放内容(能够修改),
__weak NJcontroller *weakself = self;
}
//----------------block强引用---------------------------------------------------
对象添加到数组会被数组强引用;[self sum:x ,y] self 会对sum强引用 ????强引用??
self 中有property (nonatomic, strong) NSMutableArray *myBlocks;
self 会强应用myBlocks
sum 会强引用self
int(^sum)(int, int) = ^(int x, int y) {
return [self sum:x y:y];
};
[self.myBlocks addObject:sum];
myblock会强引用sum 致使的循环引用
代码网站:githup 和codeforapp 两个网站 上面有不少内容
//----------------block循环引用---------------------------------------------------
for (int i = 0; i < 10; ++i) {
[self.queue addOperationWithBlock:^{
self ->queue ->block 在主线程的运行循环中,队列的代码块执行完毕会销毁
[self demoOp:@(i)];
}];
}
//----------------block循环引用---------------------------------------------------
快代码 准备的函数,随时被调用,预先准备好的,
快代码实现控制器中的传值,
1>快代码预先准备的代码块,在须要的时候执行
2>准备一个快代码,传递给detail
3>快代码自行时间有detail(定义快代码) 决定
快代码比较灵活,若是监听的事件比较多,仍是使用代理比较好
堆中存放对象,栈中存放地址
?const 的做用
CGPathCreateMutableCopyByTransformingPath(<#CGPathRef path#>, <#const CGAffineTransform *transform#>)
dispatch_queue_t q = dispatch_queue_create(<#const char *label#>, <#dispatch_queue_attr_t attr#>)
const 锁定指向lable的指针,
UIKIT_EXTERN NSString *const NSTabColumnTerminatorsAttributeName
锁定的是NSTabColumnTerminatorsAttributeName这内容;
//const 指针能够修改,指针所指向
//----------------串行队列-----------------------------
串行队列前面的没有执行完后面的队列没法执行
并行队列,先同步后异步 顺序执行:
并行队列:先异步后同步,混合执行,同步异步混合;先同步后异步,会对后面的阻塞;
同步操做在主线程上,异步会新建线程,在并行队列中:异步会新建多个线程,在串行队列中异步只会新建一个线程
全局队列:同步操做顺序进行,在主线程上,会阻塞后面的,异步操做无序,会新建线程,无序进行
//----------------建立全局对列-----------------------------
dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//执行同步操做,在主线程上
//执行异步操做,在子线程上仍是会有顺序
//---------------------------------------------
//-------------------主(线程)队列--------------------------
#pragma mark - 主(线程)队列,保证操做在主线程上执行
// 每个应用程序都只有一个主线程
// 为何须要在主线程上工做呢?
// 在iOS开发中,全部UI的更新工做,都必须在主线程上执行!
dispatch_queue_t q = dispatch_get_main_queue();
// 主线程是由工做的,并且除非将程序杀掉,不然主线程的工做永远不会结束!
// 阻塞了!!!
// dispatch_sync(q, ^{
// NSLog(@"come here baby!");
// });
// 异步任务,在主线程上运行,同时是保持队形的
同步任务:不会新建线程,运行在主线程上只能在(队列在哪里,任务就在哪里)主线程上,
异步任务:会新建线程;同步任务能够堵住异步任务
同步任务会堵死程序
主线程的任务不会结束(除非退出程序),
全局队列不能跟踪:本身建立的队列能够跟踪
全局队列能够指定优先级,本身建立的队列不能建立优先级
主队列添加任务在主队列工做,本身建立的nsopration 自动的并行异步
An NSThread object controls a thread of execution. Use this class when you want to have an Objective-C method run in its own thread of execution. Threads are especially useful when you need to perform a lengthy task, but don’t want it to block the execution of the rest of the application. In particular, you can use threads to avoid blocking the main thread of the application, which handles user interface and event-related actions. Threads can also be used to divide a large job into several smaller jobs, which can lead to performance increases on multi-core computers.
一个线程对象控制一个线程的执行,当你想要一个oc 的方法运行在执行的线程上,就使用这个类,当你须要执行一个长时间的任务,线程是很是有用的,可是不要去阻塞其余应用程序的执行,特殊是:你可使用线程避免阻塞主线程
主线程来更新界面相关的动做事件,线程能够划分一个大的任务为几个小的任务,在多核的设备中,这样能够提升性能
1>NSObject 多线程方法没有自动释放池
2>在oc,当自动释放池被释放或销毁的时候,会向自动释放池中得全部对象发送release消息
//可是使用nsthread 的时候系统
同步任务在多线程中少用,(少用)
串行 异步:
并行 异步:
NSAutoreleasePool
{
for (int i = 0; i < 10; ++i) {
// NSAutoreleasePool也能够在这里加自动释放池,这样的每次执行完毕对象会释放{
NSString *str = @"Hello World";
str = [str stringByAppendingFormat:@" - %d", i];
str = [str uppercaseString];
NSLog(@"%@", str);
// }
}
} 问:以上代码存在什么样的问题?若是循环的次数很是大时,应该如何修改?
#pragma mark - 串行(一个接一个,排队跑步,保持队形)队列
- (void)gcdDemo1
{
// 将操做放在队列中
// 在C语言函数中,定义类型,绝大多数的结尾是_t或者ref
// 使用串行队列,的异步任务很是很是很是有用!新建子线程是有开销的,不能无休止新建线程
// 便可以保证效率(新建一个子线程),用可以实现并发
// 应用案例:
// 1> 从网络上上下载图片
// 2> 滤镜(高光,红眼...)
dispatch_queue_t q = dispatch_queue_create("cn.itcast.gcddemo", DISPATCH_QUEUE_SERIAL);
// 非ARC开发时,千万别忘记release
// dispatch_release(q);
// 串行行队列的同步任务,一样会在主线程上运行
// 提示:在开发中极少用
// 面试中有可能会问!
for (int i = 0; i < 10; ++i) {
// 同步任务顺序执行
dispatch_sync(q, ^{
NSLog(@"%@ %d", [NSThread currentThread], i);
});
}
for (int i = 0; i < 10; ++i) {
// 异步任务,并发执行,可是若是在穿行队列中,仍然会依次顺序执行
dispatch_async(q, ^{
// [NSThread currentThread] 能够在开发中,跟踪当前线程
// num = 1,表示主线程
// num = 2,表示第2个子线程。。。
NSLog(@"%@ %d", [NSThread currentThread], i);
});
}
}
NSThread 对象的做用:
一个线程对象控制一个线程的执行,当你想要一个oc 的方法运行在执行的线程上,就使用这个类,当你须要执行一个长时间的任务,线程是很是有用的,可是不要去阻塞其余应用程序的执行,特殊是:你可使用线程避免阻塞主线程
主线程来更新界面相关的动做事件,线程能够划分一个大的任务为几个小的任务,这样能够提升性能
互斥锁:每一次只容许一个任务执行操做
//
// DemoObj.m
// 05.单例
//
// Created by apple on 14-4-23.
// Copyright (c) 2014年 itcast. All rights reserved.
//
#import "DemoObj.h"
@implementation DemoObj
static DemoObj *instance;
//---------------------单例的写法,面试常考------------------------
/**
1. 重写allocWithZone,用dispatch_once实例化一个静态变量
2. 写一个+sharedXXX方便其余类调用
*/
// 在iOS中,全部对象的内存空间的分配,最终都会调用allocWithZone方法
// 若是要作单例,须要重写此方法
// GCD提供了一个方法,专门用来建立单例的
+ (id)allocWithZone:(struct _NSZone *)zone
{
static DemoObj *instance;
// dispatch_once是线程安全的,onceToken默认为0
static dispatch_once_t onceToken;
// dispatch_once宏能够保证块代码中 i的指令只被执行一次
dispatch_once(&onceToken, ^{
// 在多线程环境下,永远只会被执行一次,instance只会被实例化一次
instance = [super allocWithZone:zone];
});
return instance;
}
+ (instancetype)sharedDemoObj
{
// 若是有两个线程同时实例化,颇有可能建立出两个实例来
// if (!instance) {
// // thread 1 0x0000A
// // thread 2 0x0000B
// instance = [[self alloc] init];
// }
// // 第一个线程返回的指针已经被修改!
// return instance;
return [[self alloc] init];
}
@end
// DemoObj.m
// 0526_单利
//
// Created by 汪刚 on 07-9-19.
// Copyright (c) 2007年 it.cast. All rights reserved.
//
#import "DemoObj.h"
@implementation DemoObj
static DemoObj *instance
//
+(id)allocWithZone:(struct _NSZone *)zone
{
static DemoObj*instance;
//这个
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//这个中得代码只执行一次
instance = [super allocWithZone:zone];
});
return instance;
}
+(instancetype)shareDemoObj
{
return [[self alloc] init];
}
//----------------------单例的写法,面试常考-----------------------
oc函数中参数凡是看到** 传入对象的地址
+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:/*传地址*/(NSURLResponse **)response error:(NSError **)error
1M主线程,每一个线程对应一个栈区,子线程对应512K的栈区
堆区,有系统管理和维护 包含全部应用程序共享的(包含内存,虚拟内存(磁盘内存))
对象在堆中,内存没有释放(没法访问)那么对象就是内存泄露
堆系统管理全部对象的,
NSData 二进制
NULL = 0;
nil 地址指向0 的对象;调用任何方法不会报错; =空
//--------------------- performSelectorOnMainThread------------------------
-(void)setImagePath:(NSString *)imagePath
{
NSLog(@"%@ = \n",[NSThread currentThread]);
//1>模拟下载延时
[NSThread sleepForTimeInterval:5.0];
//A Boolean that specifies whether [the current thread blocks until after the specified selector is performed on the receiver on the main thread].
//2>设置头像,苹果容许inbackground方法在后台更新ui线程,强烈建议不要这么作
//yes直到方法调用为yes
[self performSelectorOnMainThread:@selector(setImage:) withObject:[UIImage imageNamed:imagePath] waitUntilDone:NO];//调用的方法num =1;
}
//1>设置头像
-(void)setImage:(UIImage *)image
{
NSLog(@"%@ = setImage\n",[NSThread currentThread]);
//image = [UIImage imageNamed:@"头像1.png"];
self.imageView.image = image;
//根据头像自动调整大小
[self.imageView sizeToFit];
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self.view addSubview:self.imageView];
//在后台执行这个程序
for (int i = 0; i<50; i++) {
[self performSelectorInBackground:@selector(setImagePath:) withObject:@"头像1.png"];
}
//调用的方法Num= 1-50;
}
//--------------------- performSelectorOnMainThread------------------------
apach演示:拖两个文件到本地服务器 打开
再输密码
界面(uitextFiled)+ UILabel
2>拖线
3>
NSMutableArray *arrM
init
整数 NSNumber 整数对象
网络数据包装
assign NSInteger
@(12)
输出为NSNumber 类型 %@ @(12)
strong NSNumber* userNum %@
在处理网络数据的时候,数值的属性 能够省略不少麻烦
异步操做不会阻塞线程
打印description 便于调试
跟踪数组,打印数组
自动备份;勾上;必定要掌握:switch 备份
// copy 创建副本 为了修改属性互不影响
#define kBaseUrl @"http://192.168.1.1"
有中文的时候:url = [url string +中文转义];
asi 建议须要的时候本身去自学,http 访问终结者
非Arc
1>第三方框架:不须要去看全部的源程序
2>不须要熟悉全部的功能以后再使用
刷新表格会从新调用数据源的方法
modal 是临时的视图控制器
横竖频还须要修改plist 里面的播放的顺序
以shared standart default 开头表明是单例
@interface Video : NSObject
// copy 创建副本 为了修改属性互不影响
@property (nonatomic, copy) NSNumber *videoId;
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSNumber *length;
@property (nonatomic, copy) NSString *videoURL;
@property (nonatomic, copy) NSString *imageURL;
@property (nonatomic, copy) NSString *desc;
@property (nonatomic, copy) NSString *teacher;
- (instancetype)initWithDict:(NSDictionary *)dict;
+ (instancetype)videoWithDict:(NSDictionary *)dict;
// 在处理网络数据解析的时候,数值型的属性,必定用NSNubmer,会避免不少麻烦
@property (nonatomic, strong) NSNumber *userId;
小技巧:若是在OC中看到枚举类型的起始数值不为0,说明若是传入0做为参数,意味着不会作任何附加操做
结果就是方法运行的效率最高
一般开发时,拿到数据字典,会字典转模型,所以不须要对反序列化的结果进行处理
/*
(下面的ok)
void(^me)(UIImage *image) = ^(UIImage *image) {
self.imageView.image = image;
};
(类型的时候省略block的名称) void(^me)(UIImage *image) = ^(UIImage *image) {
self.imageView.image = image;
};
completion(参数)调用
==
^(UIImage *image) {
self.imageView.image = image;
}
==
void (^)(UIImage *image)
*/
涉及用户隐私的 都不须要用get 方法
不能把密码保存在本地:
不能直接传输用户的密码:
request 请求用可变的nsmuatblequequest post 须要更改请求?
和用户隐私相关的用post 没有隐私的时候用get 能够用浏览器辅助yong
post 的文件不能覆盖
post 会有大小的限制
全部的网络都是异步的
request.HTTPMethod = @"PUT";只要不是get方法 必须是可变的
php 输入张三 zhang 的密码后,返回null null 是由于加密后,在php文件中须要更改 加密后的密码
后面:添加psot 文件夹,系统也是这么设置的
//---------------------------------------------
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
didSendBodyData:(int64_t)bytesSent
totalBytesSent:(int64_t)totalBytesSent
totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
{
float progress = (float)totalBytesSent/totalBytesExpectedToSend;
double delayInSeconds = 1/30;
#warning 注释---???此处若是没有延时,不会重绘?? 刷新频率过高???
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
self.progressView.progress = progress;
});
NSLog(@"progress- = %.2f\n",progress);
// NJProgressView *progress1 = [[NJProgressView alloc] init];
}
- (UILabel *)label
{
if (!_label) {
_label = [[UILabel alloc] initWithFrame:self.bounds];
_label.textAlignment = NSTextAlignmentCenter;
_label.font = [UIFont systemFontOfSize:14.0];
_label.textColor = [UIColor redColor];
[self addSubview:_label];
}
return _label;
}
- (void)setProgress:(float)progress
{
_progress = progress;
int value = progress * 100;
self.label.text = [NSString stringWithFormat:@"%d%%", value];
NSLog(@"%@", [NSThread currentThread]);
// 绘制圆弧, 调用drawRect
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect
{
// 1. context
CGContextRef context = UIGraphicsGetCurrentContext();
// 2. 给context添加路径,圆弧
CGFloat x = self.bounds.size.width / 2.0;
CGFloat y = self.bounds.size.height / 2.0;
CGFloat r = MIN(x, y) - 5;
CGFloat startA = -M_PI_2;
CGFloat endA = startA + self.progress * 2 * M_PI;
// 顺时针绘制,须要设置成false
CGContextAddArc(context, x, y, r, startA, endA, false);
// 3. 设置颜色,线宽
CGContextSetRGBStrokeColor(context, 1.0, 0.0, 0.0, 1.0);
CGContextSetLineWidth(context, 3.0);
// 4. 绘制
CGContextDrawPath(context, kCGPathStroke);
}
//---------------------------------------------
/** 下载是 get 方法 */
- (IBAction)download
{
// 1. url
NSURL *url = [NSURL URLWithString:@"http://localhost/123.zip"];
// 2. request
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:10.0f];
// 3. sesssion
NSURLSession *session = [NSURLSession sharedSession];
// 4. 下载任务
[[session downloadTaskWithRequest:request completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
// 用urlsession下载的文件,会保存到临时文件夹中
// 若是不进行特殊的处理,就会被删除掉
NSLog(@"%@", location.path);
// 解压缩
// 小说,下载的是zip文件,解压缩zip文件,zip不须要
// 目标文件夹
// Documents 只能保存应用程序自己由用户生成的文件,不能把网络下载的文件放在此文件夹中
// Cache:从新启动不会丢失
// Tmp:从新启动会清空
// 偏好设置:会备份
NSString *cacheDir = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];
[SSZipArchive unzipFileAtPath:location.path toDestination:cacheDir];
}] resume];
}
/**
completionHandler 结束后的操做
*/
文件下载从服务器下载到手机,;;能够指定下载的路径
备课笔记
1. POST提交数据 application/x-www-form-urlencoded
================================================================================
application/x-www-form-urlencoded在HTTP网络访问中一般用于向服务器提交用户隐私相关的信息
缘由以下:
1> 使用GET方法全部参数都包含在URL中,这样用户信息会暴露在URL中,若是黑客获取到服务器访问日志文件。
则意味着会出现用户数据泄露的问题
2> 服务器的访问日志是黑客攻击的重点对象之一
在iOS开发中,使用application/x-www-form-urlencoded提交POST请求时,程序员只须要负责包装数据体便可
其余诸如:
1> Content-Type
2> Content-Length
3> 数据体字符串中的百分号转义
...
系统会默认处理,无需程序员作任何操做
实例代码以下:
// 1. 设置请求的HTTP方法
request.HTTPMethod = @"POST";
// 2. 拼接数据体字符串
NSString *bodyStr = [NSString stringWithFormat:@"username=%@&password=%@", self.userNameText.text, pwd];
// 3. 使用NSData设置HTTPBody
request.HTTPBody = [bodyStr dataUsingEncoding:NSUTF8StringEncoding];
2. 数据安全
================================================================================
在网络传输中,若是涉及用户隐私的数据,请记住如下两点:
1> 任何应用程序都不能"在本地直接存储与安全相关的用户信息"
2> 任何应用程序在于服务器传递数据时,都"不能直接传输与安全相关的用户信息"
一般使用MD5对用户的密码进行加密,MD5函数具备如下特色:
1> 算法不可逆,即便用散列后的MD5字符串,在知道MD5算法的前提下,仍然没法反算会初始值
2> 长度固定,使用MD5函数处理后的字符串长度统一为32位
3> 对于相同字符串使用MD5函数,每次的计算结果是相同的
因为目前网络上有160TB的数据库,记录已经破解的,MD5加密字符串
为了保证用户数据的安全,在使用MD5对用户密码进行处理时,能够为密码加点"盐"
NSString *saltStr = [NSString stringWithFormat:@"%@%@", pwd, kSaltStr];
return [saltStr md5String];
3. POST上传 multipart/form-data
================================================================================
multipart/form-data是目前很是流行的向网络服务器上传文件的一种方式,具备如下几个特色:
1> 国内的绝大多数网站都采用这种方式上传文件,网络上要上传用户头像,一般都使用此种方式
2> 会限制上传文件的大小通常是2M或者更小
3> POST上传的文件在服务器上不能重名,若是指定的文件名重复,则没法上传
要在iOS中实现文件上传,须要拼接一个NSData,具体个数以下:
# 头部字符串
--'本次上传标示字符串' \n
Content-Disposition: form-data; name="服务端字段"; filename="上传文件名" \n
Content-Type: '上传文件MIMEType' \n\n
# 上传文件的二进制数据
# 底部字符串
--本次上传标示字符串 \n
Content-Disposition: form-data; name="submit" \n\n
Submit \n
--'本次上传标示字符串'-- \n
除此以外,还需设置网络请求的'Content-Type'和'Content-Length'
// Content-Type
NSString *typeStr = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", randomIDStr];
[requestM setValue:typeStr forHTTPHeaderField:@"Content-Type"];
// Content-Length
NSString *lengthStr = [NSString stringWithFormat:@"%ld", (long)[dataM length]];
[requestM setValue:lengthStr forHTTPHeaderField:@"Content-Length"];
网络请求准备就绪以后,直接使用NSURLConnection的异步方法便可上传文件。
4. POST上传 文件名
================================================================================
为了解决POST上传文件名不能重复的问题,一般采用时间戳做为上传文件的文件名,示例代码以下:
// 日期的格式化类
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
// 设置日期格式[年月日时分秒]
formatter.dateFormat = @"yyyyMMddHHmmss";
// 使用当前系统时间做为文件名
NSString *fileName = [formatter stringFromDate:[NSDate date]];
5. NSURLSession
================================================================================
1> NSURLSession是iOS7中新的网络接口,与NSURLConnection是并列的
2> NSURLSession是线程安全的思路
3> NSURLSession提供了后台上传下载的支持
使用NSURLSession的步骤
1> 实例化NSURLSession对象,若是不使用代理,可使用系统提供全局网络回话单例
[NSURLSession sharedSession]
2> 由session发起任务
(1) 数据任务 NSURLSessionDataTask
(2) 上传任务 NSURLSessionUploadTask
(3) 下载任务 NSURLSessionDownloadTask
3> 注意:全部任务默认都是挂起的,须要调用resume方法,启动任务
//---------------------------------------------
put 上传通常传到,weddav 服务器中,能够传的数据比较大
文件下载:从指定的服务器中下载数据 默认会存在 tmp 文件夹下面,(这个文件夹中的)
//---------------------------------------------
responseSerializer 序列化
子类中的找不到所须要功能,类型的时候,到父类中得去找有没有须要的功能;
先去头文件中框架 看看简介
xml解析器 设置代理 六个方法解析 xml
monitor [ visible
青花瓷 在 工做中抓数据青花瓷安装
UIScrollView 的bounds 和其contentoffset 是同样的
#warning 注释---微博:笔记
1>服务器
2>项目组:
1>开发组(iOS Android)
2>服务器开发组
3>产品需求组
4>测试组
5>美工组
去大公司,积累规范
1>
项目文档
1>需求文档-产品经理,怎么写
2>接口文档-服务器
3>开发文档 - 开发进度
4>产品文档- 相似商品计划书
5>原型图 - 相似需求文档 (index.html 首页)
项目架构:
1>UI界面层
2>业务层
3>网络处理层
4>工具层
5>网络处理层
分配任务
1>功能和模块分
2>项目的架构(各个UI,网络,不一样的人)
3>混合分
新浪开放了部分数据,开放了部分数据接口
1>下载安装包 获取里面的资源
launchimage 里面全部的设备都要有图标,修改json 参见新浪微博的图标json
1>project Hide during application launch(加载的时候隐藏状态栏,不要时加载完)
2>完成加载显示
玻璃效果,右边的
删storyBord ,更改main?? 建立窗口
重写控制器在initNib的方法,init会调用这个 %100会调用initWithNib的方法
随机色
适配两张图片 6,7 分别
重构 代码:相同的提取 不一样的
默认渲染蓝色,因此设置渲染模式,参见0606-6,
7.6适配
适配 判断很复杂(每一个)
在初花化中判断:(高级一点)
image分类:分类的方法会覆盖系统的方法,当同名的时候
pch 中导入全部的文件
对系统的项目包装;
删插件;改插件 改plist
友盟 GitHub codeForApp
git 写-
uiview 加分类;扩充功能
分类中加方法;
分类中加属性,只会生成get set 声明,不会生成 方法
懒加载的好处1>代码独立 2>为空就建立 3>提升性能
只须要建立一次的时候,用懒加载
要想为何这么写???多思考
#warning 注释---此处删掉storyBoard 就须要建立windown 而且显示,让程序
0924:导航栏一行至关于两行:child.title 设置上面和下面
手动切换比较快
系统很差用得时候 ,自定义TabBar SearchBar
#warning 注释---技巧
子类中没有的属性去父类中找
init 默认的宽高 00
initwithImage 宽高是图片的宽高
#warning 注释---此处里面不能设置frame
- (id)initWithFrame:(CGRect)frame
在layoutSubview 里面设置frame
当图片在右 文字在左的时候须要自定义button
让一个View 填充整个图片 思路:重写drawRect 自定义Viw
弹出view 14:12 ????为何加载window上面
私有api 不能使用 能够用父类
手势识别器 若是为空,
桥接是 corefoundation 和foundatio之间的转换
3
self.plusButton.bounds = (CGRect){CGPointZero, plusButtonSize};
上面这种写法,返回值必须强转CGRect
类方法中只能调用类方法
[navBar setBackgroundImage:[UIImage imageWithName:@"navigationbar_background"] forBarMetrics:UIBarMetricsDefault];
// 默认用一条线平铺
imageWithName:@"searchbar_textfield_search_icon"];
// 经过initWithImage:建立的UIImageView, UIImageView的尺寸就是图片的尺寸
能够自定义按钮的尺寸和 文字和图片的大小
- (CGRect)imageRectForContentRect:(CGRect)contentRect
{
CGFloat imageY = 0;
CGFloat imageW = IWTitleButtonImageW;
CGFloat imageX = self.width - imageW;
CGFloat imageH = self.height;
return CGRectMake(imageX, imageY, imageW, imageH);
}
- (CGRect)titleRectForContentRect:(CGRect)contentRect
{
CGFloat titleY = 0;
CGFloat titleX = 0;
CGFloat titleW = self.width - IWTitleButtonImageW;
CGFloat titleH = self.height;
return CGRectMake(titleX, titleY, titleW, titleH);
}
微博思路:
1> 设置窗口的根控制器
2> 1.建立一个新的tabbar s
2.移除系统自带的tabbar
3> 建立并添加子控制器 初始化本身的全部子控制器,每一个子控制器UITableViewController,添加到UITabBarController 的时候就具备tabar
的属性,能够设置标题,图像;
3.1>初始化每一个的时候在初始化具体的控制器
4>系统自带的tabBar 只有四个按钮(比较整齐),没有添加大加号,因此自定义tabBar,
5>
UIButton
@property(nonatomic) UIEdgeInsets contentEdgeInsets UI_APPEARANCE_SELECTOR; // default is UIEdgeInsetsZero
@property(nonatomic) UIEdgeInsets titleEdgeInsets; // default is UIEdgeInsetsZero
@property(nonatomic) BOOL reversesTitleShadowWhenHighlighted; // default is NO. if YES, shadow reverses to shift between engrave and emboss appearance
@property(nonatomic) UIEdgeInsets imageEdgeInsets;
设置button image title 的四周多大的范围不能用,内部内容会压缩
切换控制器 :
1>modal 会保住以前的控制器
2>push 须要导航控制器(须要导航,缺点,push后的不能销毁)
3>切换根控制器
1>2>根据动画效果决定
对象无指针会销毁
default-568h.@2x.png ;lanuch
里面才会自动加载
@2x 点击rentnia 拖动 不然unsign 不能用
隐私删Cookie
oauth受权
当使用的是 数字的时候,使用 对数字对象便于用户开发
/**
* 用户的惟一标示
*/
@property (nonatomic, copy) NSNumber *uid;
新建不一样的方法类 能够保证不一样的值在不一样的文件中传输
字符串截取
- (void)setSource:(NSString *)source
{
int loc = [source rangeOfString:@">"].location + 1;
int length = [source rangeOfString:@"</"].location - loc;
source = [source substringWithRange:NSMakeRange(loc, length)];
_source = [NSString stringWithFormat:@"来自%@", source];
}
新浪返回的格式是美国的时间格式, loacl 应该写美国的时间;
真机调试须要加fmt.local = [[nsloclal alloc ]init];
不然时间不显示
没法测试环境,好比去年的时间, 能够写死创造测试条件;
Next
Overview
The UIWindow class defines an object known as a window that manages and coordinates the views an app displays on a device screen. Unless an app can display content on an external device screen, an app has only one window.
The two principal functions of a window are to provide an area for displaying its views and to distribute events to the views. To change the content your app displays, you can change the window’s root view; you don’t create a new window. A window belongs to a level—typically, UIWindowLevelNormal—that represents where it sits on the z-axis relative to other windows. For example, a system alert window appears above normal app windows.
Note: When you use storyboards and the Xcode app templates to create an app, a window is created for you. If you choose to create a window in Interface Builder, be sure to select the Full Screen at Launch option in the Attributes inspector so that the window is sized appropriately for the current device. Because a window doesn’t receive touch events outside of its bounds and views aren’t clipped to the window’s bounds by default, an improperly sized window might not be able to deliver touch events to all its views.
For more information about how to use windows, see Multiple Display Programming Guide for iOS.
Tasks
Configuring Windows
windowLevel property
screen property
rootViewController property
Making Windows Key
keyWindow property
– makeKeyAndVisible
– becomeKeyWindow
– makeKeyWindow
– resignKeyWindow
Converting Coordinates
– convertPoint:toWindow:
– convertPoint:fromWindow:
– convertRect:toWindow:
– convertRect:fromWindow:
Sending Events – sendEvent:
Properties
keyWindow(是不是keyWindo )
@property(nonatomic, readonly, getter=isKeyWindow) BOOL keyWindow
Discussion
If YES, the receiver is the key window for the application; otherwise, NO.
//主window 接受键盘,和其余非触摸相关的事件,同一时间只能有一个keywindow
rootViewController
The root view controller for the window.
window 的根控制器,提供window的内容view 指定根控制器 让控制器的view 做为window的contenView 添加根控制器之前的控制器
会移除,新的控制器的view 会被安装,默认的属性,,[pp]
@property(nonatomic, retain) UIViewController *rootViewController
The default value of this property is nil.
#warning 注释---
// 当前时间
NSDate *now = [NSDate date];
// 比较当前时间 和 帐号的过时时间
if ([account.expires_time compare:now] == NSOrderedAscending) { // 过时
return nil; // 直接返回nil
}
return account;
图文混排,coreText 使用第三方框架
#pragma mark-
字符串退换 很强大
//---------------------------------------------
只要用到令外的东西 ,都须要导入该头文件(即便已经导入了父的头文件)
//---------------------------------------------
[UIColor colorwithimage :]= color
一个控件移动须要回去的时候 使用CATransform3D
[NSTimer sched
kvc key Value coding
kvo key value observe 监听对象的属性改变
NSDictionary *dict = @{@(1):@(2),@(1):@(2)};
nsnumber 转化为字符串 description
如何保证程序在后台运行
//---------------------------------------------
#warning 注释---set方法没保存 后面的图片出不来
// 还有须要调用父类的方法,layoutsubViews///
//---------------------------------------------
initWithImage :设置的图片默认不能交互,自动调整frame,就是图片的大小
点击按钮 : touchupinside
textField 单行
不能滚动
有提示文字
textview 多行输入,能滚动
没有提示文字
//添加label到导航栏的下面
[self.navigationController.view insertSubview:lable belowSubview:self.navigationController.navigationBar];
copy 之后不相互影响
代理只能设一个 通知能够多个
一条线平铺: 平铺的方法
// 1.设置背景
self.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageWithName:@"compose_toolbar_background"]];
// 3.监听键盘的通知
位置改变的通知UIKeyboardWillChangeFrameNotification 等于下面两个通知
[IWNotificationCenter addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[IWNotificationCenter addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
之前
对象转结构体
CGRect keyboardF = [note.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
//textView 垂直方向上永远能够拖拽
textView.alwaysBounceVertical = YES;
监听scrollView 使用代理,键盘使用通知监听
弹出键盘
[self.textView becomeFirstResponder];
取字典的value
info[UIImagePickerControllerOriginalImage]
// 发送多张图片用同一个name便可(同一个请求参数名字,服务器利用数组接收便可)
[formData appendPartWithFileData:data name:@"pic" fileName:@"" mimeType:@"image/jpeg"];
}
//-------------------不能点击--------------------------
父控件没有frame 子控件还会显示的,只是父控件不能接受点击事件,
父控件设置背景色不可见,子控件就不能点击
//---------------------------------------------
// 定时发送请求给服务器(得到未读数)
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(getUnreadCount) userInfo:nil repeats:YES];//定时发送任务,
// [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];//让执行其余任务的时候定时器(好比拖拽的时候,还能给定时器发送请求);
init 内部调用 initWithNIbname(不用调父类)
init 内部也调用 initwithname (不用调父类)
模型通常继承NSObject 或者自定义的父类
backGroundView 的优先级高于backGroundColor 的优先级
重写frame 方法 修改cell 系统的东西改了 重写系统的方法
hilightTextColor 高亮时文本的颜色
微博第八天 穿透
1429????
配两下 配两下 就能够完成
软件内存的怎么样??
静态分析 有无潜在的的内存泄露
动态分析: 分析
发布 用safir 必须用这个
nscoding :archives
存对象
偏好:键值 (bool key)
plist :字典
(以上都是小数据)
sqlite3 跨平台
core data sqlite3是sqlite3的oc 形式
sqlite3 轻型 几百kb 速度比mysqql postSql 速度更快
数据库
数据结构存储数据的仓库
有必定的格式
dataBase
关系型数据库
对象型数据库
经常使用的关系型数据库
pc端 :Oracle
嵌入式/移动客户端 SQlite
数据库以表为单位
数据库有多少张表
表(列 -字段):存储一种数据
5条数据 = 5条记录
建立表 - 字段(列,属性) - 记录(行,record );
navicat - .app -sn(破解)获取 - 退出app
blog 二进制
存数据必须得有主键
主键 增长主键约束 每一个表必须有一个主键 标记记录,保持惟一
一个主键 能够是一个或者两个字段组成主键
主键必须保持惟一性
移动开发搞一个一个字段的主键就行
主键必须integer 才行
key勾选表明是主键 主键不能为空,两个空 不保证惟一性
写数据必须添加主键
real 浮点型
数据库以文件存在,永久存储
auto incre
sql 语句增长记录
sql = structure query language
sql 是数据库语句,关系型数据定义的语言
sql 语言易学易用
数据库的 增删改查= CRUD
sql 语句的特色:1>不区分大小写
2> 分号结尾
3> 关键字
4>不能用关键字 标示变量
5>ddl data defination language
6>建立删表
DMl data manipunaiton language
insert delete update
数据查询语句
DQL query
select 查数据 (最经常使用的数据)
drop 删数据
创表
create Table
沙盒 nsserchPath (doc library);
mainbundle (app 的路径);
- (IBAction)select {
// 1.查询数据, 得到查询结果集
FMResultSet *set = [self.db executeQuery:@"select * from t_student where name like ?;", @"%jay-5%"];
#warning 注释---@"%jay-5%" 与数据库中写判断 加两个% 号不一样 字符串拼接, %% 是转义子字符
// 2.从结果集里面取出数据
while ([set next]) {
// 取出当期指向的那行数据
NSString *name = [set stringForColumn:@"name"];
int age = [set intForColumn:@"age"];
NSLog(@"%@ - %d", name, age);
}
}
.keyValues write14:31直接写入plist
NSBundle 和沙盒 的区别???
set
copy 在block中是强引用
网络多线程,最后一天微博多线程中的循环引用
block 中只要用到外面东西就使用弱指针
16:04强引用
注释注释
注释paihang
// 看公司代码技巧:
修改以前备份
名字搜不到:有多是图片,网络数据是搜不到的;
代码备份
4>按钮多是图片
5>搜不到 就搜附近的名字
1>注释+加搜 (主搜 + 副搜)
2>注释:就知道作什么:
3>直接加return 就能够知道后面的代码作什么的?
6>名字= 组合搜
7>中文标签是重点搜得对象
8>控制器清空:nil
9>通常先找viewdidload
10>结构作笔记,熟悉公司代码的结构
11>一层层的找控制器,就会熟悉
12>不删除的设置背景色也能够;
13>改东西不能一行行找
面试题:c++ xmpp 讲完新浪博客 360 17.5k 14*15
增长的项目:多整项目,
AFN 返回的字典数组,不能直接写入plist 由于里面有空格 逗号,等,须要用keyValues 杰哥写的字典专,再数组转模型
模型再转数组的方法,再writeTofile 的方法写入plist
模型存数据是把数据保存在模型的属性里面
// 准备了一个块代码,传递给detail
// 块代码的具体执行时间由detail决定 str 表明接受一个形参
detail.saveBlock = ^ (NSString *str) {
self.label.text = str;
};
// [_delgate save:self.textField.text];
if (self.saveBlock) {
self.saveBlock(self.textField.text); 具体的执行由这行来执行,self.textField.text是传入的参数
}
作分享的网站:友盟,分享 光速推送
横竖屏突破:田字格里面作横竖屏适配;
长度不同 不能全部的都勾上;
让导航控制器弹出新的控制器, 再present
建立控制器:显示的时候,宽度,永远是768;高度随屏幕
设置弹出模态的方式;全屏中间,
显示蒙版还能够点击;
屏模式配 一个个的往里拖
启动图片 一个个的修改json
不适用Autolayout
0622:14:15自动取色
横竖屏 水平自动居中: 调整田字
out of date 将本身的代码和服务器的代码进行比对
svn 拷贝 修改 合并
cvs 锁定 修改 解锁
快速提交代码//
五点钟下班,四点钟提交代码
svn 会out of date
svn sp2 service pake 3
直接下一步
直接下一步,
版本控制:
tags 重大版本的备份
branches 分支目录;
initWithImage 默认就用宽高,
UIImageView *iv = [UIImageView alloc ]initWithImage
其实是蓝牙连接
peer to peer 对等 对端连接,
监听图片点击,实现图片点击
如何喧染图片;
block 指向结构体指针
block 回调,代码 等待被调用,当参数,也能够接受参数;
__block int a 在block 中能够修改a
是指针传递
copy 对应一次release
copy 将对象放在堆里面
1.微信如何搜索附近人
2.模糊搜索和精确搜索
3.即时通信的UI布局,要是你作你会用多少个cell
4.有没有直播经验
5.最近的ipv6上架的问题 以及了解ipv6是什么
6.消息机制了解么?你用它作过什么!
7.iOS如何优化
8.instuments用过哪些工具,如何测试核心动画性能
9.沙盒机制
10.ffmpeg,opengl了解嘛
11.如何收集APP异常信息(好比:崩溃、闪退等)
12.离屏渲染了解么,了解的话说一下你通常是从哪几方面操做的
13.了解GCD的信号量机制么!能谈谈你对它的理解么!
14.聊下RAC和MVVM,你对它的见解
15.block底层实现
16.响应链底的理解
17.KVC和KVO
18.lldb(gdb)经常使用的调试命令
19.热更新
20.GCD实现原理
@interface CZPlaySoundTool ()
//@property (nonatomic, strong) NSMutableDictionary *soundIDs;
@end
static NSMutableDictionary *_soundIDs;
@implementation CZPlaySoundTool
// 两个方法都会调用一次
// 真正使用这个类的时候会调用
+ (void)initialize
{
_soundIDs = [NSMutableDictionary dictionary];
}
// 加载类的时候就会调用
//+ (void)load
//{
//
//
//}
+ (void)playSoundWithName:(NSString *)name
{
//1.根据name 取字典找soundID
SystemSoundID soundID = [_soundIDs[name] intValue];
//2.判断soundID
//获取对应的音效文件
//保存到字典
if (soundID == 0) {
// 1.获取音效文件
NSString *path = [[NSBundle mainBundle]pathForResource:name ofType:nil];
NSURL *url = [NSURL fileURLWithPath:path];
AudioServicesCreateSystemSoundID((__bridge CFURLRef _Nonnull)(url), &soundID);
[_soundIDs setObject:@(soundID) forKey:name];
}
//3.播放
AudioServicesPlaySystemSound(soundID);
}