UITableView

修改分隔线宽度

对cell和tableView分别设置

if([[[UIDevice currentDevice] systemVersion] floatValue]>=8.0)
{
    self.preservesSuperviewLayoutMargins=NO;
}

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if ([cell respondsToSelector:@selector(setSeparatorInset:)]) 
    {
        [cell setSeparatorInset:UIEdgeInsetsZero];
    }
    
    if ([cell respondsToSelector:@selector(setLayoutMargins:)]) 
    {
        [cell setLayoutMargins:UIEdgeInsetsZero];
    }
}

IDP

几个概念

(1)csr,p12文件:生成钥匙串请求的CRS文件要留着,这里面有一对密钥,导出.p12文件就是这对密钥中的私钥的导出文件;
(2)Provisioning Profile:它包含的信息有 appid,证书,及设备。
(3)证书的生成和下载顺序:生成钥匙串请求,下载开发证书和发布证书,配置App ID同时把development SSL和production SSL都配置好,下载SSL证书,最后下载Provisioning证书。
(4)development和production得到的Token的不同的,可以使用AdHoc方式安装测试发布证书,使用AdHoc方式装到设备上得到的就是production Token,所以在用Ad Hoc方式测试的要使用production Token。如果使用Ad Hoc方式测试没问题,一般发布也就没问题了。
(5)Token会更新,不是固定不变的,这个在官方文档中有提到,即在一定的时间或者刷机某些不经常出现的情况下,苹果服务器可能会更新设备的Token
可以让客户端采用一个适当的频率把当前token提交到业务服务器。

AdHoc

开发者除了可以通过Xcode直接连接设备安装开发版ipa,还可以在发布到appstore前,通过ad-hoc模式,将生产的 ad-hoc profile 和 ipa 安装到设备。
可以装这两个文件都拖到itunes的应用程序界面上;
也可以把profile文件通过邮件发送到手机上,在手机上直接点击附件,即可安装这个profile。然后通过itunes同步ipa即可。

对应用程序截图

