iOS开发200个tips总结(一)

      工作了两年多,一直有个“坏习惯”,就是将工作中遇到的一些问题、技巧或心得记在印象笔记里面,按理来说,作为一个开发者,要拥抱开源精神,将这些美好的东西分享给大家,或许能够帮助别人解决问题或是引起少许的共鸣。

      简书给我的第一印象是:风格清新,易用,同时也是一个不错的交流技术,交流心得的好平台,趁最近在找工作的空档,抽些时间将印象笔记里面的tips、轮子或技术解决方案移到这里来。

       翻了一下印象笔记的笔记本,咋一看吓一跳,将近一千条笔记!!! 根据80 20 法则,怎么也有200条对一部分人是有参考意义的。这里抽取200条比较有价值的笔记分享出来,希望看完博客的看官能够有所收获。

      PS:因为有些tips是在一个swift项目中收集下来的,所以下面放出的tip既有Objective-C 也有 Swift。由于有些笔记记录的是iOS 6.0时代的一些问题,因此可能存在一些错误的地方,欢迎指正。


tip 1 :  给UIImage添加毛玻璃效果

func blurImage(value:NSNumber) -> UIImage {

      let context = CIContext(options:[KCIContextUseSoftwareRenderer:true])

      let ciImage = CoreImage.CIImage(image:self)

      let blurFilter = CIFilter(name:"CIGassianBlur")

      blurFilter?.setValue(ciImage, forKey:KCIInputImageKey)

      blurFilter?.setValue(value, forKey:"inputRadius")

      let imageRef = context.createCGImage((blurFilter?.outputImage)!, fromRect:(ciImage?.extent)!)

     let newImage = UIImage(CGImage:imageRef)

     return newImage

}

value : value代表毛玻璃效果的程度

核心内容:let blurFilter = CIFilter(name:"CIGassianBlur") 使用滤镜工具


tip 2 : 图片压缩

func imageCompress(targetWidth:CGFloat) -> UIIMage {

        let targetHeight = targetWidth/width*height

       UIGraphicsBeginImageContext(CGSizeMake(targetWidth,targetHeight))

      self.drawInRect(CGRectMake(0,0,targetWidth,targetHeight))

      let newImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()

      UIGrapicsEndImageContext()

      return newImage

}

这里是按原UIImage比例做压缩所以:let targetHeight = targetWidth/width*height


tip 3 : SVN & Git 用法总结

一:SVN

A. 项目经理:1.创建项目—CheckIn

2.设置项目人员

B.工作人员:1.CheckOut 获取项目的完整副本,此工作只需要做"一次"

2. 工作写代码....

3.阶段性工作完成后,Commit(提交) 将自己修改的文件,上传到服务器

每天下班前一定要做一次能够编译的提交!

4.定期Update项目,从服务器将最新的内容更新到本地,每天上班第一件事情一定要做的事情!

二. Git

A.项目经理:1.创建项目push

2.设置项目人员

B. 工作人员:1.Pull从服务器下拉最新的本版

2.Commit是将修改过的代码提交至本地的代码库

3.每天下班前Push自己当前的代码到服务器

4.每天上班前从服务器Pull最新的内容

三. M / A 文件更新

对于文件夹svn支持并不好,需要在工具下选定文件夹commit

对应文件选定文件commits

由于过去在公司多半时间是做独立开发,最多人的时候也是两个人做开发,所以协作工具用的少,但是不断的关注着两种代码仓库管理工具,总结了一些tip,还有待实践验证,吐槽吧......


tip 4:  UINavigationController下的坐标系

iOS 9 前:

navigationBar 如果设置了背景图片,那么可视化坐标会从navgationbar下面开始

self.navigationController?.navigationBar.setBackgroundImage(UIImage(named:"nav"), forBarMetrics:UIBarMetrics.Default)

iOS 9 后 : 坐标从状态栏下面开始


tip 5 : C字符串转成NSString &  NSString转成C字符串


const char *cString = "CString";

C字符串转成NSString : NSString *str = [NSString stringWithUTF8String:cString];


NSString * str = @"NSString";

NSString转成C字符串 : const char *cString = [str UTF8String];


tip 6 : OC & Swift 代码块(语法糖)

Objective-C :

UILabel *label1 = ({

       UILabel *label = [UILabelnew];

       [self.view addSubview:label];

       label.frame=CGRectMake(100,100,100,45);

       label.backgroundColor= [UIColor redColor];

       label.text=@"大家好1";

      label;

});

UILabel*label2 = ({

       UILabel*label = [UILabel new];

       [self.view addSubview:label];

       label.frame=CGRectMake(100,160,100,45);

       label.backgroundColor= [UIColor redColor];

       label.text=@"大家好2";

       label;

});

UILabel*label3 = ({

       UILabel*label = [UILabel new];

       label.frame=CGRectMake(100,250,100,45);

       label.backgroundColor= [UIColor redColor];

       label.text=@"大家好3";

       label;

});

[self.viewaddSubview:label3];

({

       UILabel *label = [UILabel new];

       [self.view addSubview:label];

       label.frame=CGRectMake(100,310,100,45);

       label.backgroundColor= [UIColor redColor];

       label.text=@"大家好4";

});


Swift:

