iOS 持续化集成

值得注意的小细节整理

2016-12-13  本文已影响638人  ethan_cun

一、如何输出超链接的各个组成部分

NSURL *url = [NSURL URLWithString:@"http://www.baidu.com/search?id=1"];

NSLog(@"scheme:%@", [url scheme]); //协议 http

NSLog(@"host:%@", [url host]);     //域名 www.baidu.com

NSLog(@"absoluteString:%@", [url absoluteString]); //完整的url字符串 http://www.baidu.com:8080/search?id=1   (刚才在真机上跑了一下,并没有打印出来端口 8080 啊)

NSLog(@"relativePath: %@", [url relativePath]); //相对路径 search

NSLog(@"port :%@", [url port]);  // 端口 8080

NSLog(@"path: %@", [url path]);  // 路径 search

NSLog(@"pathComponents:%@", [url pathComponents]); // search

NSLog(@"Query:%@", [url query]);  //参数 id=1

二、CAShapeLayer的strokeStart和strokeEnd属性

1 keyPath = strokeStart  动画的fromValue = 0,toValue = 1
     表示从路径的0位置画到1 怎么画是按照清除开始的位置也就是清除0 一直清除到1 效果就是一条路径慢慢的消失

2 keyPath = strokeStart  动画的fromValue = 1,toValue = 0
     表示从路径的1位置画到0 怎么画是按照清除开始的位置也就是1 这样开始的路径是空的(即都被清除掉了)一直清除到0 效果就是一条路径被反方向画出来

3 keyPath = strokeEnd  动画的fromValue = 0,toValue = 1
     表示 这里我们分3个点说明动画的顺序  strokeEnd从结尾开始清除 首先整条路径先清除后2/3,接着清除1/3 效果就是正方向画出路径

4 keyPath = strokeEnd  动画的fromValue = 1,toValue = 0
     效果就是反方向路径慢慢消失
注释: 动画的0-1(fromValue = 0,toValue = 1) 或1-0 (fromValue = 1,toValue = 0) 表示执行的方向 和路径的范围。
   CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    pathAnimation.duration = 1.5;
    pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    pathAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
    pathAnimation.toValue = [NSNumber numberWithFloat:1.0f];
    pathAnimation.autoreverses = NO;
    [_chartLine addAnimation:pathAnimation forKey:@"strokeEndAnimation"];
    _chartLine.strokeEnd = 2.0;

三、errors:The operation couldn’t be completed. Unable to log in with account 'myappleid'. An unexpected failure occurred while logging in (Underlying error code 1100).

解决方法:
原因是Apple ID 过时了,点击"Preferences" -> "Accounts", 重新登录;然后退出Xcode,重进,编译,就会自动修复repairing...

四、label 文字实现竖直排布、

只需要设置 numberOfLines = 0 然后再调用sizeToFit

五、Archive的时候,选择了发布的Provisioning Profile,但是在选择Code Signing Identify时,没有唯一对应的。
屏幕快照 2017-02-03 下午3.04.33.png

此时即使你知道当前Provisioning Profile对应的是哪个Code Signing Identify,并选择它,开始Archive时,也会提示以下的错误:

屏幕快照 2017-02-03 下午3.04.43.png
解决方案:

1.打开终端,输入:

cd Library/MobileDevice/Provisioning\ Profiles

2.在Xcode,Provisioning Profile中选择other,得到当前证书的UUID

屏幕快照 2017-02-03 下午3.06.23.png
3.然后在终端中执行

rm -rf 8ed7a446-9fd9-461e-9965-f85a75c78258.mobileprovision(此处替换成你的provision)

4.从developer.apple.com重新下载证书,添加到Xcode。

说明:有可能再次添加Provisioning Profile还会出现上面没有唯一Identify对应的情况,可以多试几次。

六、如何知道tableview已经加载完成

-(void)tableView:(UITableView*)tableViewwillDisplayCell:(UITableViewCell*)cellforRowAtIndexPath:(NSIndexPath*)indexPath
{

  if([indexPath row] == ((NSIndexPath*)[[tableView indexPathsForVisibleRows] lastObject]).row){
    //TODO:end refresh
}
}

