iOS开发 容易犯错的知识点和不错的细小知识点(持续更新)

1.UIView下,UIImageView和UILabel的 userInteractionEnabled 默认是NO,要相应交互,就要设置为YES
透明的UIView遮挡住了SuperView,使SuperView不能响应点击事件怎么办?把UIView的userInteractionEnabled属性设置为NO啊。


2.如果点击一个父视图上的子视图没有反应,有两种情况:第一种就是上面的第一点,第二种就是父视图或子视图没有给frame---与---父视图的frame给错了,给小了之类的


3.协议三部曲:接入协议--->设置代理--->实现协议方法


4.NSString 转换成NSData 对象 
NSData* xmlData = [@"testdata" dataUsingEncoding:NSUTF8StringEncoding]; 


5.NSData 转换成NSString对象 
NSData * data; 
NSString *result = [[NSString alloc] initWithData:data  encoding:NSUTF8StringEncoding]; 

6.UITableView的刷新
 #pragma mark - 数据发生改变后一定要重新刷新数据
- (void)viewWillAppear:(BOOL)animated{

    [super viewWillAppear:animated];
    /**
     *  clearsSelectionOnViewWillAppear
     *  这个是它的一个属性,默认是yes 返回列表页面的时候,默认取消这行的选中状态,可是我们已经把这条数据删除的话,会出问题
     *  如果你点击了一行cell,进入下一个页面,在这个页面中,我们把本该属于这行cell的数据给删了
     *  如果  self.clearsSelectionOnViewWillAppear = yes,返回前一页时,会刷新这一行cell,执行cellForRow方法,结果数据却没了,就崩溃了
     *  如果  self.clearsSelectionOnViewWillAppear = no,不会刷新这一行cell,就没事儿了
     */
   self.clearsSelectionOnViewWillAppear =NO;
    [self.tableView reloadData];---->并不一定要放在这里,看取得数据在什么位置,刷新数据在什么位置
}

7.awakeFromNib(storyboard)和 viewDidLoad的区别
awakeFromNib
      当.nib文件被加载的时候,会发送一个awakeFromNib的消息到.nib文件中的每个对象,每个对象都可以定义自己的 awakeFromNib函数来响应这个消息,执行一些必要的操作。也就是说通过nib文件创建view对象是执行awakeFromNib 。
viewDidLoad
      当view对象被加载到内存是就会执行viewDidLoad,所以不管通过nib文件还是代码的方式创建对象都会执行viewDidLoad。awakeFromNib和viewDidLoad的区别



8.将汉字转换为不带音调的拼音
- (NSString *)transformMandarinToLatin:(NSString *)string
{
    NSMutableString *preString = [string mutableCopy];
    /*转换成成带音 调的拼音*/
    CFStringTransform((CFMutableStringRef)preString, NULL, kCFStringTransformMandarinLatin, NO);
    /*去掉音调*/
    CFStringTransform((CFMutableStringRef)preString, NULL, kCFStringTransformStripDiacritics, NO);
    return preString;
}

9.图片适应问题
有两个view: view1,view2
view2添加view1到中,如果view2大于view1,或者view2的坐标不全在view1的范围内,view2是盖着view1的,意思就是超出的部份也会画出来

UIView有一个属性,clipsTobounds 默认情况下是NO。
如果,我们想要view2把超出的那部份隐藏起来的话,就得改变它的父视图也就view1的clipsTobounds属性值。
view1.clipsTobounds = YES;


10.第三方FMDB数据库操作问题

Unknown error finalizing or resetting statement (5: database is locked)
在使用fmdb时有时候一不小心没写好代码就会这样子啦,为什么呢,其实呢,应该是在前面代码中有调用数据库而且并没有调用[db close]就直接跳出结果来了,所以在前面的数据库操作中先运行[db close]再返回数据即可;

通过注册键盘显示的消息
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShown:)
name:UIKeyboardWillShowNotification object:nil];

- (void)keyboardWillShown:(NSNotification*)aNotification{
    // 键盘信息字典
    NSDictionary* info = [aNotification userInfo];
}

11. 改变导航栏中间标题颜色

 UIColor * color = [UIColor whiteColor];
    NSDictionary * dict = [NSDictionary dictionaryWithObject: colorforKey:NSForegroundColorAttributeName];
    self.navigationController.navigationBar.titleTextAttributes = dict;

12.UIWebView要实现横向滑动,跟UIWebview的增高没有关系,你需要设定UIWebView的属性scrollView的contentsize.width大于UIWebView的frame.size.width.