letlabel1:UILabel= {

        let label =UILabel()

        self.view.addSubview(label)

        label.frame=CGRectMake(100,100,100,45)

        label.backgroundColor=UIColor.redColor()

        label.text="大家好"

       return label

}()

let label2:UILabel= {

      let label =UILabel()

      label.frame=CGRectMake(100,200,100,45)

      label.backgroundColor=UIColor.redColor()

      label.text="大家好"

      return label

}()

self.view.addSubview(label2)

使用语法糖的好处就是拷贝代码时只需做少许的修改就可以达到目的,如上面的栗子,想要创建多个label,只要赋值粘贴,改一处,也就是对象名称就可以轻松完成!


tip 7 : 数据持久化方式归纳总结

数据缓存方式选择:

1: fmdata数据库(增删改查)   --数据需要:增删改查

2: coreData                         --数据需要:增删改查

3:序列化(NSUserDefault)    --状态、偏好设置、默认选项

4:单独.plist                         --列表数据,城市信息等

5:单独.json文件                  --页面列表数据

6: realm框架(增删改查)       --数据需要:增删改查

7:  FastCoder  某“强哥”推荐,哈哈哈!


tip 8 : 清理Profiles证书文件

~/Library/MobileDevice/Provisioning Profiles

由于平时会负责多个项目的上线管理或是开发工作,因此MAC中有很多签名文件,有时候都分不清东西南北,一不做,二不休,前往这个目录下,将文件删个精光,调试的时候用到证书再update一下当前项目的证书即可


tip 9 : 拿到当前屏幕所看到的viewController

Objective-c版本:

- (UIViewController *)getAppRootViewController

{

       UIViewController *appRootVC = [UIApplication sharedApplication].keyWindow.rootViewController;

       UIViewController *topVC = appRootVC;

       while (topVC.presentedViewController)  {

             topVC = topVC.presentedViewController;

       }

       return topVC;


Swift版本:

func getAppRootViewController() -> UIViewController? {

       var topVC = UIApplication.sharedApplication().keyWindow?.rootViewController

       while topVC?.presentedViewController != nil {

              topVC = topVC?.presentedViewController

       }

       return topVC?

}


tip 10 : 制作pch文件

步骤:

1、新建iOS->Other->PCH File

2、targets->BuildSetting->Prefix Header->设置$(SRCROOT)/文件在工程中的路径

3、pch能像以前一样正常使用

如:$(SRCROOT)/FirstProject/PrefixHeader.pch

FirstProject : pch路径中的最后一个拓展名

PrefixHeader.pch: 是pch文件名

简介:/Users/ly/Desktop/FirstProject/FirstProject


tip 11 :  设置UINavigationController title

当 UIViewController作为UINavigationController的根视图控制器的时候,将这个Nav(root)赋给 tabBarController时,

这样写:

root.title = @“title”;

那么 :self.naviagtionItem.title 会显示 title

同时 :nav.tabBarItem.title 也会显示  title



tip 12 : 判断UIScrollView是横向滚动还是竖向滚动

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer*)gestureRecognizer {

         if([gestureRecognizerisKindOfClass:[UIPanGestureRecognizerclass]]) {

               CGPointvelocity = [(UIPanGestureRecognizer*)gestureRecognizervelocityInView:gestureRecognizer.view];

               BOOLisHorizontalPanning =fabsf(velocity.x) >fabsf(velocity.y);

               return isHorizontalPanning;

        }

      returnYES;

}


tip 13 : 监听  backBarButtonItem 返回事件

github上搜: UIViewController+BackButtonHandler 开源项目


tip 14 : 让一个view透明度失效

self.view.backgroundColor=UIColor(colorLiteralRed:255.0/255, green:255.0/255, blue:255.0/255, alpha:0.3)

let subView = UIView()

subView.tintColor=UIColor.whiteColor()//不透明了

self.view.addSubview(subView)


tip 15 : 从ipod库中读出音乐文件

// 从ipod库中读出音乐文件

MPMediaQuery *everything = [[MPMediaQuery alloc] init];

// 读取条件

MPMediaPropertyPredicate *albumNamePredicate = [MPMediaPropertyPredicate predicateWithValue:[NSNumber numberWithInt:MPMediaTypeMusic] forProperty: MPMediaItemPropertyMediaType];

[everything addFilterPredicate:albumNamePredicate];

NSLog(@"Logging items from a generic query...");

NSArray *itemsFromGenericQuery = [everything items];

for (MPMediaItem *song in itemsFromGenericQuery) {

      NSString *songTitle = [song valueForProperty: MPMediaItemPropertyTitle];

       NSLog (@"%@", songTitle);

}


tip 16 : 广告标示符(adId) & adfv标示符的那些事

1.如何识别一个应用安装在同一个设备上呢?

2.如何识别一个企业的应用安装在同一个设备上呢?

苹果给我们提供了advertisingIdentifier 来解决问题1;

只要是同一台设备,那么advertisingIdentifier就是一样的

但是如果在设置-隐私-广告那里关掉这个权限或是还原设备的话,就没办法了哭死去吧

苹果给我们提供了identifierForVendor 来作为一个企业的app标示符

比如: com.game.yoyo

com.game.xoxo

只要在同一台设备上,那么identifierForVendor 是一样的

如果:com.game.yoyo

com.buyer.yoyo

