ios开发中的切图拉伸
在ios的开发中,一般都是把控件的大小设置为切图大小的一半。比如640*200的切图,做成按钮是320*100的大小。这与苹果的分辨率有关
但是在有些需要做动态加长或者动态加宽的自适应控件来说这样直接拉伸就会显示不正常。在这里一般有两种做法:
第一种方法:
在代码中用到图片的地方加上这句话
xxx.image =[xxx.image stretchableImageWithLeftCapWidth:22 topCapHeight:20];
然后再把切图资源的名字最后,后缀名之前加上@2x 就可以了,比如原来名字叫做 defaultButton.png 改成 defaultButton@2x.png就可以了,并且改了名字之后并不会影响正常使用。
第二种方法:
暂时还没有用到,等用到了之后再补充
ios中table的点击高亮
在我参与的这次项目中,关于table的创建都是通过定义一个继承自UIViewController的类,并且在该类中定义一个UITableView类型的变量mTable.
每一个单元格的构造是通过定一个自定义的类型ContantsItemView : UIView和ContantsCell : UITableViewCell,两者之间的关系是在ContantsCell中定义一个ContantsItemView类型的变量
#import <UIKit/UIKit.h> @class JSBadgeView; @class ContantsCell; @class ImageLoadOperation; @interface ContantsItemView : UIView { UIImageView * headImageView; JSBadgeView * badgeView; UILabel * name; UILabel * phoneNum; UIImageView * changeableImageView; UILabel * timeLabel; UIButton * bt; } @property (nonatomic) int viewType; @property (nonatomic,assign)PERSONTYPE personType; @property (nonatomic,retain)UIImage *headImage; @property (nonatomic) BOOL isSelected; @property (nonatomic,assign) UILabel * name; @property (nonatomic,assign) UILabel * phoneNum; @property (nonatomic) int state; @property (nonatomic,assign) ContantsCell * mCtrller; @property (nonatomic, retain) ImageLoadOperation *imageLoadOperation; @end @interface ContantsCell : UITableViewCell { ContantsItemView * itemView; int sectionNum; int rowNum; } @property (nonatomic) int sectionNum; @property (nonatomic) int rowNum; @property (nonatomic,assign) ContantsItemView * itemView; @property (nonatomic,assign) id mCtrller; @property (nonatomic,retain) NSString *headImgName; -(void)invite; @end
原来的做法是在ContantsItemView中定义一个UIImageView类型的控件作为列表中的每个单元格的背景
问题来了,我想让列表中的每一个单元格在点击的时候会出现和button一样的高亮的效果。查了一下资料发现可以用这种方法:
在我们自定义的继承自UITableViewCell的类的初始化部分使用函数:
[self setBackgroundView:[[[UIImageView alloc]initWithImage:[UIImage imageNamed:@"tableListDefault.png"]]autorelease]]; [self setSelectedBackgroundView:[[[UIImageView alloc]initWithImage: [UIImage imageNamed:@"tableListHil.png"]]autorelease]];
即可实现点击高亮。后来又发现一个页面实现了,还有一个页面还是没有实现。只能在cellForRowAtIndexPath仔细比对一下两者的不同,发现原来是这句话的原因:
cell.selectionStyle = UITableViewCellSelectionStyleGray;
IOS中NSUserDefaults的用法(轻量级本地数据存储)(转自集结号网友的原创:http://blog.csdn.net/enuola/article/details/7959767)
NSUserDefaults适合存储轻量级的本地数据,比如要保存一个登陆界面的数据,用户名、密码之类的,个人觉得使用NSUserDefaults是首选。下次再登陆的时候就可以直接从NSUserDefaults里面读取上次登陆的信息咯。
因为如果使用自己建立的plist文件什么的,还得自己显示创建文件,读取文件,很麻烦,而是用NSUserDefaults则不用管这些东西,就像读字符串一样,直接读取就可以了。
NSUserDefaults支持的数据格式有:NSNumber(Integer、Float、Double),NSString,NSDate,NSArray,NSDictionary,BOOL类型。很实用吧
NSUserDefaults很方便,读取也很容易。下面给出一个示例看看如何使用:(PS:更详细的也可以参考官方文档哈)
ViewController.h文件中主要是放几个控件,用于显示存储的数据:
- #import <UIKit/UIKit.h>
- @interface ViewController : UIViewController
- {
- IBOutlet UILabel *txtInteger;
- IBOutlet UILabel *txtFloat;
- IBOutlet UILabel *txtDouble;
- IBOutlet UILabel *txtNSString;
- IBOutlet UILabel *txtNSDate;
- IBOutlet UILabel *txtNSArray;
- IBOutlet UILabel *txtNSDictionary;
- }
- @end
ViewController.m文件中最重要的是两个方法:
saveNSUserDefaults:用于将各种类型数据保存到NSUserDefaults中
readNSUserDefautls:用于从NSUserDefaults中读取各种类型的数据。在viewDidLoad中调用这两个方法就可以看出结果咯
- #import "ViewController.h"
- @interface ViewController ()
- @end
- @implementation ViewController
- - (void)viewDidLoad
- {
- [super viewDidLoad];
- [self saveNSUserDefaults]; //调用此方法将各种数据存储到NSUserDefautls中,在下面定义
- [self readNSUserDefaults]; //调用此方法从NSUserDefautls中读取各种数据,在下面定义
- }
- - (void)viewDidUnload
- {
- [txtNSString release];
- txtNSString = nil;
- [txtNSDate release];
- txtNSDate = nil;
- [txtNSArray release];
- txtNSArray = nil;
- [txtNSDictionary release];
- txtNSDictionary = nil;
- [txtInteger release];
- txtInteger = nil;
- [txtFloat release];
- txtFloat = nil;
- [txtDouble release];
- txtDouble = nil;
- [super viewDidUnload];
- // Release any retained subviews of the main view.
- }
- - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
- {
- return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
- }
- - (void)dealloc {
- [txtNSString release];
- [txtNSDate release];
- [txtNSArray release];
- [txtNSDictionary release];
- [txtInteger release];
- [txtFloat release];
- [txtDouble release];
- [super dealloc];
- }
- //保存数据到NSUserDefaults
- -(void)saveNSUserDefaults
- {
- NSString *myString = @"enuola";
- int myInteger = 100;
- float myFloat = 50.0f;
- double myDouble = 20.0;
- NSDate *myDate = [NSDate date];
- NSArray *myArray = [NSArray arrayWithObjects:@"hello", @"world", nil];
- NSDictionary *myDictionary = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"enuo", @"20", nil] forKeys:[NSArray arrayWithObjects:@"name", @"age", nil]];
- //将上述数据全部存储到NSUserDefaults中
- NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
- //存储时,除NSNumber类型使用对应的类型意外,其他的都是使用setObject:forKey:
- [userDefaults setInteger:myInteger forKey:@"myInteger"];
- [userDefaults setFloat:myFloat forKey:@"myFloat"];
- [userDefaults setDouble:myDouble forKey:@"myDouble"];
- [userDefaults setObject:myString forKey:@"myString"];
- [userDefaults setObject:myDate forKey:@"myDate"];
- [userDefaults setObject:myArray forKey:@"myArray"];
- [userDefaults setObject:myDictionary forKey:@"myDictionary"];
- //这里建议同步存储到磁盘中,但是不是必须的
- [userDefaults synchronize];
- }
- //从NSUserDefaults中读取数据
- -(void)readNSUserDefaults
- {
- NSUserDefaults *userDefaultes = [NSUserDefaults standardUserDefaults];
- //读取数据到各个label中
- //读取整型int类型的数据
- NSInteger myInteger = [userDefaultes integerForKey:@"myInteger"];
- txtInteger.text = [NSString stringWithFormat:@"%d",myInteger];
- //读取浮点型float类型的数据
- float myFloat = [userDefaultes floatForKey:@"myFloat"];
- txtFloat.text = [NSString stringWithFormat:@"%f",myFloat];
- //读取double类型的数据
- double myDouble = [userDefaultes doubleForKey:@"myDouble"];
- txtDouble.text = [NSString stringWithFormat:@"%f",myDouble];
- //读取NSString类型的数据
- NSString *myString = [userDefaultes stringForKey:@"myString"];
- txtNSString.text = myString;
- //读取NSDate日期类型的数据
- NSDate *myDate = [userDefaultes valueForKey:@"myDate"];
- NSDateFormatter *df = [[NSDateFormatter alloc] init];
- [df setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
- txtNSDate.text = [NSString stringWithFormat:@"%@",[df stringFromDate:myDate]];
- //读取数组NSArray类型的数据
- NSArray *myArray = [userDefaultes arrayForKey:@"myArray"];
- NSString *myArrayString = [[NSString alloc] init];
- for(NSString *str in myArray)
- {
- NSLog(@"str= %@",str);
- myArrayString = [NSString stringWithFormat:@"%@ %@", myArrayString, str];
- [myArrayString stringByAppendingString:str];
- // [myArrayString stringByAppendingFormat:@"%@",str];
- NSLog(@"myArrayString=%@",myArrayString);
- }
- txtNSArray.text = myArrayString;
- //读取字典类型NSDictionary类型的数据
- NSDictionary *myDictionary = [userDefaultes dictionaryForKey:@"myDictionary"];
- NSString *myDicString = [NSString stringWithFormat:@"name:%@, age:%d",[myDictionary valueForKey:@"name"], [[myDictionary valueForKey:@"age"] integerValue]];
- txtNSDictionary.text = myDicString;
- }
- @end
好了,运行一下,可以看到xib文件中的各种数据已经绑定上了吧?
再次运行的时候,可以把viewDidLoad中的 [self saveNSUserDefaults]; 这一行注释掉,让程序直接读取而不存储数据,发现以前保存的数据仍然可以读取到界面上。
嘻嘻,很简单吧,就这样就可以是实现数据的存储了。
下面讲一下原理:
你可能会问一个问题:NSUserDefautls将数据存储在什么地方了???我都没有显示的指定路径???很疑惑吧。。。。
用NSUserDefaults存储的数据下次程序运行的时候依然存在,它把数据存储在什么地方了?如何能够清除?
/UsersLibrary/Application Support/iPhoneSimulator/4.1/Applicati*****/29788E40-AF47-45A0-8E92-3AC0F501B7F4/,(这个是应用程序对应在mac上的位置)
这个下面有/Library/Prefereces,里面有个plist文件,存储的就是你的userDefaults
想要删掉的话,用removeObjectForKey或者删掉沙盒,也就是你的应用程序然后重新安装。
Object-C中对自定义类实现<NSCopying协议>(转自http://blog.csdn.net/enuola/article/details/7801127)
如果尝试使用自定义类(例如,人类(person类)、地址簿类(myBook类)、分数类(Fraction类))中的copy方法,如
- myBook = [myBook mutableCopy];
- person = [Person copy];
等类似的操作,将会收到一条异常出错的消息,它可能如下所示:
-[Fraction copyWithZone:]: unrecognized selector sent to instance 0x7fabb8414380
这种错误,是对于自定义类,要实现使用自己的类进行复制,必须根据<NSCopying>协议实现其中的一两个方法。
下面将展示如何为自定义的分数类(Fraction类)添加copy方法。注意:这里描述的复制策略的技巧非常适合于你自己定义的类。如果这些类是任何Foundation类的子类,那么可能需要实现较为复杂的复制策略。必须考虑这样一个事实:超类可能已经实现了它自己的复制策略。
实现<NSCopying>协议时,类必须实现copyWithZone:方法来响应copy消息。(这条copy消息仅将一条带有nil参数的copyWithZone:消息发送给你的类)。注意,如果想要区分可变副本和不可变副本,那么copyWithZone:应该返回不可变副本,而mutableCopyWithZone:应该返回可变副本。产生对象的可变副本并不要求被复制的对象本身也是可变的(反之亦然),想要产生不可变副本的可变副本是很合理的(例如,字符串对象)。
在Fraction.h文件中如下所示:(其中Fraction是NSObject的子类,并且符合NSCopying协议)
- #import <Foundation/Foundation.h>
- @interface Fraction : NSObject<NSCopying>
- {
- int a, b;
- }
- @property int a, b;
- -(void)setTo:(int) a over: (int) b;
- -(void)print;
- @end
在实现文件Fraction.m中,为新方法添加如下定义:
- #import "Fraction.h"
- @implementation Fraction
- @synthesize a,b;
- -(void)setTo:(int) aa over: (int) bb
- {
- a = aa;
- b = bb;
- }
- -(void)print
- {
- NSLog(@"%i/%i",a, b);
- }
- //实现NSCopying协议的方法,来使此类具有copy功能
- -(id)copyWithZone:(NSZone *)zone
- {
- Fraction *newFract = [[Fraction allocWithZone:zone] init];
- [newFract setTo:a over:b];
- return newFract;
- }
- @end
在文件main.m中对于上述类的测试代码如下:
- #import <Foundation/Foundation.h>
- #import "Fraction.h"
- int main(int argc, const char * argv[])
- {
- @autoreleasepool {
- Fraction *f1 = [[Fraction alloc] init];
- Fraction *f2;
- [f1 setTo:2 over:5];
- f2 = [f1 copy];
- [f2 setTo:1 over:3];
- [f1 print];
- [f2 print];
- [f1 release];
- [f2 release];
- }
- return 0;
- }
由此可以实现对自定义类Fraction类的拷贝,运行结果如下:
2/5
1/3
该程序创建了一个名为f1的Fraction对象并将其设置为2/5.然后,它调用copy方法来产生副本,copy方法向你的对象发送copyWithZone:消息,这个方法产生了一个新的Fraction,将f1的值复制到其中,并返回结果。回到main函数中,再将这个结果赋值给f2.随即,将f2中的值设置为分数1/3,这样就验证了这些操作对原始分数f1是没有影响的。
如果你的类可以产生子类,那么copyWithZone:方法将被继承。在这种情况下,该方法中的程序行:
- //无子类是可以这样实现
- Fraction *newFract = [[Fraction allocWithZone:zone] init];
应该改为:
- //有子类时,需要这样实现
- Fraction *newFract = [[[self class] allocWithZone:zone] init];
这样,可以从该类分配一个新的对象,而这个类的copy的接收着(例如,如果它产生了一个名为NewFraction 的子类,那么应该确保在继承的方法中分配了新的NewFraction对象,而不是Fraction对象)。
如果编写一个类的copyWithZone:方法,而该类的超类也实现了<NSCopying>协议,那么应该先调用超类的copy方法以复制继承来的实例变量,然后加入自己的代码以复制想要添加到该类中的任何附加的实例变量(如果有的话)。
你必须确定是否在类中实现浅复制或深复制,并为其编写文档,以告知类的其他使用者。
嘿嘿