13.如何监测系统键盘的弹出

通过注册键盘显示的消息
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShown:)
name:UIKeyboardWillShowNotification object:nil];

- (void)keyboardWillShown:(NSNotification*)aNotification{
    // 键盘信息字典
    NSDictionary* info = [aNotification userInfo];
}

14.改变状态栏颜色

在Info.plist 添加
UIViewControllerBasedStatusBarAppearance, 设置值为 NO
然后再didFinishLaunchingWithOptions的AppDelegate, 添加这些代码:

[application setStatusBarHidden:NO];[application setStatusBarStyle:UIStatusBarStyleLightContent];


15.路径截取字符串的一些处理

// 从路径中获得完整的文件名(带后缀)     
exestr = [filePath lastPathComponent]; 

// 获得文件名(不带后缀) 
exestr = [exestr stringByDeletingPathExtension];     

// 获得文件的扩展类型(不带'.') 
exestr = [filePath pathExtension]; 


16.clipsToBounds 属性默认值变成NO了

引发的问题例如:

1、到 Xcode 5.1, iOS SDK 7.1 后,TableView Cell clipsToBounds 属性默认都是NO,导致以前用的把cell的height设为0来隐藏某个cell的方法没用了。cell内容会叠起来。 解决方法就是手动把clipsToBounds改YES,或者Storyboard里Clip Subview打勾。

2、UILabel的cornerRadius失效导致背景无法圆角,解决办法也是设置label的clipsToBounds为YES。


17.第三方库不支持64位造成编译错误

Xcode升级到5.1,apple默认让所有app都通过64位编译器编译。通过下面的方式可以关闭: 选中Targets—>Build Settings—>Architectures。双击Architectures,选择other,删除$(ARCH_STANDARD)(点’-’),然后增加armv7和armv7s(点‘+’)。clean一下再编译就行了。


18.移动导航栏的方法:

#import <QuartzCore/QuartzCore.h>

#define kNavBarDefaultPosition CGPointMake(160, 22)

        if (contentOffsetY > _scrollViewContentOffsetYThreshold) {
            layer.position = CGPointMake(layer.position.x,
          22 - MIN((contentOffsetY - _scrollViewContentOffsetYThreshold), 48.0));
        }
        else
        {
            layer.position = kNavBarDefaultPosition;  
        }

19.CGRect的一些相关方法:

    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(100, 120, 120, 120)];
    // 获取矩形左边缘的x坐标
    NSLog(@"MinX = %f",CGRectGetMinX(view.frame));
    // 获取矩形顶部的y坐标
    NSLog(@"MinY = %f",CGRectGetMinY(view.frame));
    // 获取矩形中心点的坐标
    NSLog(@"MidX = %f",CGRectGetMidX(view.frame));
    NSLog(@"MidY = %f",CGRectGetMidY(view.frame));
    // 获取矩形右边缘的x坐标
    NSLog(@"MaxX = %f",CGRectGetMaxX(view.frame));
    // 获取矩形底部的y坐标
    NSLog(@"MaxY = %f",CGRectGetMaxY(view.frame));

    // 返回手势在一个UIView上的触摸点坐标
    - (CGPoint)locationInView:(UIView *)view:
    // 判断矩形是否包含了一个点
    NSLog(@"isRectContainPoint = %d",CGRectContainsPoint(view.frame, CGPointMake(160, 180)));


2. CGRectInset CGRect CGRectInset (  
CGRect rect,  
CGFloat dx,  
CGFloat dy  
);  
该结构体的应用是以原rect为中心,再参考dx,dy,进行缩放或者放大。  
CGRect r1 = CGRectMake(100, 100, 50, 50);  
CGRect r3 = CGRectInset(r1, 10, 8);//结果应为:110,108,30,34 具体小多少都是要参照dx和dy来判定的。  
  
3、CGRectOffset CGRect CGRectOffset(  
CGRect rect,  
CGFloat dx,  
CGFloat dy  
); 相对于源矩形原点rect(左上角的点)沿x轴和y轴偏移, 再rect基础上沿x轴和y轴偏移  
float offset = 125.0;  
CGRect r1 = CGRectMake(100, 100, 5, 5);  
CGRect r2 = CGRectOffset(r1, offset, offset);  
结果:  
 {{225, 225}, {5, 5}}  

// 将像素point由point所在视图转换到目标视图view中,返回在目标视图view中的像素值
- (CGPoint)convertPoint:(CGPoint)point toView:(UIView *)view;
// 将像素point从view中转换到当前视图中,返回在当前视图中的像素值
- (CGPoint)convertPoint:(CGPoint)point fromView:(UIView *)view;