不管是不是同一个应用identifierForVendor 都是不一样的

上代码:

广告id:

#import

//每个设备有唯一一个,如果重置广告或设置-隐私-关闭广告就会关闭更换

NSString*adId = [[[ASIdentifierManagersharedManager]advertisingIdentifier]UUIDString];

企业id:

NSString*idfv = [[[UIDevicecurrentDevice]identifierForVendor]UUIDString];



tip 17 : 不使用JPush等的原始推送

一步一步教你做ios推送 - 有梦想的蜗牛 - 博客频道 - CSDN.NET

推送通知iOS客户端编写实现及推送服务器端编写 - OPEN 开发经验库

由于简书的一些限制,不能粘贴文件,考虑选择一个方式将我自己的实践工程放出来,以后持续更新

(MAC下搭建服务器+证书制作+推送测试)


tip 18 : 设置系统音量(排版有段乱,将就一下(⊙﹏⊙)b)

#import"VolumeSetter.h"

#import

@implementationVolumeSetter

{

MPVolumeView*volumeView;

UISlider* volumeViewSlider;

}

+ (instancetype)shareInstance

{

staticVolumeSetter*vs;

staticdispatch_once_tonce;

dispatch_once(&once, ^{

vs = [[VolumeSetteralloc]init];

});

returnvs;

}

- (void)setVolume:(float)value

{

[self getSlider];

[volumeViewSlidersetValue:valueanimated:NO];// send UI control event to make the change effect right now.

[volumeViewSlidersendActionsForControlEvents:UIControlEventTouchUpInside];

}

- (float)getVolume:(volumeBlock)handel

{

_myHandel= handel;

[selfgetSlider];

returnvolumeViewSlider.value;

}

- (MPVolumeView*)getVolumeView

{

if(volumeView==nil) {

volumeView= [[MPVolumeViewalloc]init];

[[NSNotificationCenterdefaultCenter]addObserver:self

selector:@selector(volumeChanged:)

name:@"AVSystemController_SystemVolumeDidChangeNotification"

object:nil];

}

returnvolumeView;

}

- (UISlider*)getSlider

{

[selfgetVolumeView];

for(UIView*viewin[volumeViewsubviews]){

if([view.class.descriptionisEqualToString:@"MPVolumeSlider"]){

volumeViewSlider= (UISlider*)view;break;

}

}

returnvolumeViewSlider;

}

- (void)volumeChanged:(NSNotification*)notification

{

floatvolume =

[[[notificationuserInfo]

objectForKey:@"AVSystemController_AudioVolumeNotificationParameter"]

floatValue];

NSLog(@"current volume = %f", volume);

_myHandel(volume);

}

@end


tip 19 : 提高开发效率 开发工具(转)

http://www.cocoachina.com/ios/20151110/14102.html


tip 20 : XMPP 开发与服务器搭建

待补充

tip 21 :  设置UINavigationItem 返回按钮 和 back title

1. push 之前

// back title

self.navigationItem.backBarButtonItem=UIBarButtonItem(title:"返回", style:UIBarButtonItemStyle.Plain, target:nil, action:nil)

// 特别注意:在push之前设置

self.navigationController?.pushViewController(vc, animated:true)

2.设置颜色

self.navigationController?.navigationBar.tintColor=UIColor.blackColor()

总结:

self.navigationItem.backBarButtonItem=UIBarButtonItem(title:"返回", style:UIBarButtonItemStyle.Plain, target:nil, action:nil)

self.navigationController?.navigationBar.tintColor=UIColor.blackColor()

self.navigationController?.pushViewController(vc, animated:true)


tip 22 :  语法风格

Swift : https://github.com/raywenderlich/swift-style-guide#use-of-self

 OC : https://github.com/raywenderlich/objective-c-style-guide


tip 23 : 谓词

Person类:

@interfacePerson :NSObject

@property(nonatomic) NSUIntager age;

@property(nonatomic,copy)NSString*name;

@end

#import"Person.h"

@implementationPerson

- (NSString*)description

{

return[NSStringstringWithFormat:@"age=%d,name=%@",self.age,self.name];

}

@end

ViewController.m类:

Person*p1 = [[Personalloc]init];

p1.age=15;

p1.name=@"张三";

Person*p2 = [[Personalloc]init];

p2.age=25;

p2.name=@"小米";

Person*p3 = [[Personalloc]init];

p3.age=15;

p3.name=@"李四";

NSArray*arr =@[p1,p2,p3];

//谓词

NSPredicate*pre = [NSPredicatepredicateWithFormat:@"%K==%d || %K==%@ || %K=%@",@"age",15,@"name",@"张三",@"name",@"李四"];

arr = [arrfilteredArrayUsingPredicate:pre];

NSLog(@"%@",arr);

输出:

2015-12-08 11:24:05.862 Predicate[12080:634959] (

"age=15,name=\U5f20\U4e09",

"age=15,name=\U674e\U56db"

)

用于做查询操作非常棒,避免写一大堆的if else操作


tip 24 : Xcode 插件

 VVDocumenter 是一个比较好用的注释控件

Alcatraz(插件管理器)http://www.tuicool.com/articles/v2eIVb

https://github.com/supermarin/Alcatraz

Xcode 6.4找不到packageManager :http://blog.csdn.net/yimu520csdn/article/details/47040041


