开发遇到的...
来源:互联网 发布:python 流量 预测 编辑:程序博客网 时间:2024/05/02 00:17
创建表格:create table if not exists t_contact (id integer primary key autoincrement,name text,phone text);
增:
insert into t_contact (name,phone) values ('qiuxuewei','18518914551')
改:
update t_contact set name = qiuxuewei2
删:
delete from 表名
查:
select * from 表名 where 字段名 > 10;
// ? 表示数据库里面的占位符 ? 指定的只能是对象,要是基本数据类型包装成对象
数据存储的四个方式:
1. plist :只能存储NSArray, NSDictionary,只能存储数组和字典,不能有自定义对象
2. 偏好设置: 也不能存储自定义对象
3.归档: 可以存储自定义对象,不过要一次性做读取和存储的操作
4. SQLite数据库:
1> 操作数据比较快
2>可以局部的额度去
3>比较小型,占用的内存资源比较少
操作数据库的步骤:
0>打开数据库
1>创建数据表,表明,通常以t_xxx
2>创建表的字段,看下表需要存储什么数据就添加什么字段(字段必须有一个主键,记录的唯一标示符)
3>记录数据
数据库文件不能保存在document文件夹下,会被拒!!!
数据定义语句(DDL:Data Definition Language)
包括create和drop等操作
在数据库中创建新表或删除表(create table或drop table)
数据操作语句(DML:Data Manipulation Language)
包括insert、update、delete等操作
上面的3种操作分别用于添加、修改、删除表中的数据
数据查询语句(DQL:Data Query Language)
可以用于查询获得表中的数据
关键字select是DQL(也是所有SQL)用得最多的操作
其他DQL常用的关键字有where,order by,group by和having
真机调试的步骤:
1. 装一个开发者证书,让电脑具有真机调试的功能
2. 在后台生成一个bundle ID
3. 在后台添加手机的UUID
4. 生成一个描述文件
打包调试步骤:
1. 装一个证书,打包的证书
2. 生成一个bundle ID
3. 添加手机的UUID
4. 生成一个描述文件
*在Xcode6里打包应用程序的时候输入账号就会自动添加描述文件
5. 利用Xcode打包应用程序
#pragma mark - 选择照片
- (IBAction)chooseImage {
//判断照片源是否可用
if (![UIImagePickerControllerisSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) return;
//创建照片选择控制器
UIImagePickerController *ipc = [[UIImagePickerControlleralloc] init];
//设置照片源
ipc.sourceType =UIImagePickerControllerSourceTypeSavedPhotosAlbum;
//设置代理
ipc.delegate =self;
//弹出控制器
[selfpresentViewController:ipc animated:YEScompletion:nil];
}
开启程序将图标右上角的数字清除需要在控制器的viewDidLoad中加一句:
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0]
代理和block区别:
代理:打电话让别人去做事情
block:让小弟去做事情
//这个是把数组加进去
// [self.statuses addObject:statusArr];
//这个是把数组的元素加进去
[self.statusesaddObjectsFromArray:statusArr];
请求数据常规开发步骤:
1、查看接口文档
2、依据参数列表,设置参数模型
3、依据结果,设置结果模型
4、直接拿到对应的工具类处理
软件开发步骤: 搭建界面 ————> 展示数据 ————> 处理对应的业务逻辑
1、向服务器发送数据 —》一般公司会提供一个接口文档,参照接口文档跟服务器打交道,接口文档(1、请求的url, 2、发送什么样的请求(GET/POST)3、返回数据的格式)
2、服务器相应数据 —》 解析数据,参照接口文档设计模型 —》返回数据转化为模型
3、把数据展示到界面,刷新表格!!!!!
归档:(模型归档必须要遵守一个协议NSCoding!!!!!!!!!!!!!)
数据存储一般会搞一个业务类,专门处理数据的存储
//以后不想归档用数据库可以直接修改业务类
//归档
#define XWAccountFilePath [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"account.data"]
//归档
[NSKeyedArchiverarchiveRootObject:account toFile:XWAccountFilePath];
//解档
[NSKeyedUnarchiverunarchiveObjectWithFile:XWAccountFilePath];
——————————————
//归档(告诉系统哪些属性需要归档!)
- (void)encodeWithCoder:(NSCoder *)aCoder{
[aCoderencodeObject:self.access_tokenforKey:XWAccess_token];
[aCoderencodeObject:self.expires_inforKey:XWExpires_in];
[aCoderencodeObject:self.uidforKey:XWUil];
}
//解档(告诉系统哪些属性解档)
- (id)initWithCoder:(NSCoder *)aDecoder{
if ([super init]) {
//解档完之后保存到属性中,不要白解了!!
self.access_token = [aDecoderdecodeObjectForKey:XWAccess_token];
self.expires_in = [aDecoderdecodeObjectForKey:XWExpires_in];
self.uid = [aDecoderdecodeObjectForKey:XWUil];
}
return self;
}
//KVC的底层实现原理:
/**
遍历字典里的所有key:
dict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
<#code#>
}
一个个获取key,回去模型里查找有没有setKey方法:比如:
-(void)setUid:(NSString *)uid{}
如果有直接调用这个方法赋值比如:setUid:obj
如果没有查找有没有带下划线的_key _uid,直接拿到属性,如果有直接赋值
如果找不到对应的key,就会报错
*/
偏好设置的好处:
1、不需要关心文件名
2、快速进行键值对存储
UICollectionView必须初始化布局才能显示
/**
使用UICollectionViewController的步骤:
1、初始化UICollectionViewFlowLayout布局参数:
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
//设置cell的尺寸
layout.itemSize = [UIScreen mainScreen].bounds.size;
//清空行距
layout.minimumLineSpacing = 0;
//设置水平滚动的方向
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
return [super initWithCollectionViewLayout:layout];
2、使用collection必须要注册cell:[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:ID];
3、自定义cell
*/
注意!!!!!
UITableView 和 UICollectionView 添加子控件要添加在self.contentView上面!!!!
// //创建搜索框
// UISearchBar *searchBar = [[UISearchBar alloc] init];
// searchBar.placeholder = @"搜索占位符";
UITextField *searchBar = [[UITextFieldalloc] initWithFrame:CGRectMake(0,0, [UIScreenmainScreen].bounds.size.width,30)];
searchBar.placeholder =@"搜索占位符";
searchBar.background = [UIImageimageNamed:@"searchbar_textfield_background"];
UIImageView *imageView = [[UIImageViewalloc] initWithImage:[UIImageimageNamed:@"searchbar_textfield_search_icon"]];
// imageView.frame = CGRectMake(0, 0, 15, 15);
searchBar.leftView = imageView;
//想要显示UITextField左边的leftView一定要设置这个属性
searchBar.leftViewMode =UITextFieldViewModeAlways;
self.navigationItem.titleView = searchBar;
//什么时候调用:从程序一启动的时候就会把所有的类加载进内存
//作用:加载类的时候调用
+(void)load{
NSLog(@"%s",__func__);
}
//什么时候调用:当第一次使用这个类或者这个类的子类的时候调用
//作用:初始化类的时候
+(void)initialize{
NSLog(@"%s",__func__);
}
//appearance 只要遵守UIAppearance协议,就能获取外观
//获取所有的tabarItem外观标示,包括系统自带类
UITabBarItem *item = [UITabBarItemappearance];
//获取所有的tabarItem外观标示,只当前类
UITabBarItem *itemW = [UITabBarItem appearanceWhenContainedIn:self,nil];
//创建搜索框
UISearchBar *searchBar = [[UISearchBaralloc] init];
searchBar.placeholder =@"搜索占位符";
//默认会根据按钮的背景图片、图片、文字计算出最合适的尺寸
[_plusButtnsizeToFit];
//修改系统tabbar上按钮的位置,需要自定tabbar才能实现
XWTabBar *tabBar = [[XWTabBaralloc] initWithFrame:self.tabBar.frame];
//利用KVC可以修改readONLY属性
[selfsetValue:tabBar forKeyPath:@"tabBar"];
工厂方法不能用id而要用instance声明返回值类型的原因:
1、id可以调用任何类的get、set方法,不会帮我们检查语法错误,只能在运行时崩溃
2、instance可以自动识别调用的类是父类还是子类并且自动识别其方法变量
判断当前设备是iOS8 还是iOS7
if ([[UIDevicecurrentDevice].systemVersiondoubleValue] >= 8.0) {
NSLog(@"是iOS8");
}else{
NSLog(@"是iOS7");
}
// UIScrollView 垂直方向上永远可以拖拽(有弹簧效果)
textView.alwaysBounceVertical =YES;
// 通知
// 当UITextView的文字发生改变时,UITextView自己会发出一个UITextViewTextDidChangeNotification通知
[HWNotificationCenteraddObserver:selfselector:@selector(textDidChange)name:UITextViewTextDidChangeNotificationobject:self];
// 重绘(重新调用drawRect),先把drowRect的内容擦掉
[selfsetNeedsDisplay];
/**
UITextField:
1.文字永远是一行,不能显示多行文字
2.有placehoder属性设置占位文字
3.继承自UIControl
4.监听行为
1> 设置代理
2> addTarget:action:forControlEvents:
3> 通知:UITextFieldTextDidChangeNotification
UITextView:
1.能显示任意行文字
2.不能设置占位文字
3.继承自UIScollView
4.监听行为
1> 设置代理
2> 通知:UITextViewTextDidChangeNotification
*/
// 内容模式
self.contentMode =UIViewContentModeScaleAspectFill;
// 超出边框的内容都剪掉
self.clipsToBounds =YES;
/**
UIViewContentModeScaleToFill : 图片拉伸至填充整个UIImageView(图片可能会变形)
UIViewContentModeScaleAspectFit : 图片拉伸至完全显示在UIImageView里面为止(图片不会变形)
UIViewContentModeScaleAspectFill :
图片拉伸至 图片的宽度等于UIImageView的宽度 或者 图片的高度等于UIImageView的高度为止
UIViewContentModeRedraw : 调用了setNeedsDisplay方法时,就会将图片重新渲染
UIViewContentModeCenter : 居中显示
UIViewContentModeTop,
UIViewContentModeBottom,
UIViewContentModeLeft,
UIViewContentModeRight,
UIViewContentModeTopLeft,
UIViewContentModeTopRight,
UIViewContentModeBottomLeft,
UIViewContentModeBottomRight,
经验规律:
1.凡是带有Scale单词的,图片都会拉伸
2.凡是带有Aspect单词的,图片都会保持原来的宽高比,图片不会变形
*/
计算行数公式:
行数 = ( count + max - 1 ) / max
@implementation NSDate (Extension)
/**
* 判断某个时间是否为今年
*/
- (BOOL)isThisYear
{
NSCalendar *calendar = [NSCalendarcurrentCalendar];
//获得某个时间的年月日时分秒
NSDateComponents *dateCmps = [calendarcomponents:NSCalendarUnitYearfromDate:self];
NSDateComponents *nowCmps = [calendarcomponents:NSCalendarUnitYearfromDate:[NSDatedate]];
return dateCmps.year == nowCmps.year;
}
/**
* 判断某个时间是否为昨天
*/
- (BOOL)isYesterday
{
NSDate *now = [NSDatedate];
// date == 2014-04-30 10:05:28 --> 2014-04-30 00:00:00
// now == 2014-05-01 09:22:10 --> 2014-05-01 00:00:00
NSDateFormatter *fmt = [[NSDateFormatteralloc] init];
fmt.dateFormat =@"yyyy-MM-dd";
// 2014-04-30
NSString *dateStr = [fmt stringFromDate:self];
// 2014-10-18
NSString *nowStr = [fmt stringFromDate:now];
// 2014-10-30 00:00:00
NSDate *date = [fmt dateFromString:dateStr];
// 2014-10-18 00:00:00
now = [fmtdateFromString:nowStr];
NSCalendar *calendar = [NSCalendarcurrentCalendar];
NSCalendarUnit unit =NSCalendarUnitYear | NSCalendarUnitMonth |NSCalendarUnitDay;
NSDateComponents *cmps = [calendar components:unit fromDate:date toDate:now options:0];
return cmps.year ==0 && cmps.month ==0 && cmps.day ==1;
}
/**
* 判断某个时间是否为今天
*/
- (BOOL)isToday
{
NSDate *now = [NSDatedate];
NSDateFormatter *fmt = [[NSDateFormatteralloc] init];
fmt.dateFormat =@"yyyy-MM-dd";
NSString *dateStr = [fmt stringFromDate:self];
NSString *nowStr = [fmt stringFromDate:now];
return [dateStr isEqualToString:nowStr];
}
@end
- (NSString *)created_at
{
NSDateFormatter *fmt = [[NSDateFormatteralloc] init];
//如果是真机调试,转换这种欧美时间,需要设置locale
fmt.locale = [[NSLocalealloc] initWithLocaleIdentifier:@"en_US"];
//设置日期格式(声明字符串里面每个数字和单词的含义)
// E:星期几
// M:月份
// d:几号(这个月的第几天)
// H:24小时制的小时
// m:分钟
// s:秒
// y:年
fmt.dateFormat =@"EEE MMM dd HH:mm:ss Z yyyy";
// _created_at = @"Tue Sep 30 17:06:25 +0800 2014";
// 微博的创建日期
NSDate *createDate = [fmt dateFromString:_created_at];
// 当前时间
NSDate *now = [NSDatedate];
//日历对象(方便比较两个日期之间的差距)
NSCalendar *calendar = [NSCalendarcurrentCalendar];
// NSCalendarUnit枚举代表想获得哪些差值
NSCalendarUnit unit =NSCalendarUnitYear | NSCalendarUnitMonth |NSCalendarUnitDay | NSCalendarUnitHour |NSCalendarUnitMinute | NSCalendarUnitSecond;
//计算两个日期之间的差值
NSDateComponents *cmps = [calendar components:unit fromDate:createDate toDate:now options:0];
if ([createDate isThisYear]) {// 今年
if ([createDate isYesterday]) {// 昨天
fmt.dateFormat =@"昨天 HH:mm";
return [fmt stringFromDate:createDate];
}else if ([createDateisToday]) { // 今天
if (cmps.hour >=1) {
return [NSStringstringWithFormat:@"%d小时前", cmps.hour];
}else if (cmps.minute >=1) {
return [NSStringstringWithFormat:@"%d分钟前", cmps.minute];
}else {
return @"刚刚";
}
}else { // 今年的其他日子
fmt.dateFormat =@"MM-dd HH:mm";
return [fmt stringFromDate:createDate];
}
}else { // 非今年
fmt.dateFormat =@"yyyy-MM-dd HH:mm";
return [fmt stringFromDate:createDate];
}
}
如果两个view是父子关系,一定会也要设置这两个view的控制器也设置为父子关系
⾃自定义cell的步骤(每个cell的⾼高度不⼀一样,每个cell⾥里⾯面显⽰示的内容也不⼀一样)
1. 新建⼀一个继承⾃自UITableViewCell的⼦子类
2. 在initWithStyle:⽅方法中进⾏行⼦子控件的初始化
1> 将有可能显⽰示的所有⼦子控件都添加到contentView中
2> 顺便设置⼦子控件的⼀一些属性(⼀一次性的设置:字体、⽂文字颜⾊色、背景
3. 提供2个模型
1> ⼀一个是数据模型(⽂文字数据+ 图⽚片数据)
2> ⼀一个是frame模型(数据模型+ 所有⼦子控件的frame + cell的⾼高度)
4. cell应该提供⼀一个frame模型属性
1> 将frame模型传递给cell
2> cell根据frame模型给⼦子控件设置frame,根据数据模型给⼦子控件设置数据
3> cell根据数据模型决定显⽰示和隐藏哪些⼦子控件
5. 在tableView的代理⽅方法返回cell的⾼高度
// 目的:想在系统计算和设置完按钮的尺寸后,再修改一下尺寸
/**
* 重写setFrame:方法的目的:拦截设置按钮尺寸的过程
* 如果想在系统设置完控件的尺寸后,再做修改,而且要保证修改成功,一般都是在setFrame:中设置
*/
- (void)setFrame:(CGRect)frame
{
frame.size.width +=HWMargin;
[supersetFrame:frame];
}
/**
* 当app进入后台时调用,使程序在进入后台也能进行操作
*/
- (void)applicationDidEnterBackground:(UIApplication *)application
{
/**
* app的状态
* 1.死亡状态:没有打开app
* 2.前台运行状态
* 3.后台暂停状态:停止一切动画、定时器、多媒体、联网操作,很难再作其他操作
* 4.后台运行状态
*/
//向操作系统申请后台运行的资格,能维持多久,是不确定的
UIBackgroundTaskIdentifier task = [applicationbeginBackgroundTaskWithExpirationHandler:^{
//当申请的后台运行时间已经结束(过期),就会调用这个block
// 赶紧结束任务
[applicationendBackgroundTask:task];
}];
// 在Info.plst中设置后台模式:Required background modes == App plays audio or streams audio/video using AirPlay
// 搞一个0kb的MP3文件,没有声音
// 循环播放
//以前的后台模式只有3种
// 保持网络连接
// 多媒体应用
// VOIP:网络电话
}
// @20 --> @"20"
// NSNumber --> NSString
// 设置提醒数字(微博的未读数)
NSString *status = [responseObject[@"status"]description];
MJExtension框架使用::
#import "MJExtension.h"
#import "HWPerson.h"
#import "HWBook.h"
NO1:
字典转模型:[HWPersonobjectWithKeyValues:dict]
//如果模型里面有模型则首先声明下:objectClassInArray
HMPerson模型中包含HMBook模型,需要在HMPerson.m中声明一下:(注意声明之前要在.H文件中遵守<MJKeyvalue>)
- (NSDictionary *)objectClassInArray
{
return @{@"books" : [HWBookclass]};
}
main{
NSDictionary *dict =@{
@"name" : @"张三",
@"books" : @[
@{
@"name" : @"葵花1",
@"price" : @"10.6"
},
@{
@"name" : @"葵花2",
@"price" : @"10.9"
},
@{
@"name" : @"葵花3",
@"price" : @"17.6"
},
@{
@"name" : @"葵花4",
@"price" : @"14.4"
}
]
};
//直接将字典转化成模型
HWPerson *person = [HWPersonobjectWithKeyValues:dict];
}
NO2:
//replacedKeyFromPropertyName:改变键值对的名
如果模型中有键值跟系统标示重复可以在.m中实现这个方法
- (NSDictionary *)replacedKeyFromPropertyName
{
//把id -> ID text -> mytext
return@{@"ID" : @"id", @"mytext" :@"text"};
}
NO3:
模型转化成字典:[statuskeyValues]
mian{
HWUser *user = [[HWUseralloc] init];
user.profile_image_url =@"abc.png";
user.idstr =@"4435435";
user.name =@"旺财";
HWStatus *status = [[HWStatusalloc] init];
status.mytext =@"哈哈哈哈";
status.user = user;
//把status模型转化为字典
NSDictionary *dict = [status keyValues];
}
NO4:
//[XWStatusobjectArrayWithKeyValuesArray:responseObject[@"statuses”]]将一个字典数组转化为模型数组,返回NSArray
// 将 "微博字典"数组转为 "微博模型"数组
self.statuses = [XWStatusobjectArrayWithKeyValuesArray:responseObject[@"statuses"]];
网络下载图片方法:
SDWebImage使用的好处:
1、异步下载,避免卡死主线程
2、已经做好图片缓存
3、已经解决循环利用
注意:容易造成内存警告
解决方法:在"AppDelegate.m”方法中定义这个方法!
//程序接收到内存警告的时候调用此方法
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application{
//1、停止所有下载
[[SDWebImageManagersharedManager] cancelAll];
//2、清除缓存
[[SDWebImageManagersharedManager].imageCacheclearMemory];
}
导入SDWebImage框架,在类中#import “UIImageView+WebCache.h”;
设置图片
[cell.imageViewsd_setImageWithURL:[NSURLURLWithString:imageUrl] placeholderImage:placehoder];
防止图片越来越多,需要手动管理图片缓存一般在XWAppDelegate.m方法中,导入
SDWebImageManager.h
再重写:
-(void)applicationDidReceiveMemoryWarning:(UIApplication *)application{
SDWebImageManager *mgr = [SDWebImageManagersharedManager];
//1、清除内存中所有图片
[mgrcancelAll];
//2、清除内存中所有图片
[mgr.imageCacheclearMemory];
}
//设置按钮自适应
[titleButtonsizeToFit];
// 如果图片的某个方向上不规则,比如有突起,那么这个方向就不能拉伸
// 什么情况下建议使用imageEdgeInsets、titleEdgeInsets
// 如果按钮内部的图片、文字固定,用这2个属性来设置间距,会比较简单
// 标题宽度
// CGFloat titleW = titleButton.titleLabel.width * [UIScreen mainScreen].scale;
//// // 乘上scale系数,保证retina屏幕上的图片宽度是正确的
// CGFloat imageW = titleButton.imageView.width * [UIScreen mainScreen].scale;
// CGFloat left = titleW + imageW;
// titleButton.imageEdgeInsets = UIEdgeInsetsMake(0, left, 0, 0);
// 如果仅仅是调整按钮内部titleLabel和imageView的位置,那么在layoutSubviews中单独设置位置即可
// 自定义对象的存储必须用NSKeyedArchiver,不再有什么writeToFile(字典和数组的写入)方法
//存
[NSKeyedArchiverarchiveRootObject:account toFile:path];
//取
[NSKeyedUnarchiverunarchiveObjectWithFile:filePath];
!!!!!注意!!!!
模型存取沙盒必须在模型内遵守一个<NSCoding>协议!!!告诉控制器哪些属性写进沙盒
eg:
/**
归档的时候调用!!
* 当一个对象要归档的时候调用,归档之前调用。目的:在这个方法中说明哪些属性要存进沙盒
*
* @param aCoder <#aCoder description#>
*/
-(void)encodeWithCoder:(NSCoder *)aCoder{
[aCoderencodeObject:self.access_tokenforKey:@"access_token"];
[aCoderencodeObject:self.uidforKey:@"uid"];
[aCoderencodeObject:self.expires_inforKey:@"expires_in"];
}
/**
* 当从沙盒中解档一个对象时(从沙盒中加载一个对象时),就会调用这个方法
* 目的:在这个方法中说明沙盒中的属性该怎么解析(需要取出哪些属性)
*/
-(id)initWithCoder:(NSCoder *)aDecoder{
if (self == [superinit]) {
self.access_token = [aDecoderdecodeObjectForKey:@"access_token"];
self.expires_in = [aDecoderdecodeObjectForKey:@"expires_in"];
self.uid = [aDecoderdecodeObjectForKey:@"uid"];
}
return self;
}
/*
切换控制器的手段
1.push:依赖于UINavigationController,控制器的切换是可逆的,比如A切换到B,B又可以回到A
2.modal:控制器的切换是可逆的,比如A切换到B,B又可以回到A
3.切换window的rootViewController
拿到主窗口方法
UIWindow *window = [UIApplicationsharedApplication].keyWindow;
//2、显示窗口
[self.windowmakeKeyAndVisible];
*/
//上一次的使用版本(存储在沙盒中的版本号)
NSString *lastVersion = [[NSUserDefaultsstandardUserDefaults] objectForKey:key];
// 当前软件的版本号(从Info.plist中获得)
NSString *currentVersion = [NSBundlemainBundle].infoDictionary[key];
UIImageView默认不可用户交互。如果想让用户交互需要设置:
imageView.userInteractionEnabled =YES;
// 很多重复代码 --->将重复代码抽取到一个方法中
// 1.相同的代码放到一个方法中
// 2.不同的东西变成参数
// 3.在使用到这段代码的这个地方调用方法,传递参数
/**
//添加子控制器方法一:
tabbarVc.viewControllers = @[vc1,vc2,vc3,vc4];
*/
//添加自控器方法二:
// [self addChildViewController:homeVc];
// [self addChildViewController:messageVc];
// [self addChildViewController:discoverVc];
// [self addChildViewController:profileVc];
/**
//搞个随机色
UIColor *color = [UIColor colorWithRed:arc4random_uniform(256)/255.0 green:arc4random_uniform(256)/255.0 blue:arc4random_uniform(256)/255.0 alpha:1.0];
*/
// 当test1控制器被push的时候,test1所在的tabbarcontroller的tabbar会自动隐藏
// 当test1控制器被pop的时候,test1所在的tabbarcontroller的tabbar会自动显示
test1.hidesBottomBarWhenPushed =YES;
一、为什么要自定义UITabBarController
1.想把UITabBarController内部的子控制器细节屏蔽起来,不让外界了解
2.另外一个目的:每一段代码都应该放在最合适的地方
二、重复代码的抽取
1.相同的代码放到一个方法中
2.不同的东西变成参数
3.在需要用到这段代码的地方传递参数、调用方法
三、统一所有控制器导航栏左上角和右上角的内容
1.让所有push进来的控制器,它导航栏左上角和右上角的内容都一样
2."拦截"所有push进来的控制器
3.方案:自定义导航控制器,重写push方法,就可以得到传进来的控制器参数
// 90%的"拦截"都是通过自定义类,重写自带的方法实现的
四、"duplicate symbol _OBJC_METACLASS_$_类名 in:"错误
1.90%都是因为#import了.m文件
2.其他可能是因为项目中存在了2个一样的.m文件
五、创建UIBarButtonItem的代码为什么放在UIBarButtonItem分类中最合适?
/*
+ (UIBarButtonItem *)itemWithTarget:(id)target action:(SEL)action image:(NSString *)image highImage:(NSString *)highImage
{
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
// 设置图片
[btn setBackgroundImage:[UIImage imageNamed:image] forState:UIControlStateNormal];
[btn setBackgroundImage:[UIImage imageNamed:highImage] forState:UIControlStateHighlighted];
// 设置尺寸
btn.size = btn.currentBackgroundImage.size;
return [[UIBarButtonItem alloc] initWithCustomView:btn];
}*/
1.项目中有多处地方用到这段代码
2.每一段代码都应该放在最合适的地方:这段代码明显在创建一个UIBarButtonItem,所以跟UIBarButtonItem相关
3.从命名习惯和规范的角度看:[UIBarButtonItem itemWith....]这种形式创建item比较规范
颜色在iOS中表示
// 每一个像素都有自己的颜色,每一种颜色都可以由RGB3色组成
// 12bit颜色: #f00 #0f0 #00f #ff0
// 24bit颜色: #ff0000 #ffff00 #000000
// 32bit颜色: 多了透明度
// #ff ff ff
// R:255
// G:255
// B:255
// RGBA
// UIImage *image = [UIImage imageNamed:@"searchbar_textfield_search_icon"];
// 通过initWithImage来创建初始化UIImageView,UIImageView的尺寸默认就等于image的尺寸
// UIImageView *searchIcon = [[UIImageView alloc] initWithImage:image];
//通过init来创建初始化绝大部分控件,控件都是没有尺寸
UIImageView *searchIcon = [[UIImageViewalloc] init];
// [UIApplication sharedApplication].keyWindow == self.view.window
//建议使用[UIApplication sharedApplication].keyWindow获取窗口
[[UIApplicationsharedApplication].keyWindowaddSubview:dropdownMenu];
//这样获得窗口是当前最上面的窗口
UIWindow *window = [[UIApplicationsharedApplication].windowslastObject];
[windowaddSubview:dropdownMenu];
imageView默认不能跟用户交互,上面添加的子控件也不能和用户交互,要想和用户交互需要设置子控件的userInteractionEnabled属性为YES
坐标系转换:
// 计算self.yellow在self.blue中的位置和尺寸
// CGRect newRect = [self.yellow convertRect:self.yellow.bounds toView:self.blue];
// 计算self.yellow在self.purple中的位置和尺寸
// CGRect newRect = [self.yellow.superview convertRect:self.yellow.frame toView:self.purple];
// 计算self.red在self.yellow中的位置和尺寸
// CGRect newRect = [self.red convertRect:self.red.bounds toView:self.yellow];
// 计算self.red在self.yellow中的位置和尺寸
// CGRect newRect = [self.yellow convertRect:self.red.bounds fromView:self.red];
// 计算self.red在屏幕中的位置和尺寸(nil代表屏幕)
CGRect newRect = [self.redconvertRect:self.red.boundstoView:nil];
NSLog(@"%@",NSStringFromCGRect(newRect));
// UIPageControl就算没有设置尺寸,里面的内容还是照常显示的
// pageControl.width = 100;
// pageControl.height = 50;
// pageControl.userInteractionEnabled = NO;
如果发现控制器的view还在,但是view上面的数据不显示,极大可能是因为控制器被提前销毁了
/*
[self setValue:tabBar forKeyPath:@"tabBar"];相当于self.tabBar = tabBar;
[self setValue:tabBar forKeyPath:@"tabBar"];这行代码过后,tabBar的delegate就是HWTabBarViewController
说明,不用再设置tabBar.delegate = self;
*/
/*
1.如果tabBar设置完delegate后,再执行下面代码修改delegate,就会报错
tabBar.delegate = self;
2.如果再次修改tabBar的delegate属性,就会报下面的错误
错误信息:Changing the delegate of a tab bar managed by a tab bar controller is not allowed.
错误意思:不允许修改TabBar的delegate属性(这个TabBar是被TabBarViewController所管理的)
*/
#warning 默认情况下,scrollView一创建出来,它里面可能就存在一些子控件了
#warning 就算不主动添加子控件到scrollView中,scrollView内部还是可能会有一些子控件
// EdgeInsets: 自切
// contentEdgeInsets:会影响按钮内部的所有内容(里面的imageView和titleLabel)
shareBtn.contentEdgeInsets =UIEdgeInsetsMake(10,150, 0, 0);
// titleEdgeInsets:只影响按钮内部的titleLabel
shareBtn.titleEdgeInsets =UIEdgeInsetsMake(0,10, 0, 0);
// imageEdgeInsets:只影响按钮内部的imageView
// shareBtn.imageEdgeInsets = UIEdgeInsetsMake(20, 0, 0, 50);
// shareBtn.titleEdgeInsets
// shareBtn.imageEdgeInsets
// shareBtn.contentEdgeInsets
/*
一个控件用肉眼看不见,有哪些可能
1.根本没有创建实例化这个控件
2.没有设置尺寸
3.控件的颜色跟父控件的背景色一样(实际上已经显示了,只不过用肉眼看不见)
4.透明度alpha <= 0.01
5.hidden = YES
6.没有添加到父控件中
7.被其他控件挡住了
8.位置不对
9.父控件发生了以上情况
10.特殊情况
* UIImageView没有设置image属性,或者设置的图片名不对
* UILabel没有设置文字,或者文字颜色和跟父控件的背景色一样
* UITextField没有设置文字,或者没有设置边框样式borderStyle
* UIPageControl没有设置总页数,不会显示小圆点
* UIButton内部imageView和titleLabel的frame被篡改了,或者imageView和titleLabel没有内容
* .....
11、自切了:UIEdgeInsetsMake
添加一个控件的建议(调试技巧):
1.最好设置背景色和尺寸
2.控件的颜色尽量不要跟父控件的背景色一样
*/
/*
1.程序启动会自动加载叫做Default的图片
1> 3.5inch 非retain屏幕:Default.png
2> 3.5inch retina屏幕:Default@2x.png
3> 4.0inch retain屏幕: Default-568h@2x.png
2.只有程序启动时自动去加载的图片, 才会自动在4inch retina时查找-568h@2x.png
*/
归档
//归档
[[NSUserDefaultsstandardUserDefaults] setObject:currentVersionforKey:key];
//即时刷新
[[NSUserDefaultsstandardUserDefaults] synchronize];
//将最新的微博数据添加到总数组最前面
NSRange range = NSMakeRange(0, newStatuses.count);
NSIndexSet *set = [NSIndexSetindexSetWithIndexesInRange:range];
[self.statusesinsertObjects:newStatuses atIndexes:set];
//添加刷新控件
-(void)setupRefresh{
//添加刷新控件
UIRefreshControl *refreshControl = [[UIRefreshControlalloc] init];
//只有用户通过手动下拉刷新,才会触发UIControlEventValueChanged事件
[refreshControl addTarget:selfaction:@selector(refreshStateChange:)forControlEvents:UIControlEventValueChanged];
[self.tableViewaddSubview:refreshControl];
//马上进入刷新状态(仅仅是显示刷新状态,并不会触发UIControlEventValueChanged事件)
[refreshControlbeginRefreshing];
//马上加载数据(自己加载)
[selfrefreshStateChange:refreshControl];
}
/**
* 显示最新微博数量,弹出一个小框框的效果
*
* @param count 最新微博数量
//如果某个动画执行完毕后,又要回到动画执行前的状态,建议使用transform来做动画
*/
-(void)showNewStatusCount:(int)count{
//创建label
UILabel *label = [[UILabelalloc] init];
label.backgroundColor = [UIColorcolorWithPatternImage:[UIImageimageNamed:@"timeline_new_status_background"]];
label.width = [UIScreenmainScreen].bounds.size.width;
label.height =35;
//设置其他属性
if (count == 0) {
label.text =@"没有新的微博数据,稍后再试";
}else{
label.text = [NSStringstringWithFormat:@"共有%d条新的微博数据",count];
}
label.textColor = [UIColorwhiteColor];
label.textAlignment =NSTextAlignmentCenter;
label.font = [UIFontsystemFontOfSize:16];
//添加
label.y =64 - label.height;
//将label添加到导航控制器的view中,并且盖在导航栏下面
[self.navigationController.viewinsertSubview:labelbelowSubview:self.navigationController.navigationBar];
//动画
//先利用1s的时间,让label往下移动一段距离
CGFloat duration = 1.0; //动画时间
[UIViewanimateWithDuration:duration animations:^{
// label.y += label.height;
label.transform =CGAffineTransformMakeTranslation(0, label.height);
}completion:^(BOOL finished) {
//延迟一秒后再利用1s的时间让label往上移动一段距离(回到一开始的状态)
CGFloat delay = 1.0;
//UIViewAnimationOptionCurveLinear:匀速
[UIWindowanimateWithDuration:duration delay:delayoptions:UIViewAnimationOptionCurveLinearanimations:^{
// label.y -= label.height;
label.transform =CGAffineTransformIdentity;
}completion:^(BOOL finished) {
//把自己销毁
[labelremoveFromSuperview];
}];
}];
}
- 开发遇到的...
- Android开发遇到的
- 开发遇到的问题
- 开发遇到的问题
- 开发遇到的问题
- 开发中遇到的几个问题
- 手机开发遇到的问题
- 开发中遇到的问题
- Liferay开发遇到的问题
- 开发中遇到的问题
- 开发项目遇到的bug
- cgi开发遇到的问题
- 开发遇到的典型问题
- 开发中遇到的问题
- android开发 遇到的问题
- Extjs开发遇到的问题
- Birt开发遇到的问题
- storm开发遇到的问题
- MySql数据类型和Java数据类型对应表
- 解决CentOS在虚拟机里面分辨率小的问题
- ECC与Pairing前沿调研
- C++编译器的函数编译流程
- MFC中可以设置字体颜色,背景色,前景色,是否透明
- 开发遇到的...
- 转载一篇关于设计模式
- poj_1564Sum It Up
- hdu2157 快速幂
- 最长上升子列 LIS 学习小记 Poj 2533 +CF 261D
- 需要关注的模式识别专家信息列表 --- 长期维护
- ASIHttp 详解
- 《软件测试实用技术与常用模板》第3章黑盒测试的实用技术
- trash