// 将rect由rect所在视图转换到目标视图view中,返回在目标视图view中的rect
- (CGRect)convertRect:(CGRect)rect toView:(UIView *)view;
// 将rect从view中转换到当前视图中,返回在当前视图中的rect
- (CGRect)convertRect:(CGRect)rect fromView:(UIView *)view;

例把UITableViewCell中的subview(btn)的frame转换到 controllerA中

// controllerA 中有一个UITableView, UITableView里有多行UITableVieCell,cell上放有一个button
// 在controllerA中实现:
CGRect rc = [cell convertRect:cell.btn.frame toView:self.view];
或
CGRect rc = [self.view convertRect:cell.btn.frame fromView:cell];
// 此rc为btn在controllerA中的rect

或当已知btn时:
CGRect rc = [btn.superview convertRect:btn.frame toView:self.view];
或
CGRect rc = [self.view convertRect:btn.frame fromView:btn.superview];

20.弱引用的几种写法

__weak __typeof(&*self)weakSelf = self;
__weak __typeof(self) weakSelf = self;
__weak XxxViewController *weakSelf = self;
__weak id weakSelf = self;

21.CGImageRef与UIImage的互转
CGImage和CGImageRef这两个应当是用来重绘图形的类,它们在应用时是按照图像的像素矩阵来绘制图片的,它们可以用来处理bitmap。

CGImageRef与UIImage的互转

 

CGImageRef转换成UIImage CGImageRef

iOffscreen = CGBitmapContextCreateImage(context);

UIImage* image = [UIImage imageWithCGImage: iOffscreen];

 

UIImage转换成CGImageRef

UIImage *loadImage=[UIImage imageNamed:@"comicsplash.png"];

CGImageRef cgimage=loadImage.CGImage;


22.jpg和png图片存储沙盒
NSData *data;

        if (UIImagePNGRepresentation(image) == nil) {

            data = UIImageJPEGRepresentation(image, 1);

        } else {

            data = UIImagePNGRepresentation(image);

        }

UIImagePNGRepresentation转换PNG格式的图片为二进制,如果图片的格式为JPEG则返回nil;
 [fileManager createFileAtPath:[filePath stringByAppendingString:@"/image.png"] contents:data attributes:nil];    将图片保存为PNG格式

 [fileManager createFileAtPath:[filePath stringByAppendingString:@"/image.jpg"] contents:data attributes:nil];   将图片保存为JPEG格式



我们也可以写成下面的格式存储图片

NSString *pngImage = [filePath stringByAppendingPathComponent:@"Documents/image.png"];

NSString *jpgImage = [filePath stringByAppendingPathComponent:@"Documents/image.jpg"];



[data writeToFile:pngImage atomically:YES];

[data writeToFile:jpgImage atomically:YES];


23.UIBtton上字体大小
 button.titleLabel.font = [UIFont systemFontOfSize: 28.0];

24.两个经纬度之间的相对距离
 CLLocation *orig=[[CLLocation alloc] initWithLatitude:[mainDelegate.latitude_self doubleValue]  longitude:[mainDelegate.longitude_self doubleValue]];  
 CLLocation* dist=[[CLLocation alloc] initWithLatitude:[tmpNewsModel.latitude doubleValue] longitude:[tmpNewsModel.longitude doubleValue]];  
      
 CLLocationDistance kilometers=[orig distanceFromLocation:dist]/1000;  
 NSLog(@"距离:",kilometers);  

25.真机调试错误
最近开发iPhone程序,获得开发签名后在真机器上部署测试,在点击Build And Run后,提示The executable was signed with invalid entitlements.(The entitlements specified in your application’s Code Signing Entitlements file do not match those specified in your provisioning profile.)错误->(0xE8008016),没有发布成功。在网上查询资料后,按照其中一个方法成功解决了此问题,具体如下:
 
第一步:在工程中添加文件new file,选择Code Signing 中的Entitlements,添加后名称为Entitlements.plist。
 
第二步:点击Entitlements.plist进行编辑,删除所有Root下的Key,然后添加一个Boolean类型,名称为get-task-allow的Key,状态为CHECKED
 
第三步:在Targets中的Info中的Build选项卡中的Code Signing Entitlements的值设为Entitlements.plist,重新Build即可解决