tip 25 : 微信登录,分享等 不执行代理方法

方法一:

- (BOOL)application:(UIApplication*)application handleOpenURL:(NSURL*)url

{

        return [WXApihandle OpenURL:urldelegate:self];

}

方法二:

- (BOOL)application:(UIApplication*)application openURL:(NSURL*)url sourceApplication:(NSString*)sourceApplication annotation:(id)annotation

{

        return[WXApihandle OpenURL:url delegate:self];

}

今天做微信登陆功能,随手写一个demo,没有设置bundle id , display name,结果就不走 方法一,方法二

导致下面两个代理方法不走

- (void) onReq:(BaseReq*)req{

        NSLog(@"xxxxxxxx");

}

- (void) onResp:(BaseResp*)resp{

        NSLog(@"fffffffff");

}

解决方法:设置Bundle identifier 以及 Bundledisplayname ,注意要与注册获取appid secret key 时所填的保持一致.

当然其他设置也要保证设置上,比如 URL sechme , iOS9 注意适配 ATS,添加白名单


tip 26 :  iOS7.0后隐藏状态栏(UIStatusBar)

现象:

升级到iOS7后,UIStatusBar的出现导致现有UI界面乱掉了。

原因:

由于写死了某些控件的绝对位置,原先隐藏UIStatusBar的代码没有在iOS7中起作用

解决方法:

iOS7以下版本隐藏UIStatusBar的方法:

- (BOOL)application:(UIApplication*)applicationdidFinishLaunchingWithOptions:(NSDictionary*)launchOptions

{

       [application setStatusBarHidden:YES];

       returnYES;

}


升级到iOS7后的方法:

在基类中重载UIViewController.h中的这个方法

- (BOOL)prefersStatusBarHidden NS_AVAILABLE_IOS(7_0);// Defaults to NO

- (BOOL)prefersStatusBarHidden

{

      return YES;

// iOS7后以下方法已经不起作用:   [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationFade];

}


tip 27 : UIColor 转 RGB

UIColor*color = [UIColorcolorWithRed:0.0green:0.0blue:1.0alpha:1.0];

constCGFloat*components =CGColorGetComponents(color.CGColor);

NSLog(@"Red: %f", components[0]);

NSLog(@"Green: %f", components[1]);

NSLog(@"Blue: %f", components[2]);


tip 28 :  抠图 & 合成图片 (转)

iOS开发-简单图片背景替换(实现抠图效果)

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


tip 29 :  Mac 生成UUID 命令: uuidgen

在命令行工具输入 $ uuidgen : 8-4-4-4-12


tip 30 :  23种设计模式

https://github.com/huang303513/Design-Pattern-For-iOS


tip 31 :  发布APP要求

发布APP要求,不能使用Beta版本的Xcode

如果一个开发团队里面有多个小伙伴,不要为了尝新将所有的Mac OX 或是Xcode都升级到Beta版本,应该由一个小伙伴进行测试感受新版本是否稳定,是否有坑,否定后果很严重,说多都是泪,您想想:重新装系统,重新下载Xcode是一件多么苦逼的事情。。。

 

tip 32 : UIScrollView 判断是向左滚动还是向右滚动

这是抄自项目里面的一段代码,如果您要用到判断UIScrollView向左还是向右的滚动逻辑,请先定义相关状态的全局变量

-(void)scrollViewWillBeginDragging:(UIScrollView*)scrollView

{

            startContentOffsetX= scrollView.contentOffset.x;

}\

- (void)scrollViewWillEndDragging:(UIScrollView*)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inoutCGPoint*)targetContentOffset{//将要停止前的坐标

           willEndContentOffsetX= scrollView.contentOffset.x;

}

- (void)scrollViewDidEndDecelerating:(UIScrollView*)scrollView{

       endContentOffsetX= scrollView.contentOffset.x;

       if(endContentOffsetX < willEndContentOffsetX && willEndContentOffsetX < startContentOffsetX) {

               NSLog(@"画面从右往左移动,前一页");

         }else if(endContentOffsetX > willEndContentOffsetX&&

              willEndContentOffsetX > startContentOffsetX) {

              NSLog(@"画面从左往右移动,后一页");

    }

}


tip 33 :  判断是否插入SiM卡

引入:CoreTelephony.framework

extern NSString*constkCTSMSMessageReceivedNotification;

extern NSString*constkCTSMSMessageReplaceReceivedNotification;

extern NSString*constkCTSIMSupportSIMStatusNotInserted;

extern NSString*constkCTSIMSupportSIMStatusReady;

id CTTelephonyCenterGetDefault(void);

void CTTelephonyCenterAddObserver(id,id,CFNotificationCallback,NSString*,void*,int);

void CTTelephonyCenterRemoveObserver(id,id,NSString*,void*);

int CTSMSMessageGetUnreadCount(void);

int CTSMSMessageGetRecordIdentifier(void* msg);

NSString* CTSIMSupportGetSIMStatus();

NSString* CTSIMSupportCopyMobileSubscriberIdentity();

id CTSMSMessageCreate(void* unknow/*always 0*/,NSString* number,NSString* text);

void* CTSMSMessageCreateReply(void* unknow/*always 0*/,void* forwardTo,NSString* text);

void* CTSMSMessageSend(idserver,idmsg);

