26, extern
关键字
extern关键字主要是声明这个变量已经在其他文件中声明过了(声明全局变量或者函数),如果编译过程中遇到带有extern的变量,就会去其他模块中寻找它的定义。但是注意,它只是声明而不是定义,也就是说,如果想要使用这个变量,只需要包含这个变量定义所在的位置的头文件即可。在编译阶段,虽然本模块找不到该函数或者变量,但是不会报错,会在连接时从定义的模块中找到该变量或者函数。总之,extern就是用来声明这个东西已经在其他文件中声明过了。不管是变量还是函数,都可以使用extern函数这样声明。不过函数不使用extern和使用extern关键字声明没有太大的区别。而对于变量,如果全局变量定义和使用不在一个文件中,就会发生未定义的错误。而如果在这个文件中重新定义一个同名的变量,又会发生重定义的错误。所以,这种情况就需要使用extern关键字在本文件中声明即可。
关于extern和static:两者其实是水火不容,因为extern的作用为让变量或者函数跨文件,而static的作用是让变量或者函数的作用域保留在本文件中,所以二者不能同时使用。一般定义static全局变量都是在实现文件中,而不会再跑到头文件中去声明一份。
25, 生成随机汉字
NSStringEncoding gbkEncoding = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
NSInteger randomH = 0xA1 + arc4random()%(0xFE - 0xA1+1);
NSInteger randomL = 0xB0 + arc4random()%(0xF7 - 0xB0+1);
NSInteger number = (randomH<<8)+randomL;
NSData *data = [NSData dataWithBytes:&number length:2];
NSString *string = [[NSString alloc] initWithData:data encoding:gbkEncoding];
NSLog(@"%@",string);
24, 修改UITextView
行间距
- (void)textViewDidChange:(UITextView *)textView {
/** textview 改变字体的行间距 */
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineSpacing = 16; /** 字体的行间距 */
NSDictionary *attributes = @{
NSFontAttributeName:[UIFont systemFontOfSize:15],
NSParagraphStyleAttributeName:paragraphStyle
};
textView.attributedText = [[NSAttributedString alloc] initWithString:textView.text attributes:attributes];
}
23, 监听textField输入的变化
[textField addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
-(void)textFieldDidChange :(UITextField *)theTextField{
NSLog( @"text changed: %@", theTextField.text);
}
22, tableView 滑动删除, 记录一下, 老是忘
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewCellEditingStyleDelete;
}
// 先要设Cell可编辑
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
//进入编辑模式,按下出现的编辑按钮后
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
self.searchRecordArray = [NSMutableArray arrayWithArray:[YFUserDefaults objectForKey:searchRecordArrayKey]];
[self.searchRecordArray removeObjectAtIndex:indexPath.row];
[YFUserDefaults setObject:self.searchRecordArray forKey:searchRecordArrayKey];
[YFUserDefaults synchronize];
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
//修改编辑按钮文字
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath {
return @"删除";
}
21, 修改UISearchBar 右侧 Cancel 字体和颜色
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[[UIBarButtonItem appearanceWhenContainedIn:[UISearchBar class], nil] setTitle:@"取消"];
[[UIBarButtonItem appearanceWhenContainedIn:[UISearchBar class], nil]
setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor blackColor]}
forState:UIControlStateNormal];
#pragma clang diagnostic pop
修改 UISearchBar
中 placeholder
的字体颜色
UITextField *textFiled = [_searchBar valueForKey:@"_searchField"];
[textFiled setValue:[UIColor redColor] forKeyPath:@"_placeholderLabel.textColor"];
20, reloadData
的时候tableView
上下跳动问题
最近碰到一种情况, 即使数据源没有改变, 刷新tableView
的时候会上下跳动原因是因为这个方法
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
// 因为这里写一个动画, cell出列时候会有一个偏移动画, 应该这里加个判断, 滚动以后才执行下边的动画代码
cell.layer.transform = CATransform3DMakeTranslation(0, (_isDownword ? -15 : 15), 0);
cell.alpha = 0.5;
/** 17.1.11 YF 解决cell动画过程中不能交互的问题 */
[UIView animateWithDuration:0.7f delay:0 options:UIViewAnimationOptionAllowUserInteraction animations:^{
cell.layer.transform = CATransform3DMakeTranslation(0,0,0);
cell.alpha = 1;
} completion:nil];
}
19, UIView
动画过程中允许与用户交互,
比如cell出列时候写个动画, 如果直接执行, 滑动过程中是不可以暂停的, 需要设置一下这个属性,允许滑动过程中与用户的交互
设置
options
的UIViewAnimationOptionAllowUserInteraction
属性可以完成
[UIView animateWithDuration:0.7f delay:0 options:UIViewAnimationOptionAllowUserInteraction animations:^{
// TODO: ...
} completion:nil];
18, 设置navigationBar左边的leftBarButtonItem的边距
设置
negativeSpacer.width
可以调整距离左边的间距
- (NSArray<UIBarButtonItem *> *)yf_leftBarButtonItems {
UIImage *backImage = [UIImage imageNamed:@"night_icon_back"];
UIBarButtonItem *leftBtnItem = [[UIBarButtonItem alloc] initWithImage:backImage
style:UIBarButtonItemStylePlain
target:self
action:@selector(yf_popViewController)];
UIBarButtonItem *negativeSpacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
target:nil
action:nil];
negativeSpacer.width = -15;
return @[negativeSpacer, leftBtnItem];
}
- (void)yf_popViewController {
[self.navigationController popViewControllerAnimated:YES];
}
17 , 小弹窗
底部显示的小弹窗, 自动消失, 只做了简单的适配, 显示一行文本
+ (void)yf_alertAutohHide:(NSString *)message {
static BOOL hasShow = NO;
if (hasShow) return;
UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow;
CGFloat screenW = [UIScreen mainScreen].bounds.size.width;
CGFloat screenH = [UIScreen mainScreen].bounds.size.height;
UILabel *alertLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 0, 30.0f)];
alertLabel.text = message;
alertLabel.textAlignment = NSTextAlignmentCenter;
alertLabel.font = [UIFont systemFontOfSize:15.0f];
alertLabel.textColor = [UIColor whiteColor];
alertLabel.backgroundColor = [UIColor grayColor];
alertLabel.layer.cornerRadius = 5.0f;
alertLabel.layer.masksToBounds = YES;
NSMutableDictionary *attr = [NSMutableDictionary new];
attr[NSFontAttributeName] = alertLabel.font;
CGSize alertLabelSize = [message boundingRectWithSize:CGSizeMake(screenW-30.0f, 30.0f)
options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:attr
context:nil].size;
CGRect tempFrame = alertLabel.frame;
tempFrame.size.width = alertLabelSize.width + 10.0f;
alertLabel.frame = tempFrame;
alertLabel.center = keyWindow.center;
CGRect alertLabelFrame = alertLabel.frame;
alertLabelFrame.origin.y = screenH - 100.0f;
alertLabel.frame = alertLabelFrame;
alertLabel.alpha = 0;
alertLabel.transform = CGAffineTransformMakeScale(0.7f, 0.7f);
[keyWindow addSubview:alertLabel];
[UIView animateWithDuration:0.3f delay:0 usingSpringWithDamping:0.4f initialSpringVelocity:0.5f options:UIViewAnimationOptionCurveEaseInOut animations:^{
hasShow = YES;
alertLabel.alpha = 1.0f;
alertLabel.transform = CGAffineTransformIdentity;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.6f delay:1.5f options:UIViewAnimationOptionCurveEaseInOut animations:^{
alertLabel.alpha = 0;
} completion:^(BOOL finished) {
[alertLabel removeFromSuperview];
hasShow = NO;
}];
}];
}
16, 让tableView滑动中自动加载更多
这个方法不太好, 还是用
MJRefresh
吧, 有自动刷新
if (self.tableView.contentOffset.y + (scrollView.frame.size.height) > scrollView.contentSize.height) {
// 这里调用加载更多方法
}
15, 限制UITextField 输入字数
[self.textField addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
- (void)textFieldDidChange:(UITextField *)textField {
CGFloat maxLength = 10;
NSString *toBeString = textField.text;
//获取高亮部分
UITextRange *selectedRange = [textField markedTextRange];
UITextPosition *position = [textField positionFromPosition:selectedRange.start offset:0];
if (!position || !selectedRange) {
if (toBeString.length > maxLength) {
NSRange rangeIndex = [toBeString rangeOfComposedCharacterSequenceAtIndex:maxLength];
if (rangeIndex.length == 1) {
textField.text = [toBeString substringToIndex:maxLength];
} else {
NSRange rangeRange = [toBeString rangeOfComposedCharacterSequencesForRange:NSMakeRange(0, maxLength)];
textField.text = [toBeString substringWithRange:rangeRange];
}
}
}
}
14, 给UILabel设置字体的粗细
字体粗细
UIFontWeightUltraLight
- 超细字体
UIFontWeightThin
- 纤细字体
UIFontWeightLight
- 亮字体
UIFontWeightRegular
- 常规字体
UIFontWeightMedium
- 介于Regular和Semibold之间
UIFontWeightSemibold
- 半粗字体
UIFontWeightBold
- 加粗字体
UIFontWeightHeavy
- 介于Bold和Black之间
UIFontWeightBlack
- 最粗字体(理解)
label.font = [UIFont systemFontOfSize:12 weight:UIFontWeightUltraLight];
label.font = UIFont.systemFont(ofSize: 12, weight: UIFontWeightUltraLight)
13, 使用WKWebView #import <WebKit/WebKit.h>
添加加载进度条
添加监听
// 使用KVO监听网页加载进度
[webView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];
// KVO回调方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id>*)change context:(void *)context{
// 获得进度值
CGFloat progress = [change[NSKeyValueChangeNewKey] floatValue];
// 显示进度
. . .
}
12, 去掉HTML字符串标签的方法
-(NSString *)filterHTML:(NSString *)html
{
NSScanner * scanner = [NSScanner scannerWithString:html];
NSString * text = nil;
while([scanner isAtEnd]==NO)
{
//找到标签的起始位置
[scanner scanUpToString:@"<" intoString:nil];
//找到标签的结束位置
[scanner scanUpToString:@">" intoString:&text];
//替换字符
html = [html stringByReplacingOccurrencesOfString:[NSString stringWithFormat:@"%@>",text] withString:@""];
}
// NSString * regEx = @"<([^>]*)>";
// html = [html stringByReplacingOccurrencesOfString:regEx withString:@""];
return html;
}
11, 使用 Spring Animation API 创建动画
10, 修改UIButton内字体的对其方式
我们首先要使用
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
这行代码,把按钮的内容(控件)的对齐方式修改为水平左对齐,但是这们会紧紧靠着左边,不好看, 所以还可以修改属性:
button.titleEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0);
这行代码可以让按钮的内容(控件)距离左边10个像素,
9, 计算文字高度, 这个是NSString分类里的方法
- (CGSize)sizeForFont:(UIFont *)font size:(CGSize)size mode:(NSLineBreakMode)lineBreakMode {
CGSize result;
if (!font) font = [UIFont systemFontOfSize:12];
if ([self respondsToSelector:@selector(boundingRectWithSize:options:attributes:context:)]) {
NSMutableDictionary *attr = [NSMutableDictionary new];
attr[NSFontAttributeName] = font;
if (lineBreakMode != NSLineBreakByWordWrapping) {
NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
paragraphStyle.lineBreakMode = lineBreakMode;
attr[NSParagraphStyleAttributeName] = paragraphStyle;
}
CGRect rect = [self boundingRectWithSize:size
options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
attributes:attr context:nil];
result = rect.size;
} else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
result = [self sizeWithFont:font constrainedToSize:size lineBreakMode:lineBreakMode];
#pragma clang diagnostic pop
}
return result;
}
8, 获取 webView 高度
初始化,self.view是父控件
_webView = [[UIWebView alloc] initWithFrame: CGRectMake(0, 0, self.view.frame.size.width, 0)];
_webView.delegate = self;
_webView.scrollView.bounces = NO;
_webView.scrollView.showsHorizontalScrollIndicator = NO;
_webView.scrollView.scrollEnabled = NO;
[_webView sizeToFit];
设置内容,这里包装一层div,用来获取内容实际高度(像素),htmlcontent是html格式的字符串
NSString * htmlcontent = [NSString stringWithFormat:@"<div id=\"webview_content_wrapper\">%@</div>", htmlcontent];
[_webView loadHTMLString:htmlcontent baseURL:nil];
delegate的方法重载
- (void)webViewDidFinishLoad:(UIWebView *)webView{
//获取页面高度(像素)
NSString *clientheight_str = [webView stringByEvaluatingJavaScriptFromString: @"document.body.offsetHeight"]; float clientheight = [clientheight_str floatValue];
//设置到WebView上
webView.frame = CGRectMake(0, 0, self.view.frame.size.width, clientheight);
//获取WebView最佳尺寸(点)
CGSize frame = [webView sizeThatFits:webView.frame.size];
//获取内容实际高度(像素)
NSString *height_str= [webView stringByEvaluatingJavaScriptFromString: @"document.getElementById('webview_content_wrapper').offsetHeight + parseInt(window.getComputedStyle(document.getElementsByTagName('body')[0]).getPropertyValue('margin-top')) + parseInt(window.getComputedStyle(document.getElementsByTagName('body')[0]).getPropertyValue('margin-bottom'))"];
float height = [height_str floatValue];
//内容实际高度(像素)* 点和像素的比
height = height *frame.height / clientheight;
//再次设置WebView高度(点)
webView.frame = CGRectMake(0, 0, self.view.frame.size.width, height);
}
7, 可以随处拖动的 UIButton
一、注册拖动动画
UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc]initWithTarget:self
action:@selector(doHandlePanAction:)];
[self.btn addGestureRecognizer:panGestureRecognizer];
注:btn就是要加入拖动的View子类。
二、拖动处理函数
-(void)doHandlePanAction:(UIPanGestureRecognizer *)paramSender {
CGPoint point = [paramSender translationInView:self.view];
paramSender.view.center = CGPointMake(paramSender.view.center.x + point.x, paramSender.view.center.y + point.y);
[paramSender setTranslation:CGPointMake(0, 0)inView:self.view];
}
最后一句为关键代码,因为拖动起来一直是在递增,所以每次都要用 setTranslation: 方法将每次触摸都设置为 0 位置,这样才不至于不受控制般滑动出视图.
6, 清除SDWebImage 缓存
/** 清空图片缓存 */
在SDWebImage中有两种缓存,一种是磁盘缓存,一种为内存缓存,框架都提供了相应的方法:
[[SDImageCache sharedImageCache] clearDisk];
[[SDImageCache sharedImageCache] clearMemory];
在IOS7中这两个方法缓存总清除不干净,即使断网下还是会有数据。因为在IOS7中,缓存机制做了修改,使用上述两个方法只清除了SDWebImage的缓存,没有清除系统的缓存,所以我们可以在清除缓存的代理中额外添加以下:
[[NSURLCache sharedURLCache] removeAllCachedResponses];
5, 判断app是否可以访问 相机
包含头文件:
#import<AVFoundation/AVCaptureDevice.h>
#import<AVFoundation/AVMediaFormat.h>
/** 如果没有访问相机的权限 */
AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
if(authStatus == AVAuthorizationStatusRestricted || authStatus ==AVAuthorizationStatusDenied){
//无权限
KCODEALERTSHOW(@"请在iPhone的\"设置-隐私-相机\"选项中, 允许XXX访问你的相机");
}
4,改变 UITextView
行间距
首先设置代理, 然后在如下代理方法里设置间距
补充
下边这个方法用了以后, 输入汉字, 比如河南, 当点h的时候文本框会捕获这个h, 所以输入会有问题, 应该加一句
if (textView.markedTextRange != nil) return;
- (void)textViewDidChange:(UITextView *)textView {
/** textview 改变字体的行间距 */
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineSpacing = 8; /** 字体的行间距 */
NSDictionary *attributes = @{
NSFontAttributeName:[UIFont systemFontOfSize:15],
NSParagraphStyleAttributeName:paragraphStyle
};
textView.attributedText = [[NSAttributedString alloc] initWithString:textView.text attributes:attributes];
}
3 ,iOS 设置UITextView和UITextFiled一样的边框
UITextView *textView = [[UITextView alloc]initWithFrame:CGRectMake(10, 100, 200, 40)];
textView.layer.borderColor = [[UIColor colorWithRed:215.0 / 255.0 green:215.0 / 255.0 blue:215.0 / 255.0 alpha:1] CGColor];
textView.font = [UIFont systemFontOfSize:18];
textView.layer.borderWidth = 0.6f;
textView.layer.cornerRadius = 6.0f;
2, 父视图透明, 子视图不透明用这个方法设置
FatherView.backgroundColor = [[UIColor lightGrayColor] colorWithAlphaComponent:0.5];
1, +load
和 +initialize
- initWithFrame
和 - initWithCoder
+load
和 +initialize
是 Objective-C runtime 会自动调用的两个类方法。但是它们被调用的时机却是有差别的,+load
方法是在类被加载的时候调用的,而+initialize
方法是在类或它的子类收到第一条消息之前被调用的,这里所指的消息包括实例方法和类方法的调用。也就是说+initialize
方法是以懒加载的方式被调用的,如果程序一直没有给某个类或它的子类发送消息,那么这个类的+initialize
方法是永远不会被调用的。此外+load
方法还有一个非常重要的特性,那就是子类、父类和分类中的+load
方法的实现是被区别对待的。换句话说在 Objective-C runtime 自动调用+load
方法时,分类中的+load方法并不会对主类中的+load
方法造成覆盖
- initWithFrame
和 - initWithCoder
当我们所写的程序里没用用Nib文件(XIB)时,用代码控制视图内容,需要调用initWithFrame去初始化
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [superinitWithFrame:frame]) {
// 初始化代码
}
return self;
}
用于视图加载nib文件,从nib中加载对象实例时,使用 initWithCoder初始化这些实例对象
- (instancetype)initWithCoder:(NSCoder*)coder
{
if (self = [superinitWithcoder:coder]) {
// 初始化代码
}
return self;
}