啰嗦一句
之前使用的博客系统似乎要停掉了, 自己经常会记录一些易忘记的代码片段, 还是拷贝到简书来吧...简书不支持自动生成大纲目录啊...这好尴尬...
持续继承
Jenkins 中 SVN 由于服务器时间不一致导致无法更新到最新版本
在链接中增加@HEAD
https://xxxxx/项目名称@HEAD
xib技巧
xib中用 UIColor 设置边框颜色
选中xib中的label,在右边栏的第三个标签页中第三项是User Defined Runtime Attributes
添加一个keyPath,keyPath值为layer.borderWidth,类型为NSNumber,值为你想要设置的边框宽度。第二个是设置边框的颜色layer.borderColorFromUIColor,为了兼容CALayer 的KVC ,你得给CALayer增加一个分类
@implementation CALayer (Additions)
- (void)setBorderColorFromUIColor:(UIColor *)color {
self.borderColor = color.CGColor;
}
@end
在 xib 中添加 xib
在 subview 的 xib 中添加如下代码和属性
@property (nonatomic, strong) IBOutlet UIView *view;
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
if (self = [super initWithCoder:aDecoder]) {
[self setup];
}
return self;
}
- (void)setup {
[[NSBundle mainBundle] loadNibNamed:@"ANScanDrawView" owner:self options:nil];
[self addSubview:self.view];
[self.view mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.left.bottom.right.equalTo(self);
}];
}
修改 subview 的 xib 的 file's Owner 为其 Class 并且拖拽 view 属性.
就可以在 superview 的 xib 中就可以和正常操作一样添加 subview 了.记得指定 Custom Class.
约束
别挤我
Content Compression Resistance = 不许挤我!
这个属性的优先级(Priority)越高,越不“容易”被压缩。也就是说,当整体的空间装不下所有的View的时候,Content Compression Resistance优先级越高的,显示的内容越完整。
Content Hugging = 抱紧!
这个属性的优先级越高,整个View就要越“抱紧”View里面的内容。也就是说,View的大小不会随着父级View的扩大而扩大。
topLayoutGuide和bottomLayoutGuide
就是直接使用UILayoutSupport定义的length属性。
这个时候就有个地方要特别注意,在运行到viewDidLoad的时候,length的值是0,因为这个时候界面还没有被绘制,所以一个解决方法就是在ViewController的updateViewConstraints方法里面去使用length值添加约束。如下:
- (void)updateViewConstraints {
[_topView mas_updateConstraints:^(MASConstraintMaker *make) {
// 直接利用其length属性
make.top.equalTo(self.view.mas_top).with.offset(self.topLayoutGuide.length);
}];
[super updateViewConstraints];
}
在Masonry的新版中,为UIViewController增加了一个新的Category: MASAdditions,增加了mas_topLayoutGuide和mas_bottomLayoutGuide两个方法。
自定义baseline
对于自定义的View来说,baseline默认就是整个view的底部,如果想改变baseline的话,可以重写UIView的viewForBaselineLayout,返回当成baseline的view即可。
- (UIView *)viewForBaselineLayout {
return _imageView;
}
导航栏 TitleView Frame 异常的问题
- 在自定义titleview 里重写 intrinsicContentSize 属性,代码如下
@property (nonatomic, assign) CGSize intrinsicContentSize;
- 在赋值到 TitleView 之前指定属性的 Size 即可.
UITableView
UITableViewStyleGrouped的几个问题
- Plain的时候Section的Header和Footer会默认悬停,Grouped不会.
- 如果用Grouped的话,第一个Section Header会莫名其妙不见,必须使用代理方法返回Section Header的高度,而不能给TableView直接赋值.
tableView.sectionHeaderHeight=86;
- 给TableView的tableFooterView和tableHeaderView指定一个0.01高度的UIView可以消除Grouped多余的头部和底部的间隙, 直接指定0是不行的.
UINavigationController push 的时候界面卡死的问题
@interface ANNavigationController () <UINavigationControllerDelegate>
@end
@implementation ANNavigationController
- (void)viewDidLoad {
[super viewDidLoad];
// 代理
self.delegate = self;
}
/**
由控制器控制状态栏颜色
*/
- (UIViewController *)childViewControllerForStatusBarStyle{
return self.topViewController;
}
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
if (self.viewControllers.count > 0) {
viewController.hidesBottomBarWhenPushed = YES;
/**
加入全局右滑 POP 功能
*/
self.interactivePopGestureRecognizer.delegate = nil;
}
[super pushViewController:viewController animated:animated];
}
- (void)navigationController:(UINavigationController *)navigationController
didShowViewController:(UIViewController *)viewController
animated:(BOOL)animated {
if (viewController == navigationController.viewControllers[0]) {
navigationController.interactivePopGestureRecognizer.enabled = NO;
} else {
navigationController.interactivePopGestureRecognizer.enabled = YES;
}
}
@end
NSString
过滤非法字符
通过巧妙的拆分再合并去除特殊字符
NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString:@"\"/\\ <>*|'"];
NSString *trimmed = [[string componentsSeparatedByCharactersInSet:set] componentsJoinedByString: @""];
Data 的字符串转 NSData
- (NSData *)dataWithHexString:(NSString *)hexString {
NSInteger len = [hexString length];
char *myBuffer = (char *)malloc(len / 2 + 1);
bzero(myBuffer, len / 2 + 1);
for (int i = 0; i < len - 1; i += 2) {
unsigned int anInt;
NSString * hexCharStr = [hexString substringWithRange:NSMakeRange(i, 2)];
NSScanner * scanner = [NSScanner scannerWithString:hexCharStr] ;
[scanner scanHexInt:&anInt];
myBuffer[i / 2] = (char)anInt;
}
NSData *hexData = [[NSData alloc] initWithBytes:myBuffer length:len/2];
free(myBuffer);
return hexData;
}
截取字符串时 emoji 乱码的问题
因为 emoji 的 length 并不是1, 所以按长度截取 emoji 会出现乱码问题
if (sender.text.length > kMaxLength) {
NSRange range = [sender.text rangeOfComposedCharacterSequenceAtIndex:kMaxLength];
sender.text = [sender.text substringToIndex:range.location];
}
WKWebView
预览资源, 如 PDF Excel Word 等.显示过小, 需要放大怎么办.
NSString *jScript = @"var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);";
WKUserScript *wkUScript = [[WKUserScript alloc] initWithSource:jScript injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];
WKUserContentController *wkUController = [[WKUserContentController alloc] init];
[wkUController addUserScript:wkUScript];
WKWebViewConfiguration *wkWebConfig = [[WKWebViewConfiguration alloc] init];
wkWebConfig.userContentController = wkUController;
WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:wkWebConfig];
成长
记录着自己怎样进入了 iOS 的世界...
2016-06 学习日记
2016-06-03
- LaunchImage : Launch Images Source -> LaunchImage
- AppIcon : iOS icon is pre-rendered 不需要系统渲染
- 创建窗口和根视图控制器
- 添加子控制器UITableViewController
- 自定义TabBarController
2016-06-06
- 项目分层
- PCH import
- 创建UITableViewController子类
- 创建UINavigationController并设置子控制器
- 创建UINavigationController的子类,设置hidesBottomBarWhenPushed
2016-06-07
- UINavigationController的UIBarButtonItem的Extension自定义
- 拦截push操作实现统一的导航栏按钮
- 设置整个项目UIBarButtonItem的主题颜色
- 根据是否是DEBUG来控制是否打印日志.
- (void)initialize 只在第一次使用的时候调用一次
2016-06-13
- 设置UINavigationBar的主题 背景图片
- [NSMutableDictionary dictionaryWithDictionary:xxx] 字典拷贝
- 创建UISearchBar
- 用UITextField来 订制 UISearchBar
- 用继承来实现自定义控件
- 继承UIButton实现文字在左图标在右的按钮
2016-06-14
- iOS 10 真棒!
- 自定义控件,弹出菜单,通过UIButton作为遮罩,加上UIImageView显示图片完成.
- 代理 Delegate
- 扩展UIView, 增加x y centerX centerY width height size属性,操作简便
- 扩展弹出菜单,以增加功能
- 枚举
- 研究UITabBar控件,学会举一反三,研究复杂控件结构,学会对私有类型进行处理
2016-06-15
- 自定义TabBar 遍历SubViews来修改布局以及增加按钮
- KVC和OC运行时机制来使UITabBarViewController的TabBar替换为我们自定义的TabBar
2016-06-16
- work..打包...
- 复习代理,监听TabBar中加号按钮的点击事件
- 自定义控制器和NavigationViewController initWithRootViewController来进行present和dismiss
2016-06-20
- work..打包...
- 图片拉伸的问题
- 第一次运行当前版本的判断 NSUserDefaults [[NSBundle mainBundle].infoDictionary
- CFStringRef和NSString之间的相互桥接转换 __bridge
- 获取屏幕宽度
- UIScrollView + PageControl制作新特性页面
2016-06-21
- 完善新特性页面,添加按钮
- 按钮制作复选框效果.
- 切换根控制器 UIWindow *window = [UIApplication sharedApplication].keyWindow;
- OAuth
- UIWebView 发送请求以及 通过代理拦截请求
2016-06-22
- AFNetworking 发送GET/POST请求
- MBProgressHUD 显示loading提示
- MJExtension 模型和字典的转换
- 了解运行时
- plist和Object的归档和解档
2016-06-23
- AFNetworking 不支持的Response ContentType在AFURLResponseSerialization.m中找到对应的类修改init方法中加载的默认ContentType类型
- SDWebImage 异步图像下载 以及 内存警告时候的缓存清理
- UITableView 加载数据
- 大F到手,无心学习了....罪过...
2016-06-24
- AFNetworking 监听网络状态的切换
- 自带的UIRefreshControl实现下拉刷新(继承自UIControl,通过AddTarget实现操作)
...支撑能力开放平台项目...
2016-07 学习日记
2016-07-12
- 复习
- 延时执行代码
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// CODE;
});
- UILabel的简单位移动画,来实现刷出新微博的消息提示
- 利用 Xib 自定义一个UIView,实现上拉刷新组件.
- 上拉刷新的实现关于高度计算没太明白...后续再看看...
- 自定义TextView,实现带提示文字的功能
- 通知,增加通知来监听TextView的文字变化 (dealloc要移除)
2016-07-26
- 自定义UIView实现工具条, 按钮的Tag赋值一个枚举类型,来区分不同的按钮
- TextView.alwaysBounceVertical = YES
- viewDidAppear中TextView成为第一响应者,以便自动弹出键盘
- 成为TextView代理scrollViewWillBeginDragging方法中,设置视图endEditing,关闭键盘
2016-07-27
- 代开系统照相机和相册 来提供一张照片.通过代理实现图片的获取,添加到自己定义的UIView中.
- 自定义UIView在TextView中显示图片.
- AFN发送微博, form-data编码格式传送图片
2016-07-28
- 重构,分层
- NSTimer 获取 未读消息
- TabBarItem 未读消息的显示 badgeValue
- 应用未读消息的显示
[UIApplication sharedApplication].applicationIconBadgeNumber
- APP 进入后台后申请继续运行
2016-07-29
- 控制 TableView 滚动 (点击 TabBarItem 触发) scrollToRowAtIndexPath
2016-08 学习日记
2016-08-01
- 在 iOS 8 之后,设置应用的未读消息需要申请通知权限
float version = [[[UIDevice currentDevice] systemVersion] floatValue];
if (version >= 8.0) {
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
[application registerForRemoteNotifications];
}
- 自定义Cell和Frame, 注意分层减少依赖,以便后期维护.
2016-08-04
- 完善 Cell, TableView 的细节
- UILabel 多行,设置 numberOfLines = 0, 计算高度的时候用
CGSize textMaxSize = CGSizeMake(textMaxWidth, MAXFLOAT);
[text boundingRectWithSize:textMaxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : YXStatusOrginalTextFont} context:nil].size
- 对于属性的转换和处理等, 思考一下 get方法 和 set方法 的合理运用.
2016-08-XX
出差这段时间了解了项目如何开发,了解了 Masonry 的使用. 虽然是在原有的项目上继续开发新需求, 但是还是感觉提升好大...
- 我自己斗胆引入 MJExtension , 开发效率提升很大
- 了解了 Masonry 的使用
- 了解了一个项目的各 VC (Tabbar, Navi ...)之间的层次关系
- 最重要的一点是多个模块使用了 TableView, 更深入一点点的了解了 TableView 和自定义 Cell 的使用
- 在一些特定的需求中, 我还想到使用了 delegate 来解决, 熟悉了 protocol 的使用
- 最后还用了一段时间做了优化, 有些 VC 在 pop 之后并没有调用 dealloc 方法, 了解了 block 中的循环引用以及解决方法
可以使用宏:
#define XYWeakSelf(type) __weak typeof(type) weak##type = type;
#define XYStrongSelf(type) __strong typeof(type) type = weak##type;
NavigationController 的右滑 POP 功能
self.navigationController.interactivePopGestureRecognizer.delegate = (id) self;
2016-09 学习日记
2016-09-05
new 和 alloc init 的区别
[className new]基本等同于[[className alloc] init], 区别只在于alloc分配内存的时候使用了zone.它是给对象分配内存的时候,把关联的对象分配到一个相邻的内存区域内,以便于调用时消耗很少的代价,提升了程序处理速度.
利用dispatch_once创建单例
void dispatch_once( dispatch_once_t *predicate, dispatch_block_t block);其中第一个参数predicate,该参数是检查后面第二个参数所代表的代码块是否被调用的谓词,第二个参数则是在整个应用程序中只会被调用一次的代码块。dispach_once函数中的代码块只会被执行一次,而且还是线程安全的。
+ (XYViewController *)sharedInstance {
static XYViewController *vc;
static dispatch_once_t one;
dispatch_once(&one, ^{
vc = [[self alloc] init];
});
return vc;
}
2016-09-06
继续看微薄的Demo, 保留一位小数 %.1f
发现 NSString 转换 NSDate 的时候返回 nil , 不知道为什么之前好使, 现在不好使了, 增加了一下 locole 属性的设置就好了
// Tue Sep 06 15:03:00 +0800 2016
NSDateFormatter *dfm = [[NSDateFormatter alloc] init];
dfm.dateFormat = @"EEE MMM dd HH:mm:ss Z yyyy";
// 增加这一行
dfm.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
NSDate *createDate = [dfm dateFromString:_created_at];
CGRect 的 坐标系转换
[view convertRect:(CGRect) toView:(nullable UIView *)];
[view convertRect:(CGRect) fromView:(nullable UIView *)];
2016-09-22
AVFoundation 实现扫描二维码
[简书文章](http://www.jianshu.com/p/6b7d54b3f88b)
如果用户不允许访问相机. 应用会闪退, 加入判断
NSString *mediaType = AVMediaTypeVideo;//读取媒体类型
AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:mediaType];//读取设备授权状态
if(authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied){
//不允许
}
2016-09-27
提供单例时, 建议私有init方法, 利用如下声明(.h), 提供一个编译错误:
- (instancetype)init __attribute__((unavailable("Disabled. Use +sharedInstance instead")));
注意: 此时在sharedInstance方法中,需要写[[self alloc] init]
2016-09-28
打印一堆莫名其妙看不懂的Log
Edit Scheme-> Run -> Arguments, 在Environment Variables里边添加
OS_ACTIVITY_MODE = Disable
2016-10 学习日记
2016-10-13
突发奇想用LaunchScreen做载入图
添加UIImageView.通过添加约束设置拉伸全屏显示, 似乎不用提供各种尺寸的LaunchImage.
添加 Storyboard ID. "LaunchScreen"
UIViewController *viewController = [[UIStoryboard storyboardWithName:@"LaunchScreen" bundle:nil] instantiateViewControllerWithIdentifier:@"LaunchScreen"];
UIView *launchView = viewController.view;
[UIView animateWithDuration:1.8f delay:0.1f options:UIViewAnimationOptionBeginFromCurrentState animations:^{
launchView.alpha = 0.0f;
launchView.layer.transform = CATransform3DScale(CATransform3DIdentity, 1.3f, 1.3f, 1.0f);
} completion:^(BOOL finished) {
[launchView removeFromSuperview];
}];
来为启动增加动画, 这里我设置了延迟 0.1s , 因为还添加了一个label的移动动画, 如果不延迟的话会明显感觉有个小卡顿.
2016-10-24
获取各种目录
// 获取沙盒主目录路径
NSString *homeDir = NSHomeDirectory();
// 获取Documents目录路径
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDir = [paths objectAtIndex:0];
// 获取Caches目录路径
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *cachesDir = [paths objectAtIndex:0];
// 获取tmp目录路径
NSString *tmpDir = NSTemporaryDirectory();
2016-10-26
不知道为什么 Xcode Build 报错
/Users/hanyuanxu/Library/Developer/Xcode/DerivedData/DiaryForXY-atkiwvdprytfniattjbdfgjreltv/Build/Products/Debug-iphonesimulator/DiaryForXY.app: resource fork, Finder information, or similar detritus not allowed
Command /usr/bin/codesign failed with exit code 1
网上说, 各种证书问题, 删除创建等等都无果
最后清空DerivedData目录, 工程目录下执行
xattr -rc .
解决, 并不懂...
2016-10-27
UITableView 的 Style UITableViewStylePlain 和 UITableViewStyleGrouped.
UITableViewStyleGrouped 默认会在 TableView 的 HeaderView 下面增加一条线的间隙, 会在 TableView 的 FooterView 上面增加微宽的间隙.
- Reveal 使用方法 点这里
2016-11 学习日记
2016-11-14
全透明导航栏
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
[self.navigationController.navigationBar setShadowImage:[UIImage new]];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.navigationController.navigationBar setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];
[self.navigationController.navigationBar setShadowImage:nil];
}
还原的这部分放在 viewWillDisappear 好使,但是放在 viewDidDisappear 就不好使
我猜测是因为放在 viewDidDisappear 的时候当页面没了才会执行.这时候上一个页面已经渲染完了.所以就改不了了.
修改导航栏文字颜色
[self.navigationController.navigationBar setTitleTextAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:18],NSForegroundColorAttributeName:[UIColor blueColor]];
缩放动画
view.transform = CGAffineTransformMakeScale(0.01f, 0.01f);//将要显示的view按照正常比例显示出来
[UIView beginAnimations:nil context:UIGraphicsGetCurrentContext()];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:0.8f];//动画时间
view.transform=CGAffineTransformMakeScale(1.0f, 1.0f);//先让要显示的view最小直至消失
[UIView commitAnimations]; //启动动画
2016-12 学习日记
2016-12-02
原生提供的MD5加密方法
#import <CommonCrypto/CommonDigest.h>
+ (NSString *) md5:(NSString *)str {
const char *cStr = [str UTF8String];
unsigned char result[CC_MD5_DIGEST_LENGTH];
CC_MD5(cStr, (CC_LONG)strlen(cStr), result);
NSMutableString *ret = [NSMutableString stringWithCapacity:32];
for(int i = 0; i<CC_MD5_DIGEST_LENGTH; i++) {
[ret appendFormat:@"%02X", result[i]];
}
return ret;
}
2016-12-05
GCD 实现线程组,子线程全部结束后做出响应.
// 创建线程租
dispatch_group_t group = dispatch_group_create();
// 子线程1
dispatch_group_async(group, dispatch_get_global_queue(0,0), ^{ ... });
// 子线程2
dispatch_group_async(group, dispatch_get_global_queue(0,0), ^{ ... });
dispatch_group_notify(group, dispatch_get_global_queue(0,0), ^{
// 子线程全部执行完成后执行
...
});
如果线程里面有 block , 想在block结束后执行怎么办?
可以手动控制线程结束 :
// 创建线程租
dispatch_group_t networking = dispatch_group_create();
// 子线程1
dispatch_group_enter(networking);
[A loadData:^(M *model) {
...
dispatch_group_leave(networking);
}];
// 子线程2
dispatch_group_enter(networking);
[B loadData:^(M *model) {
...
dispatch_group_leave(networking);
}];
dispatch_group_notify(networking,dispatch_get_main_queue(),^{
// 子线程全部执行完成后执行
...
});
2016-12-06
防止CollectionView更新的时候闪屏
CollectionView 更新的时候没找到带 Animation 参数的 暂时找到如下解决办法
[UIView performWithoutAnimation:^{
[self.collectionView reloadSections:[NSIndexSet indexSetWithIndex:0]];
}];
2016-12-17
CocoaPods 相关问题
git clone
之后pod install
之后打开xcode报错
大致内容就是没有执行 pod install.可是我明明执行了..
百度之后说删除 Pods 目录 和 现有的 xcworkspace 重新 pod install
即可
结果重新pod install
的时候
Generating Pods project
[1] 63036 abort pod install
报了个错误一直没办法生成 xcworkspace 文件, 百度也无果.准备重新升级cocoapods
sudo gem install cocoa pods
结果又报了个错误
Operation not permitted - /usr/bin/xcodeproj
百度后执行命令
sudo gem install -n /usr/local/bin cocoapods
升级成功,通过
pod COMMAND --version
看到版本号是1.1.1, 执行 pod setup
成功后重新 pod install
结果依然报错..
Generating Pods project
[1] 63036 abort pod install
尝试升级beta版本
sudo gem install -n /usr/local/bin cocoapods --pre
看到版本号是1.2.0beta1, 执行 pod setup
成功后重新 pod install
Generating Pods project
Integrating client project
Sending stats
Pod installation complete!
终于成功!猜测是创建工程的人使用了更高版本的CocoaPods.导致我没办法兼容.