NSString*CTSMSMessageCopyAddress(void*,void*);

NSString*CTSMSMessageCopyText(void*,void*);

NSLog(@"BOOL:%d", [CTSIMSupportGetSIMStatus()isEqualToString:kCTSIMSupportSIMStatusNotInserted] );


tip 34 :  获取链接的Wifi

#import <SystemConfiguration/CaptiveNetwork.h>

- (id)fetchSSIDInfo {

          NSArray*ifs = (__bridge_transfer id)CNCopySupportedInterfaces();

          NSLog(@"Supported interfaces: %@", ifs);

         id info =nil;

         for (NSString*ifnam in ifs) {

               info = (__bridge_transfer id)CNCopyCurrentNetworkInfo((__bridge CFStringRef)ifnam);

               NSLog(@"%@ => %@", ifnam, info);

              if(info && [info count]) {break; }

       }

         return info;

}


tip 35 :  计算文字宽度、高度

- (CGSize)currentSize{

      CGFloatversion = [[UIDevice currentDevice].systemVersionfloatValue];

    //计算size  7之后有新的方法

     CGSize size;

    if(version>=7.0) {

//得到一个设置字体属性的字典

    NSDictionary*dic = [NSDictionary dictionaryWithObjectsAndKeys:      [UIFontsystemFontOfSize:15],NSFontAttributeName,nil];

//optinos前两个参数是匹配换行方式去计算,最后一个参数是匹配字体去计算

//attributes传入使用的字体

//boundingRectWithSize计算的范围

//_tweetBody是string

   size = [_tweetBody boundingRectWithSize:CGSizeMake(215,999)options:NSStringDrawingTruncatesLastVisibleLine|NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:diccontext:nil].size;

    }else{

//ios7以前

//根据字号和限定范围还有换行方式计算字符串的size

//label中的font和linebreak要与此一致

//CGSizeMake(215,999)横向最大计算到215纵向max 999

    size = [_tweetBodysizeWithFont:[UIFont systemFontOfSize:15]constrainedToSize:CGSizeMake(215,999) lineBreakMode:NSLineBreakByCharWrapping];

   }

    return size;

}


tip 36 :  TableView  UITableViewStylePlain状态去掉省略多余的cell

_tableView= [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];

_tableView.delegate=self;

_tableView.dataSource=self;

_tableView.tableFooterView= [UIView new];  // 关键的一行代码


tip 37 : block  类型声明为strong 还是 copy ?

block声明为strong 和copy什么区别

block变量申明为strong或者copy 在ARC 的情况下 是等效的

但苹果推荐的最佳实践是 使用copy作为block的权限控制符

因为 copy能让开发者更明确地知道 block内存操作的隐式行为

及copy 到heap上

ARC下面 strong修饰的block 会自动进行这一过程

MRC下面 使用copy是必须的


tip 38 :  坐标转换

如果我的tableView的每个cell都有输入框,那我怎么样在输入的时候将对应的输入框移到合适的位置?

每个cell可以拿到在当前table的位置然后转换到屏幕上

然后自己算应该偏移多少

self是一个view  一个是把一个坐标从自己的换到其他的View上

一个是把其他的坐标换到自己上  如果self你当做tableView,然后后面的uiview你用vc.view

就能相互转了


tip 39 : 跳转至指定QQ号码

判断是否安装了QQ:

if([[UIApplication shareApplication]  canOpenURL:[NSURL:URLWithString:@“mqq://“]]){

          NSLog(@“had installed");

} else {

          NSLog(@“no installed");

}

UIWebView*webView = [[UIWebView alloc] initWithFrame:CGRectZero];

NSURL*url = [NSURLURLWithString:@"mqq://im/chat?chat_type=wpa&uin=501863587&version=1&src_type=web"];

NSURLRequest*request = [NSURLRequest requestWithURL:url];

webView.delegate=self;

[webView loadRequest:request];

[self.view addSubview:webView];


tip 40 :  企业版app 与 appStore版app之间的问题

问题一 : 一台手机能否装两个名字一样的应用呢.

回答 : 能否装两个一样的应用不是取决于应用的名字,而是取决于boundid,appId(这个本人还没考究。。。)是否一致。

但是苹果应用商店是不允许有两个名字一样的应用程序的,那我们干嘛要纠结于名字一样的问题呢?

因为如果公司有一个企业账号和一个发布账号,企业账号希望发布一个到官网供用户下载,而发布账号希望发布到AppStore,而且名字一样。

结论是:两个应用同名行不行?行,只要你的企业账号发布的应用的boundid跟AppStore上的应用的app的boundid不一致,名字可以一致。

而且苹果不会管你的企业账号发布的应用程序,你爱怎么玩就怎么玩,如果你不希望一台手机装两个名字一样的应用,那么开发者              只要将两个应用的boundid设置成一样就可以了。

注意:AppStore上不能有同名的应用程序,这个是受商标保护法保护的。但是企业账号就可以任意起名字跟设置boundid。但是嘛,你懂的。。。


tip 41 : 打印 NSHomeDirectory为空

情况:打印获取 NSHomeDirectory为空,打印有值,获取到为nil。。

如果版本是release,就会出现上面的情况

解决的办法 : 设置成 debug

安全的做法是:

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);

NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : NSTemporaryDirectory();


tip 42 :  app跳转到safari

NSURL* url = [NSURL URLWithString:urlStr];

[[UIApplication sharedApplication] openURL:url];


tip 43 :  弹出键盘 & 收键盘

//监听键盘

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyBoardShow:)name:UIKeyboardWillShowNotification object:nil];

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyBoardHide:)name:UIKeyboardWillHideNotification object:nil];