26.获取视频的第一帧图片
+ (UIImage *)getFirstFrameOfVideoWithVideoURL:(NSURL *)videoURL
{
    AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:videoURL options:nil];
    NSParameterAssert(asset);
    AVAssetImageGenerator *assetIG = [[AVAssetImageGenerator alloc] initWithAsset:asset];
    
    assetIG.appliesPreferredTrackTransform = YES;
    assetIG.apertureMode = AVAssetImageGeneratorApertureModeEncodedPixels;
    
    CGImageRef thumbnailImageRef = NULL;
    CFTimeInterval thumbnailImageTime = 60;
    NSError *igError = nil;
    thumbnailImageRef = [assetIG copyCGImageAtTime:CMTimeMake(thumbnailImageTime, 60) actualTime:NULL error:&igError];
    
    if (!thumbnailImageRef)
        NSLog(@"thumbnailImageGenerationError %@", igError );
    
    UIImage *thumbnailImage = thumbnailImageRef ? [[UIImage alloc] initWithCGImage:thumbnailImageRef] : nil;
    
    return thumbnailImage;
}

27.storyboard中放置ScrollView无法滚动的情况
很多人想到的可能是取消AutoLayout,这样确实能滑动,但不提倡这样做,应该:
- (void)viewDidLayoutSubviews
{    
    [super viewDidLayoutSubviews];
    self.mScrollView.frame = CGRectMake(0, 0, kScreenWidth, kScreenHeight);
    self.mScrollView.contentSize = CGSizeMake(kScreenWidth, 568);   
}

- (void) viewDidAppear:(BOOL)animated
{
       self.scrollView.frame = CGRectMake(0, 0, 320, 480);
       [self.scrollView setContentSize:CGSizeMake(320, 1000)];
}

我觉得,目测是storyboard中默认使用的AutoLayout会使得scrollview重置为CGRectZero

28.16进制颜色转UIColor
+ (UIColor *)colorFromHexString:(NSString *)hexString
{
    
    if ([[hexString substringToIndex:1] isEqualToString:@"#"]) {
        hexString = [hexString substringFromIndex:1];
    }
    
    unsigned rgbValue = 0;
    NSScanner *scanner = [NSScanner scannerWithString:hexString];
    [scanner scanHexInt:&rgbValue];
    
    return [UIColor colorWithRed:((rgbValue & 0xFF0000) >> 16)/255.0 green:((rgbValue & 0xFF00) >> 8)/255.0 blue:(rgbValue & 0xFF)/255.0 alpha:1.0];
}

29.按对应的尺寸缩放图片
+ (UIImage *)compressImage:(UIImage *)imgSrc withSize:(CGSize)size
{
    UIGraphicsBeginImageContext(size);
    CGRect rect = {{0,0}, size};
    [imgSrc drawInRect:rect];
    UIImage *compressedImg = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return compressedImg;
}


30.gif图片转化成一个存储image对象的数组
frame(帧):一个gif可以简单认为是多张image组成的动画,一帧就是其中一张图片image.

frameCount(帧数): 就是一个gif有多少帧

loopCount(播放次数):有些gif播放到一定次数就停止了,如果为0就代表gif一直循环播放。

delayTime(延迟时间):每一帧播放的时间,也就是说这帧显示到delayTime就转到下一帧。

 
所以gif播放主要就是把每一帧image解析出来,然后每一帧显示它对应的delaytime,然后再显示下一张。如此循环下去。

 
下面是纯粹实现由系统提供的解码:

-(void)decodeWithFilePath:(NSString *)filePath

{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^() {

        NSData *data = [NSData dataWithContentsOfFile:self.path];

        [self decodeWithData:data];

    });

}

-(void)decodeWithData:(NSData *)data
{
    CGImageSourceRef src = CGImageSourceCreateWithData((CFDataRef) data, NULL);
    if (src)
    {
        //获取gif的帧数
        NSUInteger frameCount = CGImageSourceGetCount(src);
        //获取GfiImage的基本数据
        NSDictionary *gifProperties = (NSDictionary *) CGImageSourceCopyProperties(src, NULL);
        if(gifProperties)
        {
            //由GfiImage的基本数据获取gif数据
            NSDictionary *gifDictionary =[gifProperties objectForKey:(NSString*)kCGImagePropertyGIFDictionary];
            //获取gif的播放次数
            NSUInteger loopCount = [[gifDictionary objectForKey:(NSString*)kCGImagePropertyGIFLoopCount] integerValue];
            for (NSUInteger i = 0; i < frameCount; i++)
            {
                 //得到每一帧的CGImage
                CGImageRef img = CGImageSourceCreateImageAtIndex(src, (size_t) i, NULL);
                if (img)
                {
                    //把CGImage转化为UIImage
                    UIImage *frameImage = [UIImage imageWithCGImage:img];
                    //获取每一帧的图片信息
                    NSDictionary *frameProperties = (NSDictionary *) CGImageSourceCopyPropertiesAtIndex(src, (size_t) i, NULL);
                    if (frameProperties)
                    {
                        //由每一帧的图片信息获取gif信息
                        NSDictionary *frameDictionary = [frameProperties objectForKey:(NSString*)kCGImagePropertyGIFDictionary];
                        //取出每一帧的delaytime
                        CGFloat delayTime = [[frameDictionary objectForKey:(NSString*)kCGImagePropertyGIFDelayTime] floatValue];

                       //TODO 这里可以实现边解码边回调播放或者把每一帧image和delayTime存储起来
                        CFRelease(frameProperties);
                    }
                    CGImageRelease(img);
                }
            }
            CFRelease(gifProperties);
        }
        CFRelease(src);
    }    
}