由于willDisplayCell是异步调用的,所以在上面的block里面不能即时更新UI,最好使用GCD通过主线程加上你的代码:

-(void)tableView:(UITableView*)tableViewwillDisplayCell:(UITableViewCell*)cellforRowAtIndexPath:(NSIndexPath*)indexPath
{
if([indexPath row] == ((NSIndexPath*)[[tableView indexPathsForVisibleRows] lastObject]).row){
dispatch_async(dispatch_get_main_queue,^{
//for example [activityIndicator stopAnimating];
});
    }
}

七、运行程序出现file too small (length=0)错误解决办法

ld: file too small (length=0) file '/Users/Allister/Library/Developer/Xcode/DerivedData/Haze_Meter-dkjjcmjehyitmcbhkcbujnsrhwpu/Build/Intermediates/Haze Meter.build/Debug-iphonesimulator/Haze Meter.build/Objects-normal/x86_64/ViewController.o' for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

1.选择xcode菜单的Product下的Clean,或者组合键是Cmd+Shift+K,清除一遍
2.重新编译

八、上架错误提示

屏幕快照 2017-07-31 下午3.18.26.png

原因:没有对应buddle id的应用, 先去itunes里新建一个对应buddle id的app, 然后再打包

九、统计项目中代码数量

cd到项目根目录
find . "(" -name "*.m" -or -name "*.mm" -or -name "*.cpp" -or -name "*.h" -or -name "*.rss" ")" -print | xargs wc -l

十、获取电脑ip

ifconfig en0

十一、没有导入libz库

错误 解决

十二、The file “Info.plist” couldn’t be opened because there is no such file.

解决办法:

屏幕快照 2017-08-14 下午5.00.46.png

十三、 The file “CCYYXmpp” couldn’t be opened because you don’t have permission to view it.

解决办法:切换一下project和targerts 化成真机

屏幕快照 2017-08-14 下午5.17.15.png

十四、iOS 跳转到设置界面

[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];

设置其他界面

在 URL Types 添加 一个叫 prefs 的 URL Schemes

[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"跳转不同界面对应的URLString"]]
蜂窝网络:App-Prefs:root=MOBILE_DATA_SETTINGS_ID
VPN — App-Prefs:root=General&path=Network/VPN
Wi-Fi:App-Prefs:root=WIFI
定位服务:App-Prefs:root=LOCATION_SERVICES
个人热点:App-Prefs:root=INTERNET_TETHERING
关于本机:App-Prefs:root=General&path=About
辅助功能:App-Prefs:root=General&path=ACCESSIBILITY
飞行模式:App-Prefs:root=AIRPLANE_MODE
锁定:App-Prefs:root=General&path=AUTOLOCK
亮度:App-Prefs:root=Brightness
蓝牙:App-Prefs:root=General&path=Bluetooth
时间设置:App-Prefs:root=General&path=DATE_AND_TIME
FaceTime:App-Prefs:root=FACETIME
设置:App-Prefs:root=General
键盘设置:App-Prefs:root=General&path=Keyboard
iCloud:App-Prefs:root=CASTLE
iCloud备份:App-Prefs:root=CASTLE&path=STORAGE_AND_BACKUP
语言:App-Prefs:root=General&path=INTERNATIONAL
定位:App-Prefs:root=LOCATION_SERVICES
音乐:App-Prefs:root=MUSIC
Music Equalizer — App-Prefs:root=MUSIC&path=EQ
Music Volume Limit — App-Prefs:root=MUSIC&path=VolumeLimit
Network — App-Prefs:root=General&path=Network
Nike + iPod — App-Prefs:root=NIKE_PLUS_IPOD
Notes — App-Prefs:root=NOTES
Notification — App-Prefs:root=NOTIFICATIONS_ID
Phone — App-Prefs:root=Phone
Photos — App-Prefs:root=Photos
Profile — App-Prefs:root=General&path=ManagedConfigurationList
Reset — App-Prefs:root=General&path=Reset
Safari — App-Prefs:root=Safari
Siri — App-Prefs:root=General&path=Assistant
Sounds — App-Prefs:root=Sounds
Software Update — App-Prefs:root=General&path=SOFTWARE_UPDATE_LINK
Store — App-Prefs:root=STORE
Twitter — App-Prefs:root=TWITTER
Usage — App-Prefs:root=General&path=USAGE
Wallpaper — App-Prefs:root=Wallpaper