#pragma mark弹出键盘

-(void)keyBoardShow:(NSNotification*)notification

{

//notification.userInfo获得用户的所有信息,userInfo是一个字典,根据key值     为UIKeyboardFrameEndUserInfoKey拿到键盘的frame的“字符串”,将这个字符串转成Rect

        int y = [[notification.userInfoobjectForKey:UIKeyboardFrameBeginUserInfoKey]CGRectValue].size.height;

}

#pragma mark收键盘

-(void)keyBoardHide:(NSNotification*)notification

{

}

最强的收键盘方法 :

[[UIApplicationsharedApplication]sendAction:@selector(resignFirstResponder)to:nilfrom:nilforEvent:nil];

其他的键盘监听 :

[[NSNotificationCenterdefaultCenter]addObserver:selfselector:@selector(keyboardWillChangeFrame:)name:UIKeyboardDidChangeFrameNotificationobject:nil];


tip 44 :  审核加急处理

链接:https://developer.apple.com/appstore/contact/appreviewteam/index.html

备注:到上面的连接填写相关桂东,申请加急的理由:上线的App中有Bug


tip 45 :  iTunesConnect 更新版本接受协议步骤



tip 46 :  No architectures to compile for (ONLY_ACTIVE_ARCH=YES, active arch=x86_64, VALID_ARCHS=i386).

解决的办法是 :

步骤1 :  

步骤2 :


tip 47 :  Version 号 跟Build  号的区别

version 是给用户看的,比如1.0  2.0

Build 是给开发者还有就是苹果 iTunesconnect看的

具体情景:

今天发布一个版本叫 2.0 所以 version 2.0

于是我要archive -> validate -> submit

发布完成了!

正当我们其乐融融的的准备庆祝的时候,屌丝的产品进来大吼一声,肃静,吵什么吵,我看那个搜附近的人页面太烂了!!!!

一万个草泥马在天上飞啊。。。

没事,蛋定,蛋定,改改改。。。

改完之后,发现validate不成功。提示:已经有一个2.0的版本了,怎么破????产品经理坚持要用version 2.0这个数字,但是如果不改成version2.1之类的好像一直都传不上去啊!!!灵光一闪,Build 号是干嘛的?经过一般查证,Build是给我们开发者和itunesconnect看的,改一下Build不就行了吗,改改改,重新validate发现可行,欧耶,submit , 重新选择版本,搞定!!!继续庆祝


tip 48 : Xcode 6中对于图片的要求规格:

1、AppIcon

(1)spotlight iOS 5-6 29*29

setting iOS 5-8 29*29 (1*2*3 三种尺寸)

(2)spotlight iOS 7-8 40*40 (2*3 两种尺寸)

(3)iPhone App iOS 5-6 57*57 (1*2两种尺寸)

(4)iPhone App iOS 7-8 60*60 (2*3两种尺寸)

2、启动图片

Default.png(320*480)

Default@2x.png(640*960)

Default-568h@2x.png(640*1136)

Default-667h@2x.png(750*1334) 4.7寸

Default-736h@3x.png(1242*2208)5.5寸


tip 49 :  清除签名文件 删除签名文件 清理Profile文件

Xcode - Preferences - Account - View Details,这个时候左下角有个刷新图标,点击一下就可以了


tip 50 :  应用内跳转到系统设置页面 (转)

http://code4app.com/ios/DBPrivacyHelper/548e7550933bf031268b4d82


tip 51 :  使用lipo命令合并对应版本 静态库文件

lipo -create /Users/han-zi/Desktop/Release-iphoneos/libbaidumapapi.a  /Users/han-zi/Desktop/Release-iphonesimulator/libbaidumapapi.a -output /Users/han-zi/Desktop/a/libbaidumapapi.a

备注:以百度地图SDK为栗子

真机版本的文件路径: /Users/han-zi/Desktop/Release-iphoneos/libbaidumapapi.a

模拟器版本的文件路径:/Users/han-zi/Desktop/Release-iphonesimulator/libbaidumapapi.a

输出文件路径: /Users/han-zi/Desktop/a/libbaidumapapi.a


tip 52 : 应用在AppStore的地址

webpageUrl=@"http://itunes.apple.com/us/app/id+你的应用id";


tip 53 :  颜色值转RGB

- (void)setBgRGB:(long)rub{

           red = ((float)((rgb & 0xFF0000) >> 16))/255.0;

           green = ((float)((rgb & 0xFF00) >> 8))/255.0;

          blue = ((float)(rgb & 0xFF))/255.0;

}


tip 54 :  App 上线简介

心得体会:

1.准备一个APP ID(这个可以永远用)

2.创建证书

a.创建证书的过程要上传机器标示符(钥匙串——>证书助理——>从证书颁发机构请求证书))

b.要绑定APP ID

c.填写bundleID

d.下载证书

3.生成签名文件——>绑定Bundle ID ——>生成签名文件——>下载签名文件