31.NSCountedSet 统计重复元素的个数
可能你会发现这个类的父类是NSMutableSet。纳尼?不是说NSMutableSet是不可以储存重复对象的吗。其实NSCountedSet也是不能储存重复的对象的,查看Apple文档中对这个类的描述有这么一句:

Each distinct object inserted into an NSCountedSet object has a counter associated with it.
插入NSCountedSet对象的每个不同的对象都有一个与之相关的计数器

也就是说如果遇到重复对象的加入,这个对象的计数器就会+1。所以可以到这个类有个名叫
- (NSUInteger)countForObject:(id)object    的方法来统计重复对象的个数。
NSArray *array = @[@1, @2, @2, @1];
NSCountedSet *set = [[NSCountedSet alloc]initWithArray:array];
    
[set enumerateObjectsUsingBlock:^(id obj, BOOL *stop) {
	NSLog(@"%@ => %d", obj, [set countForObject:obj]);
}];


32.导航条返回键带的title太讨厌了,怎么让它消失
[[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(0, -60)
                                                     forBarMetrics:UIBarMetricsDefault];


33.截屏转化为image
UIGraphicsBeginImageContext(self.view.bounds.size);

 [self.view.layer renderInContext:UIGraphicsGetCurrentContext()];

 UIImage *image= UIGraphicsGetImageFromCurrentImageContext();

 UIGraphicsEndImageContext();

 UIImageWriteToSavedPhotosAlbum(image, self, nil, nil);
- (UIImage *)creatImageWithView:(UIView *)view rect:(CGRect)rect
{
    CGSize size = view.bounds.size;
    UIGraphicsBeginImageContextWithOptions(size, NO, 0);
    [view.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    CGImageRef viewImageRef = viewImage.CGImage;
    CGImageRef imageRef = CGImageCreateWithImageInRect(viewImageRef, rect);
    
    UIImage *image = [[UIImage alloc] initWithCGImage:imageRef];
    CGImageRelease(imageRef);
    return image;
}




34.仿射变化:旋转角度
- (double)radians:(double)degress
{
    return degress * M_PI/180;
}


  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
uni-app是一个使用Vue.js开发所有前端应用的框架,支持iOS、Android、Web及各平台小程序。它提供了一种统一的开发语法和组件库,使得开发者可以使用一套代码编写多个平台的应用。在uni-app开发微信小程序时,有一些重要的知识点需要掌握。 首先,了解uni-app的基本概念和使用方法是非常重要的。uni-app采用了类似于Vue.js的开发方式,需要熟悉Vue.js的基本语法和组件使用方法。同时,需要了解uni-app的特殊生命周期和内置事件,以及如何在uni-app中使用Vue.js的插件和库。 其次,熟悉uni-app提供的组件和API也是非常重要的。uni-app提供了一套丰富的组件和API,用于构建小程序的界面和功能。比如,uni-app提供了页面跳转、请求数据、上传文件、分享等常用功能的API。此外,uni-app还可以通过集成第三方的UI组件库,如Vant组件,来提高开发效率和用户体验。 另外,uni-app还支持使用预处理器来编写样式,其中官方推荐使用scss。在uni-app中使用scss可以帮助开发者更方便地管理和维护样式代码。 总结起来,uni-app完成小程序开发的重要知识点包括:掌握uni-app的基本概念和使用方法、熟悉uni-app提供的组件和API、了解如何使用Vue.js的插件和库、熟悉使用scss进行样式编写。通过掌握这些知识点开发者可以更高效地开发和维护uni-app小程序应用。<span class="em">1</span><span class="em">2</span><span class="em">3</span>

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值