十五、获取AppStore应用版本号

想不通过自己服务器后台,而是直接比较本地和appStore版本大小做版本更新,但是用http://itunes.apple.com/lookup?id=%@(这里写appid,通过在itunes connect App信息里面获取)获取不到版本号?

这个时候应该怎么办: 加上*/cn*(当然这只是针对只在中国玩玩的APP) https也可以
http://itunes.apple.com/cn/lookup?id=%@

附上代码:

//获取最新版本号
-(void)VersonUpdate{
    //定义的app的地址
    NSString *urld = [NSString stringWithFormat:@"https://itunes.apple.com/cn/lookup?id=%@",@"您的appId"];
    
    //网络请求app的信息,主要是取得我说需要的Version
    NSURL *url = [NSURL URLWithString:urld];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
                                                           cachePolicy:NSURLRequestReloadIgnoringCacheData
                                                       timeoutInterval:10];
    [request setHTTPMethod:@"POST"];
    
    NSURLSession *session = [NSURLSession sharedSession];
    
    NSURLSessionDataTask *task = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        
        NSMutableDictionary *receiveStatusDic=[[NSMutableDictionary alloc]init];
        
        if (data) {
            
            //data是有关于App所有的信息
            NSDictionary *receiveDic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
            
            if ([[receiveDic valueForKey:@"resultCount"] intValue]>0) {
                
                [receiveStatusDic setValue:@"1" forKey:@"status"];
                [receiveStatusDic setValue:[[[receiveDic valueForKey:@"results"] objectAtIndex:0] valueForKey:@"version"]   forKey:@"version"];
                
                //请求的有数据,进行版本比较
                [self performSelectorOnMainThread:@selector(receiveData:) withObject:receiveStatusDic waitUntilDone:NO];
            }else{
                
                [receiveStatusDic setValue:@"-1" forKey:@"status"];
            }
        }else{
            [receiveStatusDic setValue:@"-1" forKey:@"status"];
        }
    }];
    
    [task resume];
}

//比较版本号大小 挨个比  我自己规定都是3位 0.0.0
-(void)receiveData:(id)sender
{
    //获取APP自身版本号
    NSString *localVersion = [[[NSBundle mainBundle]infoDictionary]objectForKey:@"CFBundleShortVersionString"];
    
        if ([localVersion compare:sender[@"version"] ] == NSOrderedAscending) {
            
            //判断有没有新版本 有则提示更新
          [self updateVersion];
        }
}
// 弹出框
-(void)updateVersion{
    
    NSString *msg = [NSString stringWithFormat:@"更新最新版本,优惠信息提前知"];
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"升级提示" message:msg preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *otherAction = [UIAlertAction actionWithTitle:@"现在升级"style:UIAlertActionStyleDestructive handler:^(UIAlertAction*action) {
        
        NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"您的app在AppStore的下载地址"]];
        [[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil];
    }];
    [alertController addAction:otherAction];
    [self.window.rootViewController presentViewController:alertController animated:YES completion:nil];
}

十六、app导包检验错误 如图:

屏幕快照 2017-08-25 下午2.11.01.png

解决方式:检查生产证书是否正确, 重新打开以下p12,更改bunddle id,然后再改回去,重新导出。

十七、Undefined symbols for architecture x86_64:

"_main", referenced from:
implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64

如图:


屏幕快照 2017-08-28 上午9.56.57.png

原因:工程里的main被删除了,重新添加一个main.m; 如果没有删除,则是因为main.m没有加入编译,解决办法:target -> build parse ->compile source 添加main.m。