tip 55 : UIImage加载方式怎么选?

方式一: imageName:有缓存的方式,如果一张图片会被重复用到,那么请用这种方式

方式二:contentOfFile:无缓存的方式,加载大的图片文件,特别注意,jpg图片只能以这种方式加载


tip 56 :  ARC兼容MRC,MRC兼容ARC 设置关键字

ARC兼容MRC : -fno-objc-arc

MRC兼容ARC: -fobjc-arc


tip 57 :  消息推送机制理解

1.应用程序第一次起来的时候询问是否允许消息推送,允许的时候才去注册,

向苹果APNS服务器注册是哪个{应用程序,设备号}

2.注册成功苹果APNS服务器返回一个DeviceToken,程序员要保存这个{DeviceToken}

3.注册失败 。。。。

4.注册成功,将DeviceToken发给服务器{可以是自己的服务器,可以是极光服务器},服务器保存这一大堆的DeviceToken

5.服务器要推送消息{可以是极光服务器}将这个消息发给苹果APNS服务器,APNS服务器根据{一大堆的DevicToken}向应用程序推送消息




tip 58 :  FMDB 事务操作步骤

@try{

启动事务,执行数据库操作

[_dataBase beginTransaction];//手动开启一个事务

}@Catch{

出现问题,数据库回滚

[_dataBase rollback];//回滚,回到最初的状态

}@finally{

数据库提交操作

[_dataBase commit];//提交事务,让批量操作生效

}

备注:FMDB 使用进阶包括两个内容,一个是事务,一个是线程安全,详细内容请看FMDB官方文档。

事务解决的问题: 如果要对数据库进行 多条数据的写操作,应开启事务,而不要只使用for循环直接写入,否则会比较耗时

线程安全解决的问题: 如果对同一资源进行操作,FMDB不是线程安全的,使用FMDataBaseQueue这个类可以做到线程安全。


tip 59 : UITableView重用机制的理解

UITableView自身有一套重用的机制,根据UITaleVIew 的frame的大小和cell.frame大小来计算个数,实际会创建多一个cell,创建的这些cell都放在一个数组(队列的数据结构)里面,视图出现时根据计算的结果将cell拿出来放在UITableView上面,剩下的那个cell则作为缓冲cell,比如向上拖动的时候,cell[0]会放回数组最下面,将那个上次没有使用的cell拿出来,放在TableView下面。利用这种机制来达到重用的目的。

对于拖到到看不见的位置的cell,我们可以对他清除缓存(缓存就是cell.contentView上面的子view),那怎么清除呢?方法很简单

-(UITableViewCell *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

             if(cell ! == nil)

            {

                    NSArray *arr =[ [NSArray alloc] initWithArray :cell.contentView.subviews];

                   for (UIView *subView in arr){

                  [subView removeFromSuperView];

          }

}


tip 60 :  UITableView Cell 清除缓存 说白了就是将将要出现的cell的contentView上面的子视图清除掉或销毁


tableView表格中的cell有重用机制,这是一个很好的东西,可以避免开辟很多的空间内存。但是有时候我们不想让它重用cell,,可以用以下的代码解决。

将这个代码放在:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ 

           // 这个函数中执行就好了。

           //清楚cell的缓存

           NSArray *subviews = [[NSArray alloc] initWithArray:cell.contentView.subviews];

           for(UIView *subview in subviews) {

           [subview removeFromSuperview];

}


tip 61 :  改变tabBarItem字体颜色

self.tabBar.tintColor= [UIColor colorWithHexString:BLUE_GREEN_COLOR];

UITabBarController*tabBarController = (UITabBarController*)self;

UITabBar*tabBar = tabBarController.tabBar;

UITabBarItem*trainEnquiryItem  = [tabBar.itemsobjectAtIndex:0];

[trainEnquiryItem setTitle:@"查询"];

[trainEnquiryItemsetImage:[UIImageimageNamed:@"tet"]];

[trainEnquiryItemsetSelectedImage:[UIImageimageNamed:@"tet_hover"]];

改变UITabBarItem 字体颜色

[[UITabBarItem appearance] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIColor whiteColor],UITextAttributeTextColor,nil] forState:UIControlStateNormal];

[[UITabBarItem appearance]setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIColor colorWithHexString:"#00C8D3"],UITextAttributeTextColor,nil] forState:UIControlStateSelected];


tip 62 :  UITextFiled 设置PlaceHolder字体颜色

#pragma mark设置Placeholder颜色

UIColor*color = [UIColorwhiteColor];

_userNameTextField.attributedPlaceholder= [[NSAttributedStringalloc]initWithString:@"用户名/邮箱"attributes:@{NSForegroundColorAttributeName: color}];

[tempUserNameImageViewaddSubview:_userNameTextField];

tip 63 :  应用主题设置心得以及思路

THEME是主题名称

同理,所有涉及到界面的地方都要监听THEME通知,

IOS有关主题的问题  ThemeManager 类

1.创建路径:初始化时先从指定的plist文件中读取主题文件

2.根据路径初始化有关主题的数组

3.如果这个数组为空,初始化为0个对象

4.接口 :

-(BOOL)downLoad:(NSDictionary *)dic Block:(void  (^) (BOOL))a