(1:在模拟器界面 Control+Command+C,截图将存在剪贴板
(2:打开预览(Preview,即预览专用),按Command+N会自动新建图像并从剪贴板粘贴
(3:Command+S保存文件

 

若审核结果是元数据问题,则只需要修改元数据后,在问题中心中回复,不需要点提交此版本,然后等待审核即可。

在AppIDs中编辑中,可以下载到apns证书。

加急审核申请地址,未使用过
https://developer.apple.com/appstore/contact/?topic=expedite

App Store Review Guidelines
https://developer.apple.com/appstore/resources/approval/guidelines.html

StatusBar,状态栏 ,UIWindow

1. 自定义状态栏点击
系统弹出来的对话框的Window Level最高,是UIWindowLevelAlert。
创建一个UIWindow对象,将它的windowLevel设大于等于UIWindowLevelStatusBar,然后将覆盖在状态栏上。
缺点是触摸事件不能传递给原生状态栏了,所以滚动到顶部的效果就得自己处理了,而越狱后关于状态栏的自定义手势也失效了。

具体做法:
(1).自定义StatusBarView继承自UIWindow;
(2).CGRect statusBarRect = {0,0,320,20};
statusBarView = [[StatusBarView alloc] initWithFrame:statusBarRect];//只要在需要它的控制器中做出它的实例,不需要添加到其它视图中。
(3).statusBarView.windowLevel =UIWindowLevelStatusBar+1;
(4).statusBarView.hidden=NO;//显示它。它默认是隐藏的。若隐藏状态栏,要同时把statusBarView隐藏。否则仍会在屏幕顶部响应触摸。
(5).在statusBarViewr的touchesBegan中处理事件。
(6).可以设置它为全透明,或者添加小图标来模拟放置小图标到状态栏上。

2.viewController.wantsFullScreenLayout=YES;//设置为全屏布局,默认为NO
在iPhone上测试viewController.view.frame,和wantsFullScreenLayout的值无关,NSLog(@”%@”,NSStringFromCGRect(self.view.frame)); 结果都是{{0, 0}, {320, 460}}。
当viewController.wantsFullScreenLayout=YES;时,view左顶点和状态栏相同,即view和statuBar都开始于window左顶点上;
当viewController.wantsFullScreenLayout=NO;即默认时,view左顶点在状态栏左下,即在window中statusBar,view沿y向下依次摆放;
可以调用[[UIApplication sharedApplication] setStatusBarHidden:YES];来隐藏状态栏。
viewController.wantsFullScreenLayout设置为YES时,如果statusbar,navigationbar, toolbar是半透明的,viewController的view就会缩放延伸到它们下面。
但tabBar不在这个规则内,无论该属性是否为YES,view都不会覆盖到tabbar的下方。

3. 全屏切换,注意下面的隐藏顺序,先状态栏,再导航栏。
[[UIApplication sharedApplication] setStatusBarHidden: ![UIApplication sharedApplication].statusBarHidden withAnimation:YES];
[self.navigationController setNavigationBarHidden:!self.navigationController.navigationBarHidden animated:YES];

//用淡入淡出效果切换隐藏与显示
[[UIApplication sharedApplication] setStatusBarHidden:![UIApplication sharedApplication].statusBarHidden withAnimation:UIStatusBarAnimationFade];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.2];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
if(self.navigationController.navigationBar.alpha==0.0)
self.navigationController.navigationBar.alpha=1.0;
else
self.navigationController.navigationBar.alpha=0.0;
[UIView commitAnimations];

4.自定义状态栏参考
如何使 statusBar 点击获取事件
http://www.cocoachina.com/bbs/read.php?tid-54777.html
自定义iPhone的状态栏
http://www.keakon.net/2011/08/11/%E8%87%AA%E5%AE%9A%E4%B9%89iPhone%E7%9A%84%E7%8A%B6%E6%80%81%E6%A0%8F
一个开源的自定义状态栏
http://blog.csdn.net/favormm/article/details/7421837
https://github.com/myell0w/MTStatusBarOverlay

5.rootViewController vs addSubview
The UIWindow rootViewController property is new with iOS4.
The older technique was to use addSubview.
The new, recommended technique is to set rootViewController.

6.在.plist中,Status bar style的值有Gray style (default),Transparent black style (alpha of 0.5),Opaque black style
设置为Opaque black style可使状态栏为黑色背景,不受导航条影响。

7.keyWindow
keyWindow指活跃的window,
iphone键盘也在一个window里,叫UITextEffectsWindow;
Alert也是一个window
window可以层叠的,各个window都可以被响应。
UIWindow* keyWindow=[UIApplication sharedApplication].keyWindow;
if([keyWindow isKindOfClass:NSClassFromString(@”_UIAlertOverlayWindow”)]){}

8.UIWidnows对UIMenuController的影响
UIMenuController的KeyWindow可能会被程序中使用的额外UIWindow代替,所以要重新设置keywindow
http://blog.csdn.net/james_1010/article/details/9063807

ios7

动态计算UITableViewCell高度

http://www.shinobicontrols.com/blog/posts/2013/10/16/ios7-day-by-day-day-19-uitableview-row-height-estimation
http://www.ifun.cc/blog/2014/02/21/dong-tai-ji-suan-uitableviewcellgao-du-xiang-jie/
其中一些新的方法
[cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
– (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath

iOS7的几个特点:
1.坐标:以屏幕左上角为原点(iOS7以前在状态栏或者导航条下)

2.UIScrollView及其子类: 会自动在顶部和底部预留一些空白,因为滚动经过半透明导航条或者tabbar下面,需要能隐约看到的效果。是否预留空白可以由UIViewController的automaticallyAdjustsScrollViewInsets的这个属性控制,automaticallyAdjustsScrollViewInsets的意思是自动调整滚动视图的内边距。它默认YES,表示预留空白。
一个控制器中的UIScrollView(包括其子类),必须是第一个添加到控制器的视图,才会被控制是否预留空白。

Specifies whether or not the view controller should automatically adjust its scroll view insets.
Default value is YES, which allows the view controller to adjust its scroll view insets in response to the screen areas consumed by the status bar, navigation bar, and toolbar or tab bar. Set to NO if you want to manage scroll view inset adjustments yourself, such as when there is more than one scroll view in the view hierarchy.

http://blog.csdn.net/shenjx1225/article/details/12100079

3.其它布局
http://www.vinqon.com/codeblog/?detail/11109

4.引入了JS框架<JavaScriptCore/JavaScriptCore.h>,给了“纯IOS程序员”一个枯木逢春的契机~学习强大的 JavaScript。
http://blog.csdn.net/lizhongfu2013/article/details/9232129

5.导航拖动返回
改进参考
http://www.cnblogs.com/lexingyu/p/3432444.html
http://blog.csdn.net/zhaoxy_thu/article/details/15811189
//控制导航返回图片与文字颜色
self.navigationController.navigationBar.tintColor=[UIColor whiteColor];

iOS7人机界面指南-UI元素(上)
http://isux.tencent.com/ios-human-interface-guidelines-ui-design-ios7-ui-1.html

6.iOS 7:隐藏的特性和解决之道

http://www.cocoachina.com/industry/20131122/7400.html

http://www.objc.io/issue-5/iOS7-hidden-gems-and-workarounds.html

http://nshipster.com/ios7/

http://www.cocoachina.com/industry/20140117/7715.html

http://www.tuicool.com/articles/riMzAr

自动布局 AutoLayout

Auto Layout

iOS 6 引入了自动布局(Auto Layout)概念。自动布局使用约束(Constraint)在用户界面描述各类视图的位置、行为和关系。
在Xcode 4.5及以上中,有3种方式创建约束(Constraint):

  1. 使用Interface Builder
  2. 可视化格式语言(Visual Format Language),
  3. 标准的SDK API调用(NSLayoutConstraint类)。

Auto Layout用这些Constraints对所有的视图进行计算,设置视图的位置和尺寸。不再需要设置视图的frame属性,完全基于针对视图或元素所设置的Constraints来布局界面的视图元素。

UINavigationBar自动布局异常

可能UINavigationBar不支持自动布局内部元素, 调用它的addConstraints会crash。
[UIView(UIConstraintBasedLayout) _withAutomaticEngineOptimizationDisabled:]
http://www.blogosfera.co.uk/2013/10/how-to-constrain-a-view-to-the-bottom-left-of-a-uinavigationbar/

 

iOS 6 Programming Cookbook_第3章_自动布局和Visual Format Language

http://commandshift.co.uk/blog/2013/01/31/visual-format-language-for-autolayout/

//the documentation to the visual format language
https://developer.apple.com/library/mac/documentation/UserExperience/Conceptual/AutolayoutPG/Articles/formatLanguage.html

http://zhuhaibobb.blog.163.com/blog/static/27440067201432402643739/
http://blog.163.com/moon_walker/blog/static/213179094201301794135423/
http://www.uuindex.com/?p=1741

http://www.cocoachina.com/industry/20131108/7322.html

升级xcode9 ios11遇到的问题及解决办法
https://www.jianshu.com/p/ca9069e3ccf9

UITextField, UITextView

设置UITextField左边距

textField.leftView=[[[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 0)] autorelease];
textField.leftViewMode=UITextFieldViewModeAlways;

UITextView圆角

textView.layer.cornerRadius = 6;
textView.layer.masksToBounds = YES;

 

修改UITextField的placeholder文字颜色

[textField setValue:[UIColor grayColor] forKeyPath:@"_placeholderLabel.textColor"];

ARC

ARC

Automatic Reference Counting 自动引用计数, 是新的LLVM 3.0编译器的一项特性,在iOS 5 Xcode4.2中推出。编译器(LLVM 3.0)在编译代码时,自动生成实例的引用计数管理部分代码。注意ARC并不是GC,它只是一种代码静态分析(Static Analyzer)工具。ARC是Objective-C编译器的特性,不是运行时特性或者垃圾回收机制,而因为可以在最合适的地方完成引用计数的维护,以及部分优化,使用ARC甚至能比MRC取得更高的运行效率。

MRC中的关键字在ARC中还可以使用

LLVM官网中的描述

assign implies __unsafe_unretained ownership.
copy implies __strong ownership, as well as the usual behavior of copy semantics on the setter.
retain implies __strong ownership.
strong implies __strong ownership.
unsafe_unretained implies __unsafe_unretained ownership.
weak implies __weak ownership.

即 assign 等同 unsafe_unretained
retain 等同 strong
copy的效用和MRC一样,同时又有strong的效果。

@property 的默认引用类型是assign

No ‘assign’, ‘retain’, or ‘copy’ attribute is specified – ‘assign’ is assumed
需要引用计数的属性要显示设置为storng,@property ( nonatomic, strong) NSString *note;

UIWebView

stringByEvaluatingJavaScriptFromString

android平台中调用WebView控件的addJavascriptInterface()方法可以轻松完成很多交互,在IOS中会困难复杂一些。

主程序主动通知UIWebView

[webView stringByEvaluatingJavaScriptFromString:@"some js code"];

UIWebView主动通知主程序

UIWebView通过js设置document.location = url; 会触发shouldStartLoadWithRequest接口被调用,并且返回NO。url字符串格式可自定义,把命令及参数封装到其中。

通过js设置一些webkit属性

 - (void)webViewDidFinishLoad:(UIWebView*)webView
 {
 //Disable user selection 禁用长按UIWebView时放大镜及选择功能:
 [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitUserSelect='none';"];
 //Disable callout,禁止长按链接弹出菜单,默认带有打开,拷贝,取消3个菜单项。
 [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitTouchCallout='none';"];
 //修改整个页面的字体大小
 [webView stringByEvaluatingJavaScriptFromString:@"document.getElementsByTagName('body')[0].style.webkitTextSizeAdjust= '150%';"];
 //修改点击链接时的高亮背景色
 [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitTapHighlightColor='#FF0000';"];
 }

嵌入在页面中 修改点击链接时的高亮背景色

<a style=”-webkit-tap-highlight-color: rgba(0,0,0,0);” href=”http://yourlink.com/”>

更多参考webkit webApp 开发技术要点总结
http://www.cnblogs.com/pifoo/archive/2011/05/28/webkit-webapp.html

使用UIWebView显示svg、gif

SVG:Scalable Vector Graphics,可缩放矢量图形,是用XML描述二维矢量图形的一种图形格式。
若使用img标签,<img src=” >标签中src要带有.svg扩展名才可正常显示。

CGRect rect = CGRectMake(0,0,1000,1000);
webView = [[UIWebView alloc] initWithFrame:rect];
[webView loadData:svgData MIMEType:@"image/svg+xml" textEncodingName:@"UTF-8" baseURL:nil];

[webView loadData:gifData MIMEType:@"image/gif" textEncodingName:nil baseURL:nil];

使用UIWebView显示本地html文件

显示安装包中的html文件

NSString* pathInBundle=[[NSBundle mainBundle] pathForResource:@"index" ofType:@"html" inDirectory:@"app-guide" forLocalization:nil];
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:pathInBundle]]];
或者
[webView_ loadHTMLString:htmlContent baseURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]]];

这里的重点是使用loadRequest,且使用fileURLWithPath而不是URLWithString。

如果要显示一段html内容,且其中有防盗链网络图片,则需要修改baseURL为Referer地址,例如:

[webView loadHTMLString:htmlContent baseURL:[NSURL URLWithString:@"http://a.cn"]];

动态设置img地址

NSString* path=[FileUtil getDocumentsFullPath:@"logo.png"];
NSString* path=[[NSBundle mainBundle] pathForResource:@"logo" ofType:@"png"];
     
path=[NSString stringWithFormat:@"file://%@",path];
//file后面是冒号加3个斜杠
NSString* script=[NSString stringWithFormat:@"setImgSrc(\"%@\");",path];
    
[webView stringByEvaluatingJavaScriptFromString:script];

NSHTTPCookieStorage

- (void)addCookies:(NSString *)domain withCookies:(NSArray *)cookieArray
{
    NSHTTPCookie *cookie = nil;
    NSDictionary *properties =  nil;
    NSString* cookieStr = nil;
    for (int i=0; i<[cookieArray count]; i++)
    {
        cookieStr = [cookieArray objectAtIndex:i];
        NSRange range = [cookieStr rangeOfString:@"="];
        if(range.location != NSNotFound)
        {
            properties = [NSDictionary dictionaryWithObjectsAndKeys:
                          [cookieStr substringToIndex:range.location], NSHTTPCookieName,
                          [cookieStr substringFromIndex:range.location+range.length], NSHTTPCookieValue,
                          @"/", NSHTTPCookiePath,
                          domain, NSHTTPCookieDomain,
                          nil];
        }
        cookie = [NSHTTPCookie cookieWithProperties:properties];
        [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
    }
}

- (void)clearCookies
{
    NSHTTPCookie *cookie = nil;
    NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
    for (cookie in [storage cookies])
    {
        [storage deleteCookie:cookie];
    }
}