本系列将整理以前项目开发中会遇到的部分问题,内容比较多,预计会有十多篇,从印象笔记拷贝过来的。排版比较乱,敬请谅解。欢迎评论区留言。
深拷贝,浅拷贝
KVO
-
0和1不等宽的解决方法: 1. 等宽字体 2. 评论中有好的解决方法 www.cocoachina.com/bbs/read.ph…
-
json 在线解析网站www.json.cn ,postman chyy
-
设备达到100台的处理方法
登录管理员账号 Account -> memberShip->Team ID
developer.apple.com/contact/sub…
/** * 重写这个方法目的:能够拦截所有push进来的控制器 @param viewController 即将push进来的控制器
*/
-(void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
if (self.viewControllers.count > 0) { // 这时push进来的控制器viewController,不是第一个子控制器(不是根控制器)
/* 自动显示和隐藏tabbar */
viewController.hidesBottomBarWhenPushed = YES;
/* 设置导航栏上面的内容 */
// 设置左边的返回按钮
viewController.navigationItem.leftBarButtonItem = [UIBarButtonItem itemWithTarget:self action:@selector(back) image:@"navigationbar_back" highImage:@"navigationbar_back_highlighted"];
// 设置右边的更多按钮
viewController.navigationItem.rightBarButtonItem = [UIBarButtonItem itemWithTarget:self action:@selector(more) image:@"navigationbar_more" highImage:@"navigationbar_more_highlighted"];
}
[super pushViewController:viewController animated:animated];
}
复制代码
-
expr可以修改断点的值expr value = nil,参考[ [000]LLDB中的调试命令]
-
git 添加忽略文件:www.gitignore.io 空目录提交 find . -type d -empty -exec touch {}/.tht
blog.csdn.net/jeffasd/art… 删除 UserInterfaceState.xcuserstate
文件的终极方法
- ICYP0 MBProgressHUD报错 [MBProgressHUD detailsLabel]: unrecognized selector sent to instance
清理xcode缓存gitee.com/oschina/iph…
-
iOS导航栏自定义按钮导致点击范围过大的问题 blog.csdn.net/github_2667…
-
app 统计查看网站 www.appannie.com/account/log…
-
pod升级
- 审核被拒绝或者等待审核时remove 都只需要改build即可,version是给苹果看的,build是开发看的
一个version 可以有无数个build 你可以选择一个build最终审核
-
testFight appstore beta测试 www.jianshu.com/p/684e4b56b…
-
时间戳 天数比较 需要用 30 * 24 * 60 * 60 注意乘以0.0001
-
app icon制作icon.wuruihong.com/
118 . 页面跳转push多次,背景颜色要设置 内存泄露
- 服务端返回NSNumber
NSString* json = @"{\"number\":66.51}";
NSData* data = [json dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary* dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
id object = dic[@"number"];
NSLog(@"%@",[object class]);
NSLog(@"%@",object);
复制代码
输出 NSNumber 66.519999999999
-
json串包含””的问题 www.jianshu.com/p/c7ecc1100…
-
七牛云图片处理,需要注意 宽高要乘以scale [UIScreen mainScreen].scale,用?imageView/3/w/100/h/100
-
hidesBottomBarWhenPushed = yes的正确使用姿势 www.isaced.com/post-223.ht…
-
www.mamicode.com/info-detail… ios10.3 uilabel下划线shi’xiao
-
使用分类(即AOP) 给当前vc增加逻辑处理self,缺点会增加编译时间
110.wkwebview 重新加载js 当前页面 removefromsupview uiview = uiview
-
坐标系转换 最后可以使用keywindow
-
iOS11上 保存到相册,[assetsLibrary assetForURL:assetURL resultBlock]很大几率从相册获取视频失败.
解决方法:用PHAsset替代AVAsset。也可以通过遍历等其他方式解决,在笔记里面
- NSMutableArray *toolbarButtons = [self.navigationItem.rightBarButtonItems mutableCopy];
toolbarButtons removeobject:
viewdidload 是在frameb
-
有时候,工程导航栏不显示任何东西,只显示“no filter results”,即使关闭重启Xcode也无用。解决方法:在导航栏下方的搜索框中任意输入字符,导航栏中将会出现你的工程文件目录。
-
NSDate 夏令时冬令时的问题
1986-05-04 转换成NSDate 是空的, 1986-05-03 1986-05-05 都没问题
format.timeZone = [NSTimeZone timeZoneWithName:@”UTC”]; 添加这个即可(来自给力手哥的解决方案)
- github上下载指定的文件夹
著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。
作者:pezy
链接:www.zhihu.com/question/25…
来源:知乎
譬如这个项目: Mooophy/Cpp-Primer · GitHub, 我只想看 ch03 文件夹的代码怎么办?
先打开 ch03, 其 URL 为: “https: //github. com/Mooophy/Cpp-Primer/tree/master/ch03″(这里添加空格, 为了防止知乎智能识别)
将 /tree/master/ 换成 /trunk/ . (这个以前玩 Google Code 的人应该很熟悉.)
“https: //github. com/Mooophy/Cpp-Primer/trunk/ch03″(同样有空格)
然后, 输入:
svn checkout github.com/Mooophy/Cpp…
PS: 第一次使用的话, 可能会出现下面这个提示:
R)eject, accept (t)emporarily or accept (p)ermanently?
输入 P 就行了.
102.下载SVN指定版本
101.删除SVN文件夹方法
删除”.SVN”文件夹方法
删除这些目录是很简单的,命令如下
find . -type d -name “.svn”|xargs rm -rf;
或者
find . -type d -iname “.svn” -exec rm -rf {} ;
100.Assertion failure in -[UITableView _endCellAnimationsWithContext:]—错误
删除时,要注意section和row数量的一致.要不然就容易导致上面的错误.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)theTableView{
//注意删除时保持section数量的一致,要不然,容易导致上面的错误.
if(self.totalArray.count>0)
return 1;
else
return 0;
}
}
复制代码
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
//用来设置相应的行,可不可以编辑
YLMessageModel* item=[self.totalArray objectAtIndex:indexPath.row];
if(item.msg_id<0)
{
return NO;
}else{
return YES;
}
}
复制代码
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
NSInteger r = indexPath.row;
NSInteger c = indexPath.section;
YLMessageModel* item=[self.totalArray objectAtIndex:r];
//注意先remove数据
[self.totalArray removeObjectAtIndex:r];
[msgView beginUpdates];
[msgView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
//注意这里,如果对应的section没有行的时候,要删除section,要不然,也会导致上面的错误.
if(self.totalArray.count==0){
[msgView deleteSections:[NSIndexSet indexSetWithIndex:c] withRowAnimation:UITableViewRowAnimationFade];
}
[msgView endUpdates];
}
else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
}
}
复制代码
99.注意区分一下事件传递和响应者链接的区别:
先通过事件传递找到最适合处理事件的控件,然后通过响应者链接进行事件冒泡处理.
一次完整的触摸事件的传递响应的过程
(下面这行是事件查找的过程)
UIAppliction –> UIWindow –>递归找到最适合处理事件的控件–>控件调用touches方法–>判断是否实现touches方法
–>没有实现默认会将事件传递给上一个响应者–>找到上一个响应者
(上面这行是响应者链接)
- 响应者链条:由很多响应者链接在一起组合起来的一个链条称之为响应者链条
- 响应者:继承UIResponder的对象称之为响应者对象
iOS开发UI篇—事件传递 – 文顶顶 – 博客园
98.hitTest:withEvent:方法的处理流程
iOS系统检测到手指触摸(Touch)操作时会将其放入当前活动Application的事件队列,UIApplication会从事件队列中取出触摸事件
并传递给key window(当前接收用户事件的窗口)处理,window对象首先会使用hitTest:withEvent:方法寻找此次Touch操作初始点
所在的视图(View),即需要将触摸事件传递给其处理的视图,称之为hit-test view。
window对象会在首先在view hierarchy的顶级view上调用hitTest:withEvent:,此方法会在视图层级结构中的每个视图上
调用pointInside:withEvent:,如果pointInside:withEvent:返回YES,则继续逐级调用,直到找到touch操作发生的位置,
这个视图也就是hit-test view。
hitTest:withEvent:方法的处理流程如下: 注意这是一个递归的过程:
1.首先调用当前视图的pointInside:withEvent:方法判断触摸点是否在当前视图内;
若返回NO,则hitTest:withEvent:返回nil;
若返回YES,则向当前视图的所有子视图(subviews)发送hitTest:withEvent:消息,所有子视图的遍历顺序是从top到bottom,即
从subviews数组的末尾向前遍历,直到有子视图返回非空对象或者全部子视图遍历完毕;
若第一次有子视图返回非空对象,则hitTest:withEvent:方法返回此对象,处理结束;
如所有子视图都返回非,则hitTest:withEvent:方法返回自身(self)。
hitTest:withEvent:方法忽略隐藏(hidden=YES)的视图,禁止用户操作(userInteractionEnabled=YES)的视图,以及alpha级别
小于0.01(alpha<0.01)的视图。如果一个子视图的区域超过父视图的bound区域(父视图的clipsToBounds 属性为NO,这样超过
父视图bound区域的子视图内容也会显示),那么正常情况下对子视图在父视图之外区域的触摸操作不会被识别,因为
父视图的pointInside:withEvent:方法会返回NO,这样就不会继续向下遍历子视图了。当然,也可以重写pointInside:withEvent:方法来处理这种情况。
IOS 难理解的几个屏幕接触问题 – 小浪鼓 – 博客园
97.可以在app第一次安装的时候,获取UUID,做为机器标识.
-(void) initMachineIdentifier {
NSString* uuid=[[NSUserDefaults standardUserDefaults] objectForKey:@"__machine_UUID"];
if(uuid==nil){
//注意下面的UUID,每次运行获取的都不一样.
CFUUIDRef puuid = CFUUIDCreate( nil );
CFStringRef uuidString = CFUUIDCreateString( nil, puuid );
NSString * result = (NSString *)CFBridgingRelease(CFStringCreateCopy( NULL, uuidString));
CFRelease(puuid);
CFRelease(uuidString);
[[NSUserDefaults standardUserDefaults] setObject:result forKey:@"__machine_UUID"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
}
复制代码
96.连续pushviewcontroller
今天在连续push两个vc时出现了,错乱,代码是这样的:
[rootNav pushViewController:vc1 animated:NO];
[rootNav pushViewController:vc2 animated:NO];
复制代码
改成这样,正常的,在vc1的viewWillAppear中
[rootNav pushViewController:vc1 animated:YES]; //这个YES是必须的,不知为何
[[[rvc rac_signalForSelector:@selector(viewDidAppear:)] take:1] subscribeNext:^(id x){
[rootNav pushViewController:vc animated:NO];
}];
复制代码
95.字典的删除
NSMutableArray* toBeDeleteArr=[[NSMutableArray alloc] init];
NSMutableArray *allKeys = [[viewControllersDic allKeys] mutableCopy];
for(NSString* key in allKeys){
UIViewController* v=[viewControllersDic objectForKey:key];
if([v isEqual:vc]){
[toBeDeleteArr addObject:key];
}
}
[viewControllersDic removeObjectsForKeys:[toBeDeleteArr copy] ];
复制代码
94.不能为了图省事,而直接使用@3x的照片,这样会造成在一些机器上无法正常显示,今天遇到:
msgImg = [[UIImage imageNamed:@”tabBar_msg@3x”] retain];
由于直接使用了@3x的照片,在ipod touch 上的ios8.0无法显示照片. 那么正规的做法,是直接针对每一种屏幕,都使用对应的照片.
93.xcodebuild -showBuildSettings
查看工程的配置信息.
在*.xcodeproj所在目录运行上述命令,便可以输出项目整个工程的配置信息.
比如,我要查看$(SRCROOT)实际代表的目录是什么,可运行如下命令:
.xcodebuild -showBuildSettings | grep "SRC\|PROJECT"
输出:
2015-04-01 22:27:33.217 xcodebuild[824:21844] [MT] iPhoneSimulator: SimVerifier returned: Error Domain=NSPOSIXErrorDomain Code=53 "Simulator
verification failed." UserInfo=0x7fd45a915970 {NSLocalizedFailureReason=A connection to the simulator verification service could not be established.,
NSLocalizedRecoverySuggestion=Ensure that Xcode.app is installed on a volume with ownership enabled., NSLocalizedDescription=Simulator verification failed.}
2015-04-01 22:27:34.274 xcodebuild[824:21844] [MT] DeveloperPortal: Using pre-existing current store at URL (file:///Users/taivex2/Library/Developer/Xcode/DeveloperPortal%206.2.db).
EXCLUDED_INSTALLSRC_SUBDIRECTORY_PATTERNS = .DS_Store .svn .git .hg CVS
HEADERMAP_INCLUDES_PROJECT_HEADERS = YES
PROJECT = DZMedical
PROJECT_DERIVED_FILE_DIR = /Users/taivex2/Library/Developer/Xcode/DerivedData/DZMedical-dhbntwylstigecfaaukpdvwlfitn/Build/Intermediates/DZMedical.build/DerivedSources
PROJECT_DIR = /Users/taivex2/Desktop/医联云0331/YDYL_Pub
PROJECT_FILE_PATH = /Users/taivex2/Desktop/医联云0331/YDYL_Pub/DZMedical.xcodeproj
PROJECT_NAME = DZMedical
PROJECT_TEMP_DIR = /Users/taivex2/Library/Developer/Xcode/DerivedData/DZMedical-dhbntwylstigecfaaukpdvwlfitn/Build/Intermediates/DZMedical.build
PROJECT_TEMP_ROOT = /Users/taivex2/Library/Developer/Xcode/DerivedData/DZMedical-dhbntwylstigecfaaukpdvwlfitn/Build/Intermediates
SRCROOT = /Users/taivex2/Desktop/医联云0331/YDYL_Pub
VERSION_INFO_STRING = "@(#)PROGRAM:医联云健康 PROJECT:DZMedical-"
复制代码
92.didReceiveRemoteNotification须处理的三种情况:
推送状态
You app needs to handle all the possible push notification delivery states:
* Your app was just launched
* Your app was just brought from background to foreground
* Your app was already running in the foreground
You do not get to choose at delivery time what presentation method is used to present the push notification, that is encoded in the notification itself (optional alert, badge number, sound). But since you presumably are in control of both the app and the payload of the push notification, you can specify in the payload whether or not there was an alert view and message already presented to the user. Only in the case of the app is already running in the foreground do you know that the user did not just launch your app through an alert or regularly from the home screen.
You can tell whether your app was just brought to the foreground or not in didReceiveRemoteNotification using this bit of code:
复制代码
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
if ( application.applicationState == UIApplicationStateActive )
// app was already in the foreground
else
// app was just brought from background to foreground
...
}
复制代码
当应用程序由前台转入后台,当推送通知到达,用户点击通知进入应用程序,这时在didReceiveRemoteNotification里
UIApplication的状态为 UIApplicationStateInActive
stackoverflow.com/questions/5…
91.今天在给项目里的支付宝sdk升级的时,编译遇到如下错误:
Xcode 编译报错#include <openssl/asn1.h> file not found
解决方法是:
解决方法:Targets—->Search Paths ——>Header Search Paths 里添加,
“$(PROJECT_DIR)/MinHang/thridpart/AliSDK”
那么AliSDK的文件目录
90: 64 bit下数据类型的变化.
在32位的系统中:
int: 32位
long: 32位
NSInteger: 32位
指针: 32位
float: 32位
double: 32位
CGFloat: 32位
在64位系统中:
int: 32位
long: 64位
NSInteger: 64位
指针:64位
float: 32位
double: 64位
CGFloat: 64位
复制代码
不论是32位,还是64位的系统中, char(1字节) ,short(2字节),int(4字节),float(4字节),double(8字节),所占
的字节数不变.
89.树状视图栈,根为window:
present的过程
1)presenting view 寻找其根视图(window除外),
2)presenting view(根视图) 和presented view 一同被放到 UITransitionView进行动画切换。
3)动画完成时,presenting view(根视图)从视图体系中移除,presented view添加到window上。
复制代码
88.presentViewController的弹出风格.
SDetailImageViewController* v=[[SDetailImageViewController alloc] init];
UINavigationController* nav=[[UINavigationController alloc] initWithRootViewController:v];
v.baseData=[self.picArray objectAtIndex:tap.view.tag];
nav.modalTransitionStyle =UIModalTransitionStyleCrossDissolve;
[self presentViewController:nav animated:YES completion:nil];
复制代码
Modal Transition Style(弹出时的动画风格)
通过设置设置presenting VC的modalTransitionStyle属性
我们可以设置弹出presented VC时场景切换动画的风格,其定义如下:
typedef enum {
UIModalTransitionStyleCoverVertical = 0,//底部滑入
UIModalTransitionStyleFlipHorizontal, //水平翻转进入
UIModalTransitionStyleCrossDissolve, //交叉溶解
UIModalTransitionStylePartialCurl, //翻页
} UIModalTransitionStyle;
我们可以看到有从底部滑入,水平翻转进入,交叉溶解以及翻页这四种风格可选。
这四种风格在不受设备的限制,即不管是iPhone还是iPad都会根据我们指定的风格显示转场效果。
复制代码
87.下面的动画是无效的,因为affineTransform并没做为CAAnimation的keypath
CGAffineTransform transform = CGAffineTransformIdentity;
transform = CGAffineTransformScale(transform, 0.5, 0.5);
CABasicAnimation *scaleAnim = [CABasicAnimation animationWithKeyPath:@"affineTransform"];
scaleAnim.fromValue = [NSValue valueWithCGAffineTransform:CGAffineTransformIdentity];
scaleAnim.toValue = [NSValue valueWithCGAffineTransform:transform];
scaleAnim.removedOnCompletion = YES;
scaleAnim.duration=0.5f;
scaleAnim.fillMode=kCAFillModeForwards;
scaleAnim.autoreverses=NO;
[layer addAnimation:scaleAnim forKey:nil];
复制代码
Technically, affineTransform is not a property of CALayer, and is documented as a "convenience
method" wrapper around the transform property, which is documented as animatable.
It's only really by objective-c's implicit conversion of keypaths to selectors that it appears
affineTransform behaves like a property when use (under most circumstances) in a keypath.
However, the CA libraries are setup to observe only certain keypaths, and that's not one of them :-)
复制代码
ref: stackoverflow.com/questions/1…
86.navigationController.navigationItem vs navigationItem
不要混淆 self.navigationItem 和 self.navigationController.navigationItem ,
UINavigationItem 本身是用来 定制 ViewController 自己在被导航过程中的 appearence ,
navigationItem 是 UIViewController类 关于UINavigationControllerItem 类别的扩展,
也就是说当UIViewController放在UINavigationController中呈现的时候,
navigationItem属性有值,反之其值为nil
复制代码
@interface UIViewController (UINavigationControllerItem)
@property(nonatomic, readonly, retain)UINavigationItem * navigationItem;
...
@end
复制代码
The class UIViewController has a property navigationItem.
This is true of all the subclasses too whether it is a UICollectionViewController, UITableViewController,
UINavigationViewController or any custom subclass.
When presented by a UINavigationController the nav controller will create this property and so each view
controller gets its own navigationItem. If you do not present it from a navigation controller then the navigationItem is nil.
Now, with a UINavigationController you are more than likely using this as your initial view controller.
Therefore, the navigation controller is NOT being presented by another navigation controller and its navigationItem property is nil.
The navigation bar is slightly different as this is managed the other way around.
复制代码
ref: stackoverflow.com/questions/1…
85.CGAffineTransform中的“仿射”的意思是无论变换矩阵用什么值,图层中平行的两条线在变换之后任然保持平行,
- performSelector:withObject 只能传递一个参数 [其实可以传递多个参数]
SEL action2 = @selector(action2:);
[object performSelector:action2 withObject:data afterDelay:1.f]; 延迟执行一个方法
要传递多个参数可以用NSInvocation
void viewDidLoad{
//获取方法签名
NSMethodSignature* msigture=[[self class] instanceMethodSignatureForSelector:@selector(addTwoNum:with:)];
NSInvocation* invokation=[NSInvocation invocationWithMethodSignature:msigture];
//设置selector及target
[invokation setSelector:@selector(addTwoNum:with:)];
[invokation setTarget:self];
NSNumber* a=@1;
NSInteger b=2;
[invokation setArgument:&a atIndex:2];//这里得传指针的指针
[invokation setArgument:&b atIndex:3];
[invokation retainArguments];
[invokation invoke];
NSInteger returnValue;
[invokation getReturnValue:&returnValue];
NSLog(@"return value is:%ld",returnValue);
//延时调用
//[invokation performSelector:@selector(invoke) withObject:nil afterDelay:5];
}
-(NSInteger)addTwoNum:(NSNumber*) num1 with:(NSInteger)num2{
NSLog(@"%@",[NSThread currentThread]);
NSInteger ret=num1.integerValue+num2;
NSLog(@"%ld",ret);
return ret;
}
复制代码
用NSInvocation來作為object performSelector的替代方案 – Green
视图的 frame , bounds 和 center 属性仅仅是存取方法,当操纵视图的 frame ,实际上是在改变位于视图下方CALayer 的 frame ,不能够独立于图层之外改变视图的 frame 。
对于视图或者图层来说, frame 并不是一个非常清晰的属性,它其实是一个虚拟属性,是根据 bounds ,
position 和 transform 计算而来,所以当其中任何一个值发生改变,frame都会变化。相反,改变frame
的值同样会影响到他们当中的值
为什么iOS要基于UIView和CALayer提供两个平行的层级关系呢?为什么不用一个简单的层级来处理所有事情呢?
原因在于要做职责分离,这样也能避免很多重复代码。在iOS和Mac OS两个平台上,事件和用户交互有很多地
方的不同,基于多点触控的用户界面和基于鼠标键盘有着本质的区别,这就是为什么iOS有UIKit和UIView,但
是Mac OS有AppKit和NSView的原因。他们功能上很相似,但是在实现上有着显著的区别。
绘图,布局和动画,相比之下就是类似Mac笔记本和桌面系列一样应用于iPhone和iPad触屏的概念。把这种功
能的逻辑分开并应用到独立的Core Animation框架,苹果就能够在iOS和Mac OS之间共享代码,使得对苹果
自己的OS开发团队和第三方开发者去开发两个平台的应用更加便捷。
“Prior to iOS 7, the device token was the same across all app installations on a given device. Different apps on your phone, whether
Tap Tap Revenge or USA Today, would utilize the same address, i.e., device token, to route the push notification to you. The security
credentials that you pair with a message would ensure it made it to the right app. On iOS 7, Apple has gone one step further and made
sure that device tokens are now different in every single app install. This helps further protect users’ privacy by removing another phone-level identifier.”
ref: stackoverflow.com/questions/1…
80.1.新用户证书的布置
在证书管理中心里,右键开发证书,导出.
右键推送证书导出.
在xcode里找到相应的provision file 导出.
79.store weak reference object in array, dictionary.
one more thing: iOS6 and OSX 10.8 supposedly offer a better solution:
[NSHashTable weakObjectsHashTable]
[NSPointerArray weakObjectsPointerArray]
[NSPointerArray pointerArrayWithOptions:]
复制代码
These should give you containers that hold weak references (but note matt’s comments below).
1.NSValue
+ (NSValue *)valueWithNonretainedObject:(id)anObject
This method is useful if you want to add an object to a collection but don’t want the collection to create a strong reference to it.
2.There is a tricky way use block to do so:
typedef id (^WeakReference)(void);
WeakReference MakeWeakReference (id object) {
__weak id weakref = object;
return ^{ return weakref; };
}
id WeakReferenceNonretainedObjectValue (WeakReference ref) {
if (ref == nil)
return nil;
else
return ref ();
}
[arr addObject:MakeWeakReference(obj)];
id newobj = WeakReferenceNonretainedObjectValue([arr objectAtIndex:0]);
复制代码
3.Use a custom WeakReference class that hold on a weak pointer to the value.
-
我们使用集合(NSArray,NSMutableArray,NSDictionary,NSMutableDictionary,NSSet,NSMutableSet)存储对象时会对其强引用(你可以使用单例的集合存储数据试一下咯),有时候我们不想这样子,怎么办呢?
-
那就使用NSHashTable这个集合吧,它的使用方法与NSSet完全相似,不同的是,它的一种初始化方式是weakObjectsHashTable,专门用来存储弱引用对象,不会持有它,那个对象的所有人消失了,这个对象也会从这个集合中消失,多么人性化!
-
下面介绍它的一些方法:
- (BOOL)containsObject:(id)anObject
Returns a Boolean value that indicates whether the hash table contains a given object.
返回一个bool值,用来指示这个hash表中是否包括了你给与的对象.
- (void)addObject:(id)object
Adds a given object to the hash table.
将一个对象添加进hash表中.
- (void)removeObject:(id)object
Removes a given object from the hash table.
从hash表中移除你给定的对象.
+ (id)weakObjectsHashTable
Returns a new hash table for storing weak references to its contents.
返回一个hash表用来存储弱引用对象.
复制代码
stackoverflow.com/questions/2…
78.正确的删除数组:
NSMutableArray *discardedItems = [NSMutableArray array];
SomeObjectClass *item;
for (item in originalArrayOfItems) {
if ([item shouldBeDiscarded])
[discardedItems addObject:item]; //在遍历的时候的不能删除,否则会遍历不到
}
[originalArrayOfItems removeObjectsInArray:discardedItems];
复制代码
ref: stackoverflow.com/questions/1…
You can use the following code
for (int i=0;i<[inputArray count]; i++) {
NSString *item = [inputArray objectAtIndex:i];
if ([item rangeOfString:s].location == NSNotFound) {
[inputArray removeObject:item];
i--;
}
}
复制代码
77.类型判断
-(BOOL)isKindOfClass:class-object //判断对象是不是class-object或其子类的实例.
-(BOOL)isMemberOfClass:class-object //判断对象是不是class-object的实例.
+(BOOL)isSubclassOfClass:class-object //对象是否是指定类的子类 ???
复制代码
76.在xcode中可以直接解析crashLog
Xcode菜单上的Window——Organizer,找到设备的device logs项中的crash log,
稍等片刻,你就会发现这里的crash log已经被自动解析过了
(大部分情况会自动解析,如果不行请右键点击选择Re-Sysbomlicate)
别用symbolicatecrash来解析crash Log了
复制代码
75.得到代理
appdelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
复制代码
74.sqlite does not support SELECT INTO.
You can probably use this form instead:
INSERT INTO equipments_backup SELECT * FROM equipments;
CREATE TABLE equipments_backup AS SELECT * FROM equipments
INSERT INTO destinationTable (risposta, data_ins)
SELECT STATUS risposta, DATETIME('now') data_ins
FROM sourceTable
复制代码
73.UITableView滚动到最下面一行:
方法一:
//下面语句在模拟器使用会导致崩溃
[table setContentOffset:CGPointMake(0, CGFloat.max)]
复制代码
方法二:
if (self.messages.count > 0)
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:self.messages.count-1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES];
复制代码
方法三:
//Works with autolayout, BUT it’s important to call this method from viewDidLayoutSubviews
-(void)scrollToBottom
{
CGFloat yOffset = 0;
if (self.tableView.contentSize.height > self.tableView.bounds.size.height) {
yOffset = self.tableView.contentSize.height - self.tableView.bounds.size.height;
}
[self.tableView setContentOffset:CGPointMake(0, yOffset) animated:NO];
}
复制代码
stackoverflow.com/questions/2…
72.数组的过滤:
@interface Food : NSObject
@property (nonatomic, strong) NSString *foodName;
@property (nonatomic, assign) NSInteger idFood;
@end
@implementation Food
@end
Food *food1 = [[Food alloc]init];
Food *food2 = [[Food alloc] init];
food1.foodName=@"aaaa"; food1.idFood=1;
food2.foodName=@"bbbb"; food2.idFood=2;
NSArray *array = [NSArray arrayWithObjects:food1, food2, nil];
[array filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(Food* evaluatedObject, NSDictionary *bindings){
if(evaluatedObject.idFood>1)
return YES;
return NO;
}]];
复制代码
//输出:foodname:aaaa foodid:1
NSLog(@"foodname:%@ foodid:%d",[(Food*)array[0] foodName],[(Food*)array[0] idFood] );
复制代码
71.awakeFromNib
-(id) initWithCoder:(NSCoder *)aDecoder //一个初始化的方法,当调用它的时候,nib中的各组件还没加载.均为nil.
复制代码
-awakeFromNib //在这个方法中,nib中的各组件都已经加载完毕,这时,可以获取组件的相关信息.
复制代码
The nib-loading infrastructure sends an awakeFromNib message to each object recreated from a nib archive, but only after all the objects in the archive have been loaded and initialized. When an object receives an awakeFromNib message, it is guaranteed to have all its outlet and action connections already established.
ios – Should I be using awakeFromNib or initWithCoder here? – Stack Overflow
70.关于OC中的json
An object that may be converted to JSON must have the following properties://但是转换成JSON的对象必须具有如下属性:
The top level object is an NSArray or NSDictionary.//顶层对象必须是NSArray或者NSDictionary
All objects are instances of NSString, NSNumber, NSArray, NSDictionary, or NSNull.//所有的对象必须是NSString、NSNumber、NSArray、NSDictionary、NSNull的实例
All dictionary keys are instances of NSString.//所有NSDictionary的key必须是NSString类型
Numbers are not NaN or infinity.//数字对象不能是非数值或无穷
The top level object is an NSArray or NSDictionary
把字符串转化为json对象:
NSString *jsonString = @"{\"ID\":{\"Content\":268,\"type\":\"text\"},\"ContractTemplateID\":{\"Content\":65,\"type\":\"text\"}}";
NSData *data = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
复制代码
69.并行队列:GCD doesn’t guarantee that subsequent blocks on the same queue are invoked on the same thread
66.predicateWithFormat 中ANY的用法. 用来处理一对多的关系,比如一个包含对象数组的类.
对于下面结构的数组,如果要过滤Name的话,
I would like to create a NSPredicate searching if a given string is contained inside of Name. How can I achieve reaching that deep?
If you cant understand the graph. I have an array full of dictionaries, Inside the dictionaries are A string, An Array of dictionaries, and An Array of dictionaries, Inside of the dictionaries are string objects
So How do I get into the second dictionaries and search the Name key
==================================================================================
NSString *str = <search string>;
NSPredicate *pred = [NSPredicate predicateWithFormat:@"ANY Mens.Name LIKE %@ OR ANY Womens.Name LIKE %@", str, str];
NSArray *result = [your_array filteredArrayUsingPredicate:pred];
BOOL success = result.count > 0;
复制代码
ref:stackoverflow.com/questions/2…
- weak vs assign :
1.weak在对象销毁时置为nil.
在MRC中要慎用如下代码:
if (self.delegate && [self.delegate respondsToSelector:@selector(test:)]) {
[self.delegate test:nil];
}
复制代码
For ARC projects I would use strong instead of retain, I would use assign for C primitive properties and
weak for weak references to Objective-C objects.
UIViewAutoresizingNone就是不自动调整。
UIViewAutoresizingFlexibleLeftMargin 自动调整与superView左边的距离,保证与superView右边的距离不变。
UIViewAutoresizingFlexibleRightMargin 自动调整与superView的右边距离,保证与superView左边的距离不变。
UIViewAutoresizingFlexibleTopMargin 自动调整与superView顶部的距离,保证与superView底部的距离不变。
UIViewAutoresizingFlexibleBottomMargin 自动调整与superView底部的距离,也就是说,与superView顶部的距离不变。
UIViewAutoresizingFlexibleWidth 自动调整自己的宽度,保证与superView左边和右边的距离不变。
UIViewAutoresizingFlexibleHeight 自动调整自己的高度,保证与superView顶部和底部的距离不变。
UIViewAutoresizingFlexibleLeftMargin |UIViewAutoresizingFlexibleRightMargin 自动调整与superView左边的距离,
保证与左边的距离和右边的距离和原来距左边和右边的距离的比例不变。比如原来距离为20,30,调整后的距离应为68,102,即68/20=102/30
//当superview的宽度是160时
UIView* av=[[UIView alloc] initWithFrame:CGRectMake(10, 20, 80, 40)]; //与右边距离70
av.autoresizingMask=UIViewAutoresizingFlexibleLeftMargin;
//当superview的宽度是320时
NSLog(@”%@”,NSStringFromCGRect(av.frame)); // {{170, 20}, {80, 40}} 调整后与右边距离还是70//当superview的宽度是160时
UIView* av=[[UIView alloc] initWithFrame:CGRectMake(10, 20, 80, 40)]; //与右边距离70 左边距离10
av.autoresizingMask=UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin;
//当superview的宽度是320时
NSLog(@”%@”,NSStringFromCGRect(av.frame)); //{{30, 20}, {80, 40}} //与右边距离210 左边距离30,与上边成比例
{{170, 20}, {80, 40}}
63.instancetype可以返回和方法所在类相同类型的对象
①instancetype可以返回和方法所在类相同类型的对象,id只能返回未知类型的对象;
②instancetype只能作为返回值,不能像id那样作为参数
关联返回类型(related result types)
根据Cocoa的命名规则,满足下述规则的方法:
1、类方法中,以alloc或new开头
2、实例方法中,以autorelease,init,retain或self开头
会返回一个方法所在类类型的对象,这些方法就被称为是关联返回类型的方法。虽然上面这些方法返回的
是id类型,但是由于它们是是关联返回类型,编译器做相应的类型检查
[[[NSArray alloc] init] mediaPlaybackAllowsAirPlay]; // “No visible @interface forNSArray
declares the selectormediaPlaybackAllowsAirPlay
”
[[NSArray array] mediaPlaybackAllowsAirPlay]; // (No error) ,这里就不是关联返回类型了,这时instancetype 有
用武之地了.
Objective-C中的instancetype和id关键字
- performSelectorOnMainThread 和 dispatch_async on main queue区别
performSelectorOnMainThread需要特定的run loop mode
dispatch_async on main queue不受run loop mode的影响.
By default,-performSelectorOnMainThread:withObject:waitUntilDone:
only schedules the selector to run in the default run loop mode.
If the run loop is in another mode (e.g. the tracking mode), it won’t run until the run loop switches back to the default mode.
You can get around this with thevariant -performSelectorOnMainThread:withObject:waitUntilDone:modes:
(by passing all the modes you want it to run in).On the other hand, dispatch_async(dispatch_get_main_queue(), ^{ … }) will run the block as soon as the main run loop returns control flow back to the event loop.
It doesn’t care about modes. So if you don’t want to care about modes either, dispatch_async() may be the better way to go.
ref: stackoverflow.com/questions/9…
61.在 serial queue上dispatch_async and dispatch_sync 的不同.
a.他俩的区别就是相对于当前向我们创建的queue中追加任务的queue来说,是同步调用还是异步调用.
b.同步就阻塞,等待;异步立即返回,不等待。
c.总结下,如果是想对于任务之间操作就是控制queue是并行还是串行 , 如果是想相对于当前线程就控制函数 dispatch_async还是dispatch_sync。
Yes. Using serial queue ensure the serial execution of tasks. The only difference is that dispatch_sync only return after the block is finished whereas dispatch_async return after it is added to the queue and may not finished.
for this code
dispatch_async(_serialQueue, ^{ printf("1"); });
printf("2");
dispatch_async(_serialQueue, ^{ printf("3"); });
printf("4");
it may print 2413 or 2143 or 1234 but 1 always before 3
for this code
dispatch_sync(_serialQueue, ^{ printf("1"); });
printf("2");
dispatch_sync(_serialQueue, ^{ printf("3"); });
printf("4");
it always print 1234
复制代码
ref:stackoverflow.com/questions/1…
GCD学习(六) dispatch_async 和dispatch_sync – 酱酱爱 – 博客园
60.dispatch_set_target_queue的用法:
- 他可以改变queue的优先级与目标queue相同
- 如果将多个串行的queue使用dispatch_set_target_queue指定到了同一目标,那么着多个串行queue在目标queue上就是同步执行的,不再是并行执行。
-(void)testTargetQueue {
dispatch_queue_t targetQueue = dispatch_queue_create("test.target.queue", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t queue1 = dispatch_queue_create("test.1", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t queue2 = dispatch_queue_create("test.2", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t queue3 = dispatch_queue_create("test.3", DISPATCH_QUEUE_SERIAL);
dispatch_set_target_queue(queue1, targetQueue);
dispatch_set_target_queue(queue2, targetQueue);
dispatch_set_target_queue(queue3, targetQueue);
dispatch_async(queue1, ^{
NSLog(@"1 in:%@",[NSThread currentThread]);
[NSThread sleepForTimeInterval:3.f];
NSLog(@"1 out");
});
dispatch_async(queue2, ^{
NSLog(@"2 in:%@",[NSThread currentThread]);
[NSThread sleepForTimeInterval:2.f];
NSLog(@"2 out");
});
dispatch_async(queue3, ^{
NSLog(@"3 in:%@",[NSThread currentThread]);
[NSThread sleepForTimeInterval:1.f];
NSLog(@"3 out");
});
}
复制代码
输出:
2015-10-31 09:59:53.982 TEST_TabCrash[17918:50312] 1 in:<NSThread: 0x7ff439f39040>{number = 2, name = (null)} 2015-10-31 09:59:56.986 TEST_TabCrash[17918:50312] 1 out 2015-10-31 09:59:56.987 TEST_TabCrash[17918:50312] 2 in:<NSThread: 0x7ff439f39040>{number = 2, name = (null)} 2015-10-31 09:59:58.989 TEST_TabCrash[17918:50312] 2 out 2015-10-31 09:59:58.989 TEST_TabCrash[17918:50312] 3 in:<NSThread: 0x7ff439f39040>{number = 2, name = (null)} 2015-10-31 09:59:59.991 TEST_TabCrash[17918:50312] 3 out 注意上面的输入queue1,queue2,queue3的代码都在targetQueue所对应的线程上招待了 复制代码
3.如果将多个串行的queue使用dispatch_set_target_queue指定target Queue为global queue时,那么这
相当于给global queue指定了与global queue一样的优先级. [类似nsoperation]
Dispatch Queue Targeting
All custom dispatch queues have the concept of a target queue. In essence, a custom dispatch queue doesn’t actually execute any work, but passes work to its target queue for execution. Normally the target queue of a custom queue is the default-priority global queue.
The target queue of a custom queue can be set by using the dispatch_set_target_queue function. You can pass it any other dispatch queue, even another custom queue, so long as you never create a cycle. This function can be used to set the priority of a custom queue by simply setting its target queue to a different global queue. If you set your custom queue’s target to be the low priority global queue, all work on your custom queue will execute with low priority, and the same with the high priority global queue.
Another potential use of this is to target a custom queue to the main queue. This will cause all blocks submitted to that custom queue to run on the main thread. The advantage of doing this instead of simply using the main queue directly is that your custom queue can be independently suspended and resumed, and could potentially be retargeted onto a global queue afterwards, although you’ll have to be careful to ensure that all blocks which run after that point can tolerate being away from the main thread!
Yet another potential use is to target custom queues to other custom queues. This will force multiple queues to be serialized with respect to each other, and essentially creates a group of queues which can all be suspended and resumed together by suspending/resuming the queue that they target. For a way that this could be used, imagine an application which is scanning a set of directories and loading the files within. In order to avoid disk contention, you want to make sure that only one file loading task is active for each physical disk. However, multiple files can be read from physically separate disks simultaneously. To make this happen, all you have to do is build a dispatch queue structure which mirrors your disk structure.
First, you would scan the system and find the disks, and create a custom dispatch queue for each one. Then you would scan the filesystems and create a custom queue for each one of those as well, pointing their target queues at the queue of the appropriate disk. Finally, each directory scanner can have its own queue as well, pointing the target at the filesystem on which the directory resides. The directory scanners can enumerate their directories and submit a block for each file directly to their own queue. Due to how the system is set up, this will inherently serialize all access to each physical disk while allowing parallel access to separate disks, all without any manual intervention beyond the initial queue setup process.
ref: dispatch_set_target_queue的用法
60.为什么dispatch_get_current_queue被遗弃了
dispatch_get_current_queue never really made sense in the first place. Here’s why: There are a handful of “root” queues (one for each priority, and then the main queue). Every other queue ultimately ends up targeting one of these root queues. This means that, in the general case, there isn’t a single answer to the question, “What queue am I running on?”
For instance, if you have queue B that targets queue A, then either A or B would be a reasonable answer to that question, for a block submitted to queue B. Furthermore, since all queues end up targeting one of the global/root queues, arguably the best answer would be “whatever root queue it ended up executing on”, except that’s not really useful to anyone, because it doesn’t significantly differentiate anything.
In my experience, in most cases, what folks want from dispatch_get_current_queue is the answer to, “What queue was I initially submitted to?” However, by definition, whatever code submitted the block already knows what queue it was submitted to (because it’s doing the submission). So arguably, if you needed to capture that information, you could trivially do so at enqueue time; you don’t need dispatch_get_current_queue to answer that question. For these cases, dispatch_get_current_queue would just be a shortcut, and a flawed one at that (because of queue targeting.)
The other big class of cases is when you want to know if you’re on the main queue. -[NSThread isMainThread] is sufficient/authoritative for that, so you don’t need dispatch_get_current_queuefor that either.
Another answerer also pointed out that dispatch_get_current_queue was frequently misused in an attempt to emulate recursive locking with GCD queues. It’s not possible to reliably implement recursive locks in a queue based system because “queues aren’t locks”. I’ve written at some length about that particular situation in another answer.
59.在.mm文件中,也就是说以objective-c++方式编译的文件中:
下面的这种写法会造成编译错误:
RAC(self.submitButton, enabled) = [RACSignal
combineLatest:@[siteAddressValidSignal, accessKeyValidSignal]
reduce:^id(NSNumber *siteAddressValid, NSNumber *accessKeyValid){
return @(siteAddressValid.boolValue && accessKeyValid.boolValue);
}];
复制代码
得改成下面这样:
[RACSignal combineLatest:@[siteAddressValidSignal, accessKeyValidSignal]
reduce:(id)^id(NSNumber *siteAddressValid, NSNumber *accessKeyValid){
return @(siteAddressValid.boolValue && accessKeyValid.boolValue);
}];
[RACSignal combineLatest:reduce:] won’t compile as Objective-C++
- [_tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
//不使用tableview默认的分隔线
而是自己自定义分隔线.
可以在每个cell中,通过下面的方式来自定义出分隔线的样子,下面是用一个细长的label来实现,然后将其放到合适的位置
UILabel *line1 = [[UILabel alloc]initWithFrame:CGRectMake(sparatorStartx, cellheight-0.5, cellwidth, 0.5)];
[line1 setBackgroundColor:[UIColor lightGrayColor]];
[cell.contentView addSubview:line1];
if(indexPath.row == 0){
UILabel *line1 = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, cell.frame.size.width, 0.5)];
[line1 setBackgroundColor:[UIColor lightGrayColor]];
[cell.contentView addSubview:line1];
}
复制代码
注:注意每个cell只允许addsubview一次,所以上面的方法只是讲解怎么加,程序中是会出问题的
57.在工程中资源文件放到group下,Build之后,文件直接就复制到了根目录下,于是读取的方法,应该是这样:
蓝色的是文件夹,黄色的是
NSString *earth = [[NSBundle mainBundle] pathForResource:@"Brad Cox" ofType:@"png"];
使用文件夹的时候,依然使用同样的方法,需要制定文件夹路径
{
NSString *earth = [[NSBundle mainBundle] pathForResource:@"a" ofType:@"png" inDirectory:@"bb"];
NSLog(@"%@",earth);
}
{
NSString *earth = [[NSBundle mainBundle] pathForResource:@"a" ofType:@"png" ];
NSLog(@"%@",earth);
}
复制代码
输出:
2016-07-09 22:31:21.072 testaa[20822:74824] /Users/taivex2/Library/Developer/CoreSimulator/Devices/6F5EE523-D3D1-4F69-AD19-F0DD311A5F0C/data/Containers/Bundle/Application/6FFAB630-2B87-49C9-B988-19F5A195AB0F/testaa.app/bb/a.png 2016-07-09 22:31:21.072 testaa[20822:74824] /Users/taivex2/Library/Developer/CoreSimulator/Devices/6F5EE523-D3D1-4F69-AD19-F0DD311A5F0C/data/Containers/Bundle/Application/6FFAB630-2B87-49C9-B988-19F5A195AB0F/testaa.app/a.png 复制代码
NSBundle的使用,注意mainBundle和Custom Bundle的区别
56.得到AppDelegate
appdelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
stackoverflow.com/questions/1…
55.If you have an NSArray of strings
{ @"ONE", @"ONE", @"ONE", "TWO", @"THREE", @"THREE" }
How would I turn that into
{ @”ONE”, @”TWO”, @”THREE” }
My initial thought was that you could do:
NSArray * a = [NSArray arrayWithObjects:@"ONE", @"ONE", @"ONE", @"TWO", @"THREE", @"THREE", nil];
NSLog(@"%@", [a valueForKeyPath:@"@distinctUnionOfObjects.self"]);
//But that does not maintain order. Therefore, you have to do it manually:
NSArray * a = [NSArray arrayWithObjects:@"ONE", @"ONE", @"ONE", @"TWO", @"THREE", @"THREE", nil];
NSMutableArray * unique = [NSMutableArray array];
NSMutableSet * processed = [NSMutableSet set];
for (NSString * string in a) {
if ([processed containsObject:string] == NO) {
[unique addObject:string];
[processed addObject:string];
}}
复制代码
I use an NSMutableSet for determining if I’ve already come across this entry before (as opposed to [unique containsObject:string], since a set will have O(1) lookup time, and an array has O(n) lookup time. If you’re only dealing with a small number of objects, then this won’t matter. However, if the source array is very large, then using the set to determine uniqueness may add a bit of a speed boost. (however, you should use Instruments to profile your code and see if it’s necessary)
NSArray * uniqueArray = [[NSOrderedSet orderedSetWithArray:duplicatesArray] array];
This way, you also preserve the order!
NSArray *myArray = @[@"TWO", @"THREE",@"ONE", @"ONE", @"ONE", @"THREE"];
NSArray * uniqueArray = [[myArray valueForKeyPath:@"@distinctUnionOfObjects.self"] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
复制代码
stackoverflow.com/questions/4…
54.对于AFNetworking 2.0 – “unacceptable content-type: text/plain”,解决办法:
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@”text/plain”];
stackoverflow.com/questions/2…
53.对于服务器传来的时间戳,最好用long long value 来表示:
NSLog(@”%lld”, [myValue longlongValue]);
52.sqllite中所有字符串的编码都是Unicode
In Microsoft SQL Server, VARCHAR is ASCII and NVARCHAR is Unicode (UTF-16). In SQLite, all text is Unicode, so it’s not relevant. In any case, SQLite is loosely typed so it wouldn’t make a difference anyways. See www.sqlite.org/datatype3.h…🙂
Moreover SQLite will never enforce length specifications. If you declare a column as CHAR(n), VARCHAR(n), TEXT or STRING or (…) it has no length limitation. – Benoit Oct 14 ’10 at 6:22
stackoverflow.com/questions/3…
51.NSRecursiveLock
参照官方文档,该lock可以防止一个线程对该锁申请多次而产生死锁的情况。当一次线申请了某段代码的lock(一次或多次),则其他线程再次申请的时候不会成功,被阻塞。
NSRecursiveLock类定义的锁可以在同一线程多次lock,而不会造成死锁。递归锁会跟踪它被多少次lock。每次成功的lock都必须平衡调用unlock操作。只有所有的锁住和解锁操作都平衡的时候,锁才真正被释放给其他线程获得。
同一个线程,同一个线程,在没有unlock的情况下,对同一个lock多次加锁,那么这时为了避免死锁,就需要NSRecursiveLock
Objective-C中不同方式实现锁(二)
50.注意下在返回值的含义,如果是NSOrderedDescending代表从s至v是降序,那么s就比v要大”大” 逐个比较
NSString* s=@"12345a";
NSString* v=@"12345b";
if([s compare:v options:NSCaseInsensitiveSearch]==NSOrderedDescending){
NSLog(@"%@ is bigger than %@",s,v);
}
else{
NSLog(@"%@ is smaller than %@",s,v);
}
复制代码
输出:12345a is smaller than 12345b
49.新增发布证书的影响
如果原来的发布证书失效了,那么我在开发者后台重新生成一个新的证书,那么有哪些证书,还需要相应的变动
一下吗?
在开发者中心新增发布证书,那么需要得重新生成一个distribution provisioning file 和 一个adhoc provisioning file ,因为原来的这两个证书不与现在新增的的发布证书相关. 也就是这两个证书都是与开发证书相关联的.
那么生产版的推送证书,不用变动,因为推送证书是与AppID相关联的.
48.”The application does not have a valid signature”错误的处理方法
在xcode->product->clean,清理一下解决方案,一般来说,就可以解决问题了.
47.AD Hoc模式验证生产证书
在开发者中心生成了Production SSL Certificate并导入mac,然后再到开发者中心生成制作一个Ad hoc的Provisioning Profiles,
这些做完了之后,在XCode->Product->Archive。在Organizer中可以看到打包的文件,然后Export就得到了ipa文件。通过itunes装到有权限的设备上就可以验证生产证书的推送。总结下,首先需要在苹果开发者中心把app勾选push服务,然后发布证书 + Ad hoc的Provisioning文件 + push生产证书 。通过Ad
hoc模式,就可以对现网Push服务进行验证了。
itunes安装的步骤: 先将生成的ipa文件添加到资料库,然后应用程序列表就会出现相应的app,点击安装,然后同步一下,就可以安装到iphone了
46.NSDate creation using NSCalendar and NSTimeZone
If you are creating a date manually you should specify the calendar (2012 in Gregorian, but 5772 in Hebrew) and time zone (22PM London time, but 7AM Sydney time). // Use the user's current calendar and time zone NSCalendar *calendar = [NSCalendar currentCalendar]; [calendar setTimeZone: [NSTimeZone systemTimeZone]]; // Specify the date components manually (year, month, day, hour, minutes, etc.) NSDateComponents *timeZoneComps=[[NSDateComponents alloc] init]; [timeZoneComps setHour:22]; [timeZoneComps setMinute:0]; [timeZoneComps setSecond:0]; // ... year, month, ... // transform the date compoments into a date, based on current calendar settings NSDate *date = [calendar dateFromComponents:timeZoneComps]; 复制代码
45.今天在ios7下运行一个老版本的程序,出现Xib not found异常,处理方法是:进入interface builder,找到相应的xib,点击localize,添加对应的localization信息,就可以了.
stackoverflow.com/questions/1…
- localTimeZone代表当前程序 在使用的时区
localTimeZone VS systemTimeZone
- localTimeZone is the default time zone for the current application. This can be set by the user or programmatically in the app (or possibly in other ways). It’s basically a pointer to defaultTimeZone with a level of indirection; if the default time zone changes, localTimeZone will change as well.
- systemTimeZone, on the other hand, is the time zone used by the core system. A cached value for this will not change if the system time zone changes during the application’s execution, unlike localTimeZone.
- If you want to know the system’s time zone setting, you probably want to use +[NSTimeZone systemTimeZone]. If you just want the correct time zone for your app to work in, you probably want +[NSTimeZone localTimeZone].
stackoverflow.com/questions/1…
43.注意format格式中的MM是大定的,以及HH大小写之间的区别.
[NSDate date] returns the date in GMT.
如果想输出当前时区制的时间:
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.timeZone=[NSTimeZone localTimeZone];
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];//24小时制
//[dateFormatter setDateFormat:@"yyyy-MM-dd hh:mm:ss"];//12小时制
NSString *dateString = [dateFormatter stringFromDate:[NSDate date]];
NSLog(@"str:[%@]",dateString);
复制代码
42.推送时遇到”未找到应用程序的“aps-environment”的权利字符串” 的解决方法
did Fail To Register For Remote Notifications With Error: Error Domain=NSCocoaErrorDomain Code=3000 “未找到应用程序的“aps-environment”的权利字符串” UserInfo=0x15d68990 {NSLocalizedDescription=未找到应用程序的“aps-environment”的权利字符串}
解答:出现这个问题有两个方面的原因,一个是由于当前应用程序的boundle identifier 和推送证书中对应的boundle identifier不一样
另一个是由于provision profile的问题,可以去开发者中心重新生成一个包含调试设备的deviceToken的provision profile.然后下载下来,双击,安装到xcode中重新编译程序就行了.
或者是由于你的Provisioning Profile文件,不具备APNS功能导致的。请登陆Apple Developer 网站设置好证书,更新Provisioning Profile,重新导入Xcode。
- NSString大小写转换
NSString 变大写,小写,每个字母开头大写
-(void)viewDidLoad
{
NSString *a = @"i like long dress";
NSLog(@" \n 大写 a:%@ ", [a uppercaseString]);
NSLog(@" \n 小写 a:%@ ", [a lowercaseString]);
NSLog(@" \n 字母开头大写 a:%@ ", [a capitalizedString]);
}
2011-07-11 17:33:58.082 Q[6111:207] 大写 a:I LIKE LONG DRESS
2011-07-11 17:33:58.083 Q[6111:207] 小写 a:i like long dress
2011-07-11 17:33:58.084 Q[6111:207] 字母开头大写 a:I Like Long Dress
复制代码
40.#import #include的区别
他俩的作用 差不多 。 只不是 #import 解决了重复引用的问题。 但是使用 #include 就必须要注意处理 重读引用的问题。
“What is the difference between #include and #import?
#import ensures that the preprocessor only includes a file once.
#include will allow you to include the same file many times. ”
摘录来自: Hillegass, Aaron. “Objective-C Programming: The Big Nerd Ranch Guide, 2/e (Big Nerd Ranch Guides)”。
复制代码
import和@class和include的区别
39.CAAnimition完成时的回调调用
下面的方法都是在有如下设置才有效
CAAnimation *anim = ...
anim.removedOnCompletion = NO; //如果这里是YES的话,那么回调也会被调用.
CATransition *animation = [CATransition animation];
[animation setType:kCATransitionFade];
[animation setSubtype:kCATransitionFromTop];
[animation setDelegate:self];
- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag{
}
复制代码
CAAnimation Completion handler
38.CAAnimationGroup会覆盖组合动画中其它的动画的设置
CAAnimationGroup *anim = [CAAnimationGroup animation];
[anim setAnimations:[NSArray arrayWithObjects:[self transparencyAnimation], [self translateAnimation], nil]]; [anim setDuration:3.0];//这个时间周期,会覆盖其它动画的周期
[anim setRemovedOnCompletion:NO];//这个也会覆盖
[anim setDelegate:self];//这个也会覆盖
[anim setFillMode:kCAFillModeForwards];//这个也会
[layer addAnimation:anim forKey:nil];
“… animations are clipped to the duration of the animation group. For example, a 10 second animation
grouped within an animation group with a duration of 5 seconds will only display the first 5 seconds of
the animation.”
“The delegate and removedOnCompletion properties of animations in the animations property are currently
ignored. The CAAnimationGroup delegate does receive these messages.”
复制代码
CAAnimationGroup的用法
37.左右晃动效果
CAKeyframeAnimation * anim = [ CAKeyframeAnimation animationWithKeyPath:@"transform" ] ;
anim.values = @[ [ NSValue valueWithCATransform3D:CATransform3DMakeTranslation(-5.0f, 0.0f, 0.0f) ], [ NSValue valueWithCATransform3D:CATransform3DMakeTranslation(5.0f, 0.0f, 0.0f) ] ] ;
anim.autoreverses = YES ;
anim.repeatCount = 2.0f ;//反向会减慢回来的动画,需要设置速度anim.speed = 2
anim.duration = 0.07f ;
[ viewToShake.layer addAnimation:anim forKey:nil ] ;
复制代码
CAAnimation 效果tip
36.stringByAddingPercentEscapesUsingEncoding不会对特殊字符!*'();:@&=+,/?%#[] 进行编码,如果你的url参数中有这些特殊字符的话,就要用到下面所讲到的CFURLCreateStringByAddingPercentEscapes
stringByReplacingPercentEscapesUsingEncoding will do the opposite, convert the percent escape to the Unicode*.
objectiveC中的urlEncode
35.UITableView中的NSIndexPath是从零开始的.
34.[UITableView cellForRowAtIndexPath:]
只能获取可见的cell,如果不可见的,返回nil
An object representing a cell of the table or nil if the cell is not visible or indexPath is out of range.
So if that cell is not currently visible then it will return nil. So, is it visible?Other than that – check that you are actually creating cells in cellForRowAtIndexPath: as you haven’t specifically shown that you are.
- stringByAddingPercentEscapesUsingEncoding 把链接字符串进行 urlEncode
// 修改提醒时间
NSString *strUrl1 = [NSString stringWithFormat:@"%@%@?Token=%@&taskid=%d&sn=%@&remindtime=%@&inputuser=%@&delflag=%@&lastmodifydate=%@",k3BaseURL,kActionUpdateDrugRemindTime,Token,intId,sn,remindtime,inputuser,@"0",lastmodifydate];
self.alertID=[NSString stringWithFormat:@"%d",intId];
strUrl1 = [strUrl1 stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
- (NSString *)URLDecode
{
NSString *result = [(NSString *)self stringByReplacingOccurrencesOfString:@"+" withString:@" "];
result = [result stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
return result;
}
复制代码
32.UIScrollView横向滚动,根据当前的contentOffset.x的值来设置UIPageControl页码的状态,注意下面
随着滚动方向的不同,分别使用ceil和floor两个不同的求近似值的函数.
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat pageWidth = self.view.frame.size.width;
int page=0;
//根据滚动方向来设置取值的方式不同
if(lastContentOffset>scrollView.contentOffset.x){
page =(int)(ceil(scrollView.contentOffset.x / pageWidth));
}
else if(lastContentOffset<scrollView.contentOffset.x){
page =(int)(floor(scrollView.contentOffset.x / pageWidth));
}
lastContentOffset=scrollView.contentOffset.x;
pageIndicator.currentPage=page;
}
复制代码
31.UIPageControl中指示点的颜色操作.
- pageIndicatorTintColor 没有选中的点点的颜色
- currentPageIndicatorTintColor 当前页码值的颜色
30.几个求近似值的数学函数的区别
ceil(x)返回不小于x的最小整数值(然后转换为double型)。
floor(x)返回不大于x的最大整数值。
round(x)返回x的四舍五入整数值。
复制代码
29.在IOS6中参数中文件名必须要大小写一致,否则会找不到相应的文件
比如bundle中有个文件default1.png
下面的写法:在IOS7以上的版本中,可以加载文件,但是在IOS6.x版本中,image1直接就为nil
UIImage *image1 = [UIImage imageNamed:@"Default1"];
复制代码
28.禁止UIScrollView垂直方向滚动,只允许水平方向滚动
scrollview.contentSize = CGSizeMake(你要的长度, 0);
禁止UIScrollView水平方向滚动,只允许垂直方向滚动
scrollview.contentSize = CGSizeMake(0, 你要的宽度);
27.ios隐藏状态栏(status bar)
For iOS6 and below, we used to write a line of code in didFinishLaunchingWithOptions: as
[UIApplication sharedApplication].statusBarHidden = YES;
26.UIScrollView滚动方向
//somewhere in the header
@property (nonatomic, assign) CGFloat lastContentOffset
//
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
ScrollDirection scrollDirection;
if (self.lastContentOffset > scrollView.contentOffset.x)
scrollDirection = ScrollDirectionRight;
else if (self.lastContentOffset < scrollView.contentOffset.x)
scrollDirection = ScrollDirectionLeft;
self.lastContentOffset = scrollView.contentOffset.x;
// do whatever you need to with scrollDirection here.
}
复制代码
24.当viewWillAppear:被触发时,说明对应的view controller变为”active”状态
viewWillAppear:方法的作用是与屏幕中改变的内容进行交互。告诉view controller将对应的界面内容显示到屏幕最前端:确保view controller中所有的文本控件显示出最新的信息、必要的数据是可访问的、并对适当的通知(notification)进行观察等。当viewWillAppear:被触发时,说明对应的view controller变为”active”状态
23.//将html文本中的img中的宽度替换成90%,这样就可以适应各屏幕
-(NSString*)replaceImgTagWidth:(NSString*)markup{
NSString *regexToReplaceWidth = @"<(img)\\s+src=\"(.*?)\".*?>";
NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:regexToReplaceWidth
options:NSRegularExpressionCaseInsensitive
error:&error];
return [regex stringByReplacingMatchesInString:markup
options:0
range:NSMakeRange(0, markup.length)
withTemplate:@"<img src=\"$2\" style=\" width:92%;border: 0px; margin:0px; padding: 0px; font-size: 0px; color: transparent;\" />"];
}
复制代码
[000]IOS中的正则总结
22.NSString的遍历
- (NSString *)replaceChineseQuatationMark:(NSString*) markup
{
NSMutableString* s=[markup mutableCopy];
unichar temp=[@"“" characterAtIndex:0];
NSInteger len=s.length;
BOOL flag=NO;
for(NSInteger i=0;i<len;i++){
if([s characterAtIndex:i]=='<')
{
flag=YES;
continue;
}
if([s characterAtIndex:i]==temp && flag==YES)
{
[s replaceCharactersInRange:NSMakeRange(i, 1) withString:@"\""];
continue;
}
if([s characterAtIndex:i]=='>')
flag=NO;
}
return [s copy];
}
复制代码
21.自定义UITableViewCell分隔线.
{
[self.tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
}
after that
{
#define cellHeight 80 // You can change according to your req.
#define cellWidth 320 // You can change according to your req.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UIImageView *imgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"seprater_line.png"]];
imgView.frame = CGRectMake(0, cellHeight, cellWidth, 1);
[customCell.contentView addSubview:imgView];
return customCell;
}
}
复制代码
20.block的实现牵扯到三个结构体
struct __main_block_impl_0 //类型名字可变
{
struct __block_impl impl;//类型名字不变,这个结构体中的成员是不变的
struct __main_block_desc_0 * Desc; //类型名字可变,使用了__block标识符时,这个结构体成员多了两个函数指针 指针入口
struct __Block_byref_val_0 //类型名字可变,使用了__block标识符时,这个结构体根据被__block标识符修饰的变量的个数,其定义中成员的数量是可变的
}
//使用了__block标识符时
static struct __main_block_desc_0 {
unsigned long reserved;
unsigned long Block_size;
void (*copy )(struct __main_block_impl_0*, struct __main_block_impl_0*);
void (*dispose )(struct __main_block_impl_0*);
}
struct __Block_byref_val_0 {
void *__isa ;
__Block_byref_val_0 *__forwarding ;
int __flags ;
int __size ;
int val ;
};
复制代码
19.对于视图或者图层来说, frame 并不是一个非常清晰的属性,它其实是一个虚拟属性,是根据 bounds , position 和 transform 计算而来,所以当其中任何一个值发生改变,frame都会变化。相反,改变frame的值同样会影响到他们当中的值
18.关联属性的用法
#import <objc/runtime.h>
static char alertInfoKey;
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
NSString* dataYouWantToPass = @"some info";
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"hello" message:@"miss-chalk" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"YES", nil];
[alert show];
objc_setAssociatedObject(alert, &alertInfoKey, dataYouWantToPass, OBJC_ASSOCIATION_RETAIN);
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSString* data = objc_getAssociatedObject(alertView, &alertInfoKey);
NSLog(@"%@",data);
}
@end
复制代码
17.而对于引用了外部变量的block,如果没有对他进行copy,他的作用域只会在声明他的函数栈内(类型是__NSStackBlock__),如果想在非ARC下直接返回此类block,Xcode会提示编译错误的. 所以在非ARC下,必须把block复制到堆中才可以在函数外使用block.
- frame 和 bounds的不同用法
frame
The frame rectangle, which describes the view’s location and size in its superview’s coordinate system.
bounds
The bounds rectangle, which describes the view’s location and size in its own coordinate system.
So if you want to change the position of your cell within it’s superview (the tableview in this case), use the frame. Bu if you want to shrink or move an element within the view, use the bounds!
15.frame是一个框架,bounds是显示子view的东西。
- 对于bound的point:它可以不会改变frame的原点,改变的是bounds自己的原点,进而影响到“子view”的显示位置。这个作用更像是移动bounds原点的意思。
- 对于bound的size:它可以改变的frame。如果bounds的size比frame的size大。那么frame也会跟着变大,那么frame的原点也会变。这个作用更像边界的意思。
- frame定义了一个相对父视图的一个框架(容器),bounds则是真实显示区域。如果,bounds比frame小了,可以放到框架(容器)里。如果bounds比frame大,感觉frame被“撑大”了。frame变成了{{25, 25}, {250, 250}}了。25是如何得出的?bounds比frame长,宽各大了50像素,那么四条边平衡一下,各溢出“25”像素。如图所示:
13.使用容器的block版本的枚举器时,内部会自动添加一个AutoreleasePool:
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
// 这里被一个局部@autoreleasepool包围着
}];
复制代码
当然,在普通for循环和for in循环中没有,所以,还是新版的block版本枚举器更加方便。for循环中遍历产生大量autorelease变量时,就需要手加局部AutoreleasePool咯。
12.对于代理对象,最好的调用方式是:判断该对象能否响应将要执行该代理类的方法,这样可以避免unrecognized selector错误导致程序崩溃
[ViewA convertPoint:CGPointMake(0, tp.y) toView:ViewB] //把ViewA坐标系中的点的坐标转换成ViewB坐标系的坐标.
[ViewA convertPoint:CGPointMake(0, tp.y) fromView:ViewB] //把ViewB坐标系中的点的坐标转换成ViewA坐标系的坐标.
复制代码
10.NSString去除两边空格字符,like trim( )
NString *cleanString = [dirtyString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
复制代码
IOS简单的字串替换方法stringByTrimmingCharactersInSet
NSCharacterSet NSScanner 对字符串的处理
9.二者方法的执行顺序:heightForRowAtIndexPath这个代理方法是先执行的,后执行cellForRowAtIndexPath
在cellForRowAtIndexPath设置相应cell的高度,然后再在cellForRowAtIndexPath中返回这个对应cell的高度就可以了.
设置了estimateHeight,先后执行 cellForRowAtIndexPath 再 heightForRowAtIndexPath
8.//键盘遮挡处理
//_svQues是scrollview.
//从子到父的关系:textField-> textfild.superview->self.view
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
CGPoint sp=_svQues.contentOffset;
CGPoint tp=textField.frame.origin;
//textFiled相对于self.view的位置
CGPoint temp=[textField.superview convertPoint:CGPointMake(0, tp.y) toView:self.view];
sp.y+=temp.y;
sp.y-=40;
_svQues.contentOffset=sp;
}
复制代码
第三方库IQKeyBoardMannager