{

//1.保存block

//2.从字典中获得主题名称

//3.数组中保存这个主题文件: 根据名字判断主题是否已经存在

[self.dataArray containsObject:self.tempTheme];

//4.1存在:NSUserDefault保存——>通知中心发送通知post——>结束返回

//4.2  根据url发起网络请求——>

进行下载——>

下载完成保存文件——>

}

-(void)saveData:(NSData *)data

{

保存到指定文件——>

解压缩文件——>

用NSUserDefault记录主题名,启动的时候方便读取——>

//4.3主题持久化工作

将主题名字保存到数组中,将整个数组写到初始化时的plist文件目录中 ,(里面包含所有的主题名称) writeToFile

//4.4保存完发送主题广播 post

//4.5发送广播,调用回调函数

//4.6在MainTabBarController里面配置界面,相当于设置主题,不同主题,里面的图片的名字是不一样的

}

在某个类中使用新的主题文件 比如:MainViewController:

-(void)dealloc{

[ [NSNotificationCenter defaultCenter] removeObserver:self name:THEME object :nil];

}

-(void)viewDidLoad

{

//顺序不可以颠倒

[self createTabBarItem];

//接收通知后一定要在第一次读取默认主题创建好之后再接收 createTabBarItem是布局界面的方法

[ [NSNotification defaultCenter]  addObserver:self  selector:@selector(createTabBarItem) name:THEME object:nil];

}

-(void)createTabBarItem

{

//设置界面主题图片

}


tip 64 :  设置UITabBarItem文字属性

//设置文字颜色

if(iOS7) {

         [[UITabBarItem appearance]setTitleTextAttributes:@{NSForegroundColorAttributeName:                    [UIColorwhiteColor]}forState:UIControlStateSelected];

}else{

       [[UITabBarItem appearance]setTitleTextAttributes:@{UITextAttributeTextColor: [UIColorwhiteColor]}forState:UIControlStateSelected];

}


tip 65 : 设置UITabBarItem背景图片

if(iOS7) {

      item = [iteminitWithTitle:title[i]

     image:[unSelectImageimageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]

    selectedImage:[selectImageimageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]];

}else{

     itemsetFinishedSelectedImage:selectImagewithFinishedUnselectedImage:unSelectImage];

     item.title= title[i];

}


tip 66 :  一个View旋转一定角度

//M_PI == 3.14 == 180

[btn setTransform:CGAffineTransformMakeRotation(M_PI/7.2)];//25


tip 67 : 一些crash崩溃原因

1、对象里面没有某个方法

2、自己建的类没有NSCopying协议,就去copy

3、对某类的对象进行归档接档,没有实现NSCoding协议

4、下标越界

5、导航视图控制器出栈时,某个vc不在

6、数据为空,没有初始化


tip 68 : id类型不能用点语法


tip 69 :  设置睡眠 & 产生真正的随机数

sleep(1.f);  // 睡眠一秒

arc4random()%10; // 10以内的随机数


tip 70 : 参数要遵循某种协议的写法

void play(id ins) // look at here

{

     if ([ins respondsToSelector:@selector(playMusic)]) {

            [ins playMusic];

     }

}


tip 71 :  NSString的一些特殊情况

//__autoreleasing 对象设置为这样,要等到离自己最近的释放池销毁时才release

//__unsafe__unretained不安全不释放,为了兼容过去而存在,跟__weak很像,但是这个对象被销毁后还在,不像__weak那样设置为nil

//__weak 一创建完,要是没有引用,马上释放,将对象置nil

//

__weak NSMutableString *str = [NSMutableString stringWithFormat:@"%@",@"xiaobai"];

//__weak 的话但是是alloc的对象,要交给autorelease管理

//arc下,不要release 和 autorelease因为


tip 72 : 判断类,成员,调用方法

[obj isMemberOfClass:[runTime class]] //判断是不是一个一个类的成员

[obj isKindOfClass:[NSObject class]] //是不是从属一个类,包括父类

[obj conformsToProtocol:@protocol(NSCoding)]//是不是支持这一个协议

[obj performSelector:@selector(showA:) withObject:[NSNumber numberWithInt:8]]//给方法发送消息


tip 73 :  文件操作注意事项

//NSFileHandle * fh = [NSFileHandle fileHandleForReadingAtPath:@"/Users/qianfeng/Desktop/C考试准备"];

//[fh seekToFileOffset:2];//定位到某处开始执行操作,显示的seek会更新文件指针

//NSData * data = [fh availableData];

//NSData *data = [fh readDataOfLength:2];

写文件的注意事项

voidtestArchiver()//“支持nscopy的可以写到文件”

{

NSString* str =@"123445788";

NSArray* array = [[NSArray alloc]initWithObjects:@"nihao",nil];

[strwriteToFile:@"/Users/qianfeng/Desktop/笔记本使用注意事项2.text"atomically:YES encoding:NSUTF8StringEncodingerror:nil];

[arraywriteToFile:@"djhfdj"atomically:YES];//读写保护

}

voidtest3()//NSCode是能将OC类型写到文件的

{

Myfiler* mf = [[Myfileralloc]init];

NSArray* array = [NSArray arrayWithObject:mf];

[arraywriteToFile:@"djhfdjf"atomically:YES];//失败,因为普通类Myfiler不支持nscopy协议

}



由于篇幅关系,未完待续!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容