十八、 [#pragma clang diagnostic ignored 用法 更多看这]

// 例子 没有使用的变量
#pragma clang diagnostic push     
#pragma clang diagnostic ignored "-Unused-variable"     
  int a;     
#pragma clang diagnostic pop 

十九、宏与函数的区别(特有意思 举个例子)

宏:
#define czyMax(a,b) ((a)>(b)?(a):(b))
函数:
- (NSInteger)compare:(NSInteger)a andB:(NSInteger)b
{
    if (a++>b) {
        return a;
    }
    return b;
}
比较部分:
    NSInteger a = 1;
    NSInteger b = 0;
    
    [self compare:a andB:b];
    
    NSLog(@"a = %ld, b = %ld", a, b);

    czyMax(a++, b);
    
    NSLog(@"a = %ld, b = %ld", a, b);
    
    NSInteger c = 1;
    NSInteger d = 0;
    
    czyMax(c++, d+10);
    
    NSLog(@"c = %ld, d = %ld", c, d);
输出结果:
2017-09-01 11:37:24.835 czytext[14333:851733] a = 1, b = 0
2017-09-01 11:37:24.835 czytext[14333:851733] a = 3, b = 0
2017-09-01 11:37:24.835 czytext[14333:851733] c = 2, d = 0
充分说明了两者的变量作用域的区别 同时应该注意用宏比较a++之后a的值变化; 
即MAX(a++,b);与MAX(a++,b+10);运行两者后a的值是多少
还有一个问题,如果我要是用上面的宏求a++(a=1), b=0的最大值,
那么我得到的值是3,此时宏也不实用了,怎么办呢? 
求最大值的宏正确书写姿势:
//##合并
#define CZY_JOGIN(A,B) A##B

//COUNTER是一个预定义的宏,这个值在编译过程中将从0开始计数,每次被调用时加1。
//为变量名a和b添加了一个计数后缀,这样大大避免了变量名相同而导致问题的可能性
#define CZY_MAX(A,B) CZY_GET_MAX(A,B,COUNTER)

//求最大值 宏中用反斜杠换行\
#define CZY_GET_MAX(A,B,L) ({ \
        typeof(A) CZY_JOGIN(__a,L) = (A);\
        typeof(B) CZY_JOGIN(__b,L) = (B);\
        (CZY_JOGIN(__a,L) > CZY_JOGIN(__b,L)) ? CZY_JOGIN(__a,L) : CZY_JOGIN(__b,L); \
})

//补充弱强类型的宏 也用的很多
#define weak(obj) __weak typeof(obj) weak##obj = obj;
#define strong(obj) __strong typeof(obj) strong##obj = obj;
//类似的求三者最大值的宏
//三者求最大值
#define CZY_THREE_JOIN(A,B) A##B
#define CZY_THREE_MAX(A,B,C) CZY_THREE_COMPARE(A,B,C,COUNTER)
#define CZY_THREE_COMPARE(A,B,C,COUNTER) ({\
    typeof(A) CZY_THREE_JOIN(__a, COUNTER) = (A);\
    typeof(B) CZY_THREE_JOIN(__b, COUNTER) = (B);\
    typeof(C) CZY_THREE_JOIN(__c, COUNTER) = (C);\
    (CZY_THREE_JOIN(__a, COUNTER)>CZY_THREE_JOIN(__b, COUNTER))?\
    ((CZY_THREE_JOIN(__a, COUNTER)>CZY_THREE_JOIN(__c, COUNTER))?CZY_THREE_JOIN(__a, COUNTER):CZY_THREE_JOIN(__c, COUNTER)):\
    ((CZY_THREE_JOIN(__b, COUNTER)>CZY_THREE_JOIN(__c, COUNTER))?CZY_THREE_JOIN(__b, COUNTER):CZY_THREE_JOIN(__c, COUNTER));\
})

十九、 Xcode实现顶部自定义注释

Xcode 显示包内容 :Contents -> Developer -> Platforms -> iPhoneOS.platform -> Developer -> Library -> Xcode -> Templates -> File Templates 
修改Source文件夹下面的Cocoa Touch Class.xctemplate对应的所有文件的.h和.m,如果只修改一个,那么新建文件的时候,必须继承这个类才会看到自定义的文件注释。

十九、 如图

屏幕快照 2017-09-28 下午3.21.45.png

解决:用文本编辑器打开Launch.storyboard 和Main.storyboard 文件删掉:

<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
上一篇 下一篇

猜你喜欢

热点阅读