延续上一篇iOS |知识点整理(2)
27.IOS如何模拟新机器第一次安装:
已安装的机器,模拟新机器第一次安装:
1.先删除app
2.按住HOME+开机键 15秒,强制重启
3.将系统时间往后调1天.
4.按住HOME+开机键 15秒,强制重启
5.重新安装app
复制代码
一般情况下,只有在新机器第一次安装,且在你的应用程序调用registerForRemoteNotifications,会询问你是否开启远程通知.那么如果用户选择了,不接受的话,用户想再次接收推送,就只能到设置里面去开启了. 也就是说,这时,在我们的app里,是无法用代码来再次开启用户的推送功能的.
也就是说,如果用户在IOS设置里面关闭了对应APP的推送,那么在你程序里registerForRemoteNotifications是没作用的的
如果用户在IOS设置里面开启了对应APP的推送,那我们可以在应用程序里通过unregisterForRemoteNotifications来关闭推送.
[Technical Note TN2265: Troubleshooting Push Notifications]
The first time a push-enabled app registers for push notifications, iOS asks the user if they wish to receive notifications for that app. Once the user has responded to this alert it is not presented again unless the device is restored or the app has been uninstalled for at least a day.
If you want to simulate a first-time run of your app, you can leave the app uninstalled for a day.You can achieve the latter without actually waiting a day by setting the system clock forward a day or more, turning the device off completely, then turning the device back on.
Update: As noted in the comments below, this solution stopped working since iOS 5.1. I would encourage filing a bug with Apple so they can update their documentation. The current solution seems to be resetting the device’s content and settings.
Update: The tech note has been updated with new steps that work correctly as of iOS 7.
- Delete your app from the device.
- Turn the device off completely and turn it back on.
- Go to Settings > General > Date & Time and set the date ahead a day or more.
- Turn the device off completely again and turn it back on.
ref: stackoverflow.com/questions/8…
stackoverflow.com/questions/2…
stackoverflow.com/questions/8…
26.NSStringFormClass 这个不用说,看命名都应该知道吧。
NSClassFromString 将NSString转换成一个Class,如果不存在,返回一个nil。 NSClassFromString的好处是: 1 弱化连接,因此并不会把没有的Framework也link到程序中。 2 不需要使用import,因为类是动态加载的,只要存在就可以加载。因此如果你的toolchain中没有某个类的头文件定义,而你确信这个类是可以用的,那么也可以用这种方法。 同样的,还可以通过一个方法名字来得到一个Selector,然后就可以动态的调用这个Selector了,在Obj-c里面,一切都是动态的。 类似的函数如下: NSClassFromString NSGetSizeAndAlignment NSLog NSLogv NSSelectorFromString NSStringFromClass NSStringFromSelector 复制代码
ref: wsqwsq000.iteye.com/blog/118133…
25.引号与尖括号包裹引用头文件的区别
“When specifying the name of the file to be imported, you can wrap the filename in quotes or angle brackets. Quotes indicate that the header is in your project directory. Angle brackets indicate that the header is in one of the standard locations that the preprocessor knows about. (<math.h>, for example, is /Applications/Xcode46-DP3.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk/usr/include/math.h.) Here are two examples of #import directives:
// Include the headers I wrote for Pet Store operations
#import “PetStore.h”
// Include the headers for the OpenLDAP libraries
#import <ldap.h>
24.Xcode6中的standard architectures排除了armv7s
Xcode 6 Standard architectures exclude armv7s,因为armv7和armv7s的指令集差别很小.就算是你不包含armv7s
armv7的机器码一样可以在32位的A6处理器的机子上运行得很好.
I also filed a bug on this and got a reply stating that this is intentional. If you want do build for armv7s you have to add the architecture manually. I have now idea why this change was made. I’ll update this if I get additional information.
Update from the dev forums:
The reason for including armv7s would be marginal backward compatibility. But the general differences between armv7 and armv7s instruction sets are minor. So if you choose not to include armv7s, the targeted armv7 machine code still runs fine on 32 bit A6 devices, and hardly one will notice performance gap.
ref: stackoverflow.com/questions/2…
23. Terminating app due to uncaught exception ‘NSUnknownKeyException’,*
reason: ‘[<UIApplication 0x6a14650> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key calculatorScreen.’
如果在Target -> General -> Main Interface里设置的xib,必须包含UIWindow,并且该xib的File Owner应该是AppDelegate
,如果没有满足这些条件,就会报上面的错误.
解决的方法是,将在Target -> General -> Main Interface里设置的xib,设置为空. 自己在AppDelegate的代码里,设置UIWindow.
If you have a control in your nib (xib file) that is linked to a property (IBOutlet) or method (IBAction) in your view controller, and you have either deleted or renamed the property or method, the runtime can’t find it because it has been renamed and therefore crashes.
In your case, you have set the Main Interface property of the project to your ViewController.nib. This is a problem because the only nibs that should be used as Main Interface should have UIWindows in them and the File Owner in that nib should be set to the AppDelegate. The UIWindow in the nib should be linked to the File Owner’s (AppDelegate) window property. Because you set that with a nib without the traits the runtime was looking for, it gives you this error.
The solution is to leave the Main Interface blank as you do not have to set up UIWindows manually anymore.
ref: stackoverflow.com/questions/1…
22.Xcode ‘CodeSign error: code signing is required’
Be sure you code sign on the line “any iOS SDK” and not “Debug/Distribution/Release”
Here is exactly what I did :
Code signing identity -> don't code sign
* Debug -> don't code sign
** any iOS SDK -> [my developer profile]
* Distribution -> don't code sign
** any iOS SDK -> [my AppStore profile]
* Release -> don't code sign
** any iOS SDK -> [my AdHoc profile]
When I put my profiles one level above (at Debug/Ditribution/Release), it doesn't work for some reason (bug ?).
复制代码
Hope it helps some of us !
stackoverflow.com/questions/3…
21.今天,使用了第三方一个库,结果,出现,iOS Undefined symbols for architecture armv7 std::basic_string<char, std::char_traits
注意:不是修改Build Setting里面的设置,而是添加一个libstdc++.dylib, 搞定!
- //如果dx,dy大于零,则结果比rect小,相当于rect加了padding后,里面可用rect的大小
//如果dx,dy小于零,则结果比rect大
CGRectInset(<#rect#>, <#dx#>, <#dy#>)
- //获取系统字体的大小
label.font = [UIFont systemFontOfSize:18.0];
- //禁止autoresizingmask到contraints的转换,以便下面使用自定义的constraints
label.translatesAutoresizingMaskIntoConstraints = NO;
//错误信息的处理
static NSString* errordomain=@"login error";
typedef NS_ENUM(NSInteger,ErrorCode){
LOGIN_ERROR_INPUT,
LOGIN_ERROR_AUTH
};
//NSDictionary* userinfo=@{NSLocalizedDescriptionKey:NSLocalizedString(@"用户名不存在或密码错误!", nil)};
//NSError* error=[[NSError alloc] initWithDomain:errordomain code:LOGIN_ERROR_AUTH userInfo:userinfo];
errorinfo.localizedDescription; //获取错误信息
复制代码
4.NSPredicate predicateWithBlock 及array filteredArrayUsingPredicate的用法
NSArray *array = @[@1, @2, @3, @7, @8, @11, @14, @19, @20];
NSPredicate *evenNumbers = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
NSNumber *number = (NSNumber *)evaluatedObject;
return [number integerValue] % 2 == 0;
}];
NSArray *filteredArray = [array filteredArrayUsingPredicate:evenNumbers];
NSLog(@"%@", filteredArray); // (2, 8, 14, 20)
复制代码
- array filteredArrayUsingPredicate 也可表示为下列的方法:
NSPredicate* _predicate = [NSPredicate predicateWithBlock:^BOOL(MyObject evaluatedObject, NSDictionary * bindings) {
BOOL expectedValue = [[bindings valueForKey:@"EXPECTED_VALUE"] boolValue];
return (evaluatedObject.enabled == expectedValue);
}];
NSDictionary *bindings = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:@"EXPECTED_VALUE"];
NSIndexSet *indexSet = [array indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
return [_predicate evaluateWithObject:object substitutionVariables:bindings];
}];
return [array objectsAtIndexes:indexSet];
复制代码
引用:NSPredicate predicateWithBlock & bindings
6.1. *-(CGRect)convertRect:(CGRect)rect toView:(UIView )view;
文档解释:Converts a rectangle from the receiver’s coordinate system to that of another view.
意思就是说把一个矩形从接收者的坐标系转换到另一个视图(view)的坐标系中.
注:1. 若view参数为nil,则转换为窗口(window)的坐标系;接收者与view都必须是同一窗口(window)的对象。
eg1:下面是把选中的cell单元的frame转换为相对于当前窗口坐标系的坐标:
CGRect convertRect = [tableView convertRect:cell.frame toView:self.view];
注意参数的位置,别写反了。
得到了cell相对于self.view的相对坐标,那么cell上控件相对self.view的坐标也就能相应的计算出来了。
eg2:把UIScrollView中的btn,转换成UIScrollView的父view中的坐标.
view体系如下: mainView <- UIScrollView <- view <- btn. 要把btw转换成,mainView坐标系中坐标.
CGRect r=[mainView convertRect:btn.bounds fromView:btn];
扩展阅读:www.jianshu.com/p/1c6544777…
7.注册Nib作为UITableViewCell:
[self.tableView registerNib:[PhotoCell nib] forCellReuseIdentifier:PhotoCellIdentifier];
使 用:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:self.cellIdentifier forIndexPath:indexPath];
8.动画操作的一般源码
[UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:2.0]; [UIView setAnimationCurve:UIViewAnimationCurveLinear]; [UIView setAnimationBeginsFromCurrentState:YES]; 复制代码
// imagevew.transform=CGAffineTransformConcat(CGAffineTransformMakeScale(0.1, 0.1),CGAffineTransformMakeRotation(M_PI0.75));
[UIView commitAnimations];
或者:
[UIView animateWithDuration:2.0 animations:^{
imagevew.transform=CGAffineTransformConcat(CGAffineTransformMakeScale(0.1, 0.1),CGAffineTransformMakeRotation(M_PI0.75));} completion:^(BOOL finished){}];
The transform property is absolute. If you want relative rotation from the current position you’ll either need to keep track of the absolute rotation for your button and use your existing method (which would probably be faster), or concatenate the new rotation into the existing rotation. Below is the code for concatenating rotation matrices.
9.取UITableViewCell中的子控件:
cell.contentView.subviews[index];
10.通过addChildViewController添加子视图
DetailsViewController *details = [[DetailsViewController alloc] init];
// details.photo = self.photo;
// details.delegate = self;
[self addChildViewController:details];
CGRect frame = self.view.bounds;//设置一下在父视图中的位置
frame.origin.y = 110;
details.view.frame = frame;
[self.view addSubview:details.view];
[details didMoveToParentViewController:self];//通知一下子视图,已被添加到了父视图
复制代码
- 返回当前application的代理,这样就可以访问在appdelegate.m中添加的属性及方法
+ (instancetype)sharedDelegate
{
return [UIApplication sharedApplication].delegate;
}
复制代码
12.数组的排序:
[self.photos sortedArrayUsingComparator:^NSComparisonResult(Photo *photo1, Photo *photo2) {
return [photo2.creationDate compare:photo1.creationDate];
}];
复制代码
13.readArchive能用代码:
NSURL *archiveURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"photodata" withExtension:@"bin"];
NSAssert(archiveURL != nil, @"Unable to find archive in bundle.");
NSData *data = [NSData dataWithContentsOfURL:archiveURL options:0 error:NULL];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
// _users = [unarchiver decodeObjectOfClass:[NSArray class] forKey:@"users"];
// _photos = [unarchiver decodeObjectOfClass:[NSArray class] forKey:@"photos"];
[unarchiver finishDecoding];
复制代码
14.用在xib对应的view里,可以返回当前view的UINib对象
+ (UINib *)nib
{
return [UINib nibWithNibName:@"PhotoCell" bundle:nil];
}
复制代码
用法 :
self.tableView.dataSource = self.photosArrayDataSource;
[self.tableView registerNib:[PhotoCell nib] forCellReuseIdentifier:PhotoCellIdentifier];
复制代码
这样在
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:self.cellIdentifier
forIndexPath:indexPath]; //这里可以直接用了,下面就不用再出队后判断cell是否为空,就可以直接用了.
id item = [self itemAtIndexPath:indexPath];
self.configureCellBlock(cell, item);
return cell;
}
复制代码
14.要把UI类的UI操作部分和业务操作部分分开,可以将他们放在不同的分类中:
如:将它的UI操作部分放在PhotoCell.m中
@implementation PhotoCell
+ (UINib *)nib
{
return [UINib nibWithNibName:@"PhotoCell" bundle:nil];
}
- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated
{
[super setHighlighted:highlighted animated:animated];
if (highlighted) {
self.photoTitleLabel.shadowColor = [UIColor darkGrayColor];
self.photoTitleLabel.shadowOffset = CGSizeMake(3, 3);
} else {
self.photoTitleLabel.shadowColor = nil;
}
}
@end
复制代码
而将其与业务相关的操作放在PhotoCell+ConfigureForPhoto.m中:
#import "PhotoCell+ConfigureForPhoto.h"
#import "Photo.h"
@implementation PhotoCell (ConfigureForPhoto)
- (void)configureForPhoto:(Photo *)photo
{
self.photoTitleLabel.text = photo.name;
self.photoDateLabel.text = [self.dateFormatter stringFromDate:photo.creationDate];
}
- (NSDateFormatter *)dateFormatter
{
static NSDateFormatter *dateFormatter;
if (!dateFormatter) {
dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.timeStyle = NSDateFormatterMediumStyle;
dateFormatter.dateStyle = NSDateFormatterMediumStyle;
}
return dateFormatter;
}
@end
复制代码
- Because shadow is an effect done outside the View, and that masksToBounds set to YES will tell the UIView not to draw everything that is outside itself.
self.photoTitleLabel.layer.masksToBounds=NO;这里设置为NO的时候,才能看到阴影效果
self.photoTitleLabel.layer.cornerRadius = 5.0;
self.photoTitleLabel.layer.shadowPath = [UIBezierPath bezierPathWithRoundedRect:self.photoTitleLabel.bounds cornerRadius:3.0f].CGPath;
self.photoTitleLabel.layer.shadowColor = [[UIColor blackColor] CGColor];
self.photoTitleLabel.layer.shadowOpacity = 1.0;//这一句很关键,默认是0,也就是说是透明的,所以看不到
self.photoTitleLabel.layer.shadowRadius = 10.0;
self.photoTitleLabel.layer.shadowOffset = CGSizeMake(3.0f, 3.0f);
复制代码
当要设置阴影的时候,最好用两个层:
UIView *view1 = [[UIView alloc] init];
UIView *view2 = [[UIView alloc] init];
view1.layer.cornerRadius = 5.0;
view1.layer.masksToBounds = YES;
view2.layer.cornerRadius = 5.0;
view2.layer.shadowColor = [[UIColor blackColor] CGColor];
view2.layer.shadowOpacity = 1.0;//这一句很关键,默认是0,也就是说是透明的,所以看不到
view2.layer.shadowRadius = 10.0;
view2.layer.shadowOffset = CGSizeMake(0.0f, 0.0f);
[view2 addSubview:view1];
[view1 release];
复制代码
16.一个用于输入email地址的textfield
_emailTextField = [UITextField new];
_emailTextField.borderStyle = UITextBorderStyleRoundedRect;
_emailTextField.font = [UIFont boldSystemFontOfSize:16];
_emailTextField.placeholder = NSLocalizedString(@"Email address", nil); //用于本地方字符串
_emailTextField.keyboardType = UIKeyboardTypeEmailAddress;
_emailTextField.autocapitalizationType = UITextAutocapitalizationTypeNone;
复制代码
SEL action2 = @selector(action2:);
[object performSelector:action2 withObject:data afterDelay:1.f]; 延迟执行一个方法
复制代码
用NSInvocation來作為object performSelector的替代方案 – Green
18.这也不能算是一个经验了,重写父类的方法,来加入自己的代码
//继承UITableViewCell ,重写 initWithStyle:reuseIdentifier: ,来加入自己的初始化代码.
@class UserViewModel;
@interface UserCell : UITableViewCell
@property (nonatomic) UserViewModel *viewModel;
@end
@implementation UserCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self != nil) {
RAC(self.imageView, image) = RACObserve(self, viewModel.avatarImage);
RAC(self.textLabel, text) = [RACObserve(self, viewModel.name) ignore:nil];
}
return self;
}
@end
复制代码
- NSObject performSelectorInBackground:withObject: method的应用
/*
* Start a task on a background thread
* by NSObject performSelectorInBackground:withObject: method.
*/
- (void) launchThreadByNSObject_performSelectorInBackground_withObject
{
[self performSelectorInBackground:@selector(doWork) withObject:nil];
}
/*
* A method to be executed on a background thread.
*/
- (void) doWork
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
/*
* Here, processing a time-consuming task,
* such as AR image processing,
* database accessing, etc.
*/
/*
* The task is completed. Next, use the result on the main thread as follows.
*/
[self performSelectorOnMainThread:@selector(doneWork)
withObject:nil waitUntilDone:NO];
[pool drain];
}
/*
* A method to be executed on the main thread.
*/
- (void) doneWork
{
/*
* A task that can work only on the main thread should be here,
* such as updating user interface, etc.
*/
}
复制代码
20.在MRC的情况下NSAutorelease Pool object,最好用drain方法来销毁
When you’d like to release the NSAutorelease Pool object, calling “drain” instead of
“release” is recommended. By “drain” the pool is released immediately even in an environment
with garbage collection enabled. If garbage collection is not used, there is no problem in simply
using “release.
复制代码
21.iOS Http URL Cache清除
[[NSURLCache sharedURLCache] removeAllCachedResponses];
[[NSURLCache sharedURLCache] setDiskCapacity:0];
[[NSURLCache sharedURLCache] setMemoryCapacity:0];
其实只需要第一行即可。
UIWebView中的cache也可以用此方法清除, 所有通过URL Loading System缓存的数据都可以清除。
复制代码
22.resignFirstResponder for all textfields
[self.view endEditing:YES];
This will hide keyboard if its presented due to a subview of your self.view
复制代码
23.webView加载本地的html文件
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"index" ofType:@"html" inDirectory:@"html"]];
NSString *URLString = [url absoluteString];
NSString *queryString = @"?param1=1";
NSString *URLwithQueryString = [URLString stringByAppendingString: queryString];
NSURL *finalURL = [NSURL URLWithString:URLwithQueryString];
NSURLRequest *request = [NSURLRequest requestWithURL:finalURL cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:(NSTimeInterval)10.0 ];
[web loadRequest:request];
复制代码
24.UIApplicationDidBecomeActiveNotification
You get this notification if your app was interrupted by a phone call or push notification. Generally, if your application is getting active on screen after interruption.
UIApplicationWillResignActiveNotification will be called when a phone call comes in. though. If you answer the call, only then will UIApplicationDidEnterBackgroundNotification be posted.
- NSString*s=[NSString stringWithFormat:@”已上传 %.02f%%”,x.floatValue *100.0]; 注意 格式字符串中的%%