1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let saveBool = UIVideoAtPathIsCompatibleWithSavedPhotosAlbum (newURL!.path)
if saveBool == true {
UISaveVideoAtPathToSavedPhotosAlbum (newURL!.path, self , #selector(self .image(image:didFinishSavingWithError:contextInfo:)), nil )
}
func image (image: UIImage, didFinishSavingWithError error: NSErrorPointer, contextInfo:UnsafeRawPointer) {
if error == nil {
printLog("保存成功" )
} else {
printLog("保存失败\(error) " )
}
}
1
2
3
4
5
6
let str = "itms-apps://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?type=Purple+Software&id=966492118"
let url = URL (string: str)
UIApplication .shared.openURL(url!)
忽略 “Undeclared selector…” 的 Warning
1
2
3
4
5
6
7
8
9
10
11
12
13
14
if (_delegate && [_delegate respondsToSelector:@selector(retrievingProgressMP4:)])
{
[_delegate performSelector:@selector(retrievingProgressMP4:) withObject:[NSNumber numberWithFloat:_exportSession.progress]];
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"
#pragma clang diagnostic pop
将GIF图片分解成多张PNG图片,使用UIImageView播放。
需要导入#import
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
NSURL *fileUrl = [[NSBundle mainBundle] URLForResource:@"<#gifName#>" withExtension:@"gif" ];
CGImageSourceRef gifSource = CGImageSourceCreateWithURL ((CFURLRef ) fileUrl, NULL );
size_t frameCout = CGImageSourceGetCount (gifSource);
NSMutableArray *frames = [[NSMutableArray alloc] init];
for (size_t i = 0 ; i < frameCout; i++) {
CGImageRef imageRef = CGImageSourceCreateImageAtIndex (gifSource, i, NULL );
UIImage *imageName = [UIImage imageWithCGImage:imageRef];
[frames addObject:imageName];
CGImageRelease (imageRef);
}
UIImageView *gifImageView = [[UIImageView alloc] initWithFrame:CGRectMake (<#x#>, <#y#> , <#w#> , <#h#> )];
gifImageView.animationImages = frames;
gifImageView.animationDuration = 0.15 ;
[gifImageView startAnimating];
[self .view addSubview:gifImageView];
// 视频中获取图片 视频截取图片
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
CMTime itemTime = self .playerItem.currentTime;
CVPixelBufferRef pixelBuffer = [_playerItemVideoOutput copyPixelBufferForItemTime:itemTime itemTimeForDisplay:nil ];
CIImage *ciImage = [CIImage imageWithCVPixelBuffer:pixelBuffer];
CIContext *temporaryContext = [CIContext contextWithOptions:nil ];
CGImageRef videoImage = [temporaryContext
createCGImage:ciImage
fromRect:CGRectMake (0 , 0 ,
CVPixelBufferGetWidth(pixelBuffer),
CVPixelBufferGetHeight(pixelBuffer))];
UIImage *uiImage = [UIImage imageWithCGImage:videoImage];
CGImageRelease (videoImage);
NSLog (@"uiImage:%@" , uiImage);
self .myImgView.image = uiImage;
分析得到:copyPixelBufferForItemTime这个方法需要的参数是当前avplayerItem的cmtime, 也就是说前提是正在播放视频流,不知道有没有理解错。
视频播放时候如何在静音模式下有声音
1
2
3
4
5
6
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayback error:nil ];
let audioSession = AVAudioSession .sharedInstance()
try? audioSession.setCategory(AVAudioSessionCategoryPlayback );
// 简单保存视频到相册 —
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
let filepath = GetDownFilePath (fileName).path
printLog("测试保存地址 \(filepath) " )
if ( UIVideoAtPathIsCompatibleWithSavedPhotosAlbum (filepath) == true ){
UISaveVideoAtPathToSavedPhotosAlbum (filepath, self , #selector(self .video(videoPath:didFinishSavingWithError:contextInfo:)), nil );
}
func video (videoPath: String, didFinishSavingWithError error: NSError?, contextInfo info: AnyObject) {
}
func image (_ image: UIImage, didFinishSavingWithError error: NSError?, contextInfo: UnsafeRawPointer) {
if error == nil {
MBManage .shareMode.showBriefHUD("保存成功" )
}else {
MBManage .shareMode.showBriefHUD("保存失败" )
}
}
view 层级调整 ,互换 层最上层等
1
2
3
4
5
6
7
8
9
self.view .bringSubviewToFront (view1)
self.view .sendSubviewToBack (view1)
self.view .exchangeSubviewAtIndex (2 , withSubviewAtIndex: 3 )
swift 3 继承变量问题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
open var isRotate:Bool = false
override var isRotate: Bool {
get {
return true
}
set {
super .isRotate = newValue
}
}
是否显示状态栏
1
2
3
4
5
UIApplication.shared .setStatusBarHidden (false, with: UIStatusBarAnimation.none )
navigationController 自带边缘右滑 退出, 代理 可以设置启用和不启用 UIGestureRecognizerDelegate
1
2
3
4
5
6
self .navigationController?.interactivePopGestureRecognizer?.delegate = self
func gestureRecognizerShouldBegin (_ gestureRecognizer: UIGestureRecognizer) -> Bool {
return false
}
iOS获取数组的最大值
1
2
3
4
5
6
7
NSMutableArray * array = [NSMutableArray array];
for (int i = 0 ; i < 10 ; i++) {
CGFloat num = arc4random() % 100 + 1 ;
[array addObject:[NSNumber numberWithFloat:num]];
}
CGFloat maxValue = [[array valueForKeyPath:@"@max.floatValue" ] floatValue];
CGFloat minValue = [[array valueForKeyPath:@"@min.floatValue" ] floatValue];
重点在这句话上 @”@max.floatValue”(获取最大值), @”@min.floatValue”(获取最小值), @”@avg.floatValue” (获取平均值), @”@count.floatValue”(获取数组大小) 等等。。。。
oc通过强制类型转换四舍五入。swift 同理可行
1
2
3
4
float f = 1.5
int a
a = (int )(f+0 .5 )
NSLog("a = %d" ,a)
TabBarViewController 和UINavigationController的bar 上的黑线
1
2
3
let tabFrame = CGRect(x: 0 , y: 0 , width: stageWidth, height: self.tabBar.frame.height)
self.tabBar.backgroundImage = Getdevice.shared().image(withFrame: tabFrame, alphe: 1.0 )
self.tabBar.shadowImage = UIImage()
UINavigationController 中的navigationBar 同理
iOS 字符串 中包含 % 百分号的方法
百分号的转换,NSString中需要格式化的字符串中百分号使用%%表示,而char*中百分号也是使用%%表示。
例如:NSLog(@”%%%@%%”,@”hello”),控制台会打印出%hello%。
cell 选择按钮替换
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
class UserVideoManagerTableViewCell: UITableViewCell {
var showView:ShowVideoTableCellView!
override func layoutSubviews() {
super .layoutSubviews()
if #available(iOS 8 , *){
for control in self .subviews{
if control.isMember(of: NSClassFromString ("UITableViewCellEditControl" )!){
for v in control.subviews{
if v.isKind(of: UIImageView .classForCoder()){
if self .isSelected{
(v as! UIImageView ).image = UIImage (named: "v2_4_btn_set_selected" )
}else {
}
}
}
}
}
}else {
for view in self .subviews{
if view.isMember(of: NSClassFromString ("UITableViewCellScrollView" )!){
printLog("views \(view.subviews)" )
let views2 = view.subviews
for control in views2{
if control.isMember(of: NSClassFromString ("UITableViewCellEditControl" )!){
for v in control.subviews{
if v.isKind(of: UIImageView .classForCoder()){
let img = v as! UIImageView
if self .isSelected{
img.image = UIImage (named: "v2_4_btn_set_selected" )
}else {
}
}
}
}
}
}
}
}
}
}
下面的方法本地还在 github 删除错误提交
git reset –hard HEAD~1 git push –force 就会删除远程的提交
1
2
3
git reset
git push origin HEAD
其他:
1
2
3
4
5
6
7
8
9
10
11
根据–soft –mixed –hard,会对working tree和index和HEAD进行重置:
git reset –mixed:此为默认方式,不带任何参数的git reset ,即时这种方式,它回退到某个版本,只保留源码,回退commit 和index 信息
git reset –soft:回退到某个版本,只回退了commit 的信息,不会恢复到index file 一级。如果还要提交,直接commit 即可
git reset –hard:彻底回退到某个版本,本地的源码也会变为上一个版本的内容
HEAD 最近一个提交
HEAD ^ 上一次
<commit_id> 每次commit 的SHA1 值. 可以用git log 看到,也可以在页面上commit 标签页里找到.
commit 合并:
使用Cocoapods时忽略Xcode警告 我使用相当多的第三方库,其中有很多警告,在最新的Xcode更新后。 (例如Facebook SDK pod) 现在所有这些警告都显示在我的Xcode上我想看到自己的警告或错误的地方。 有没有办法忽略这些错误?修复它们不会有帮助,因为在每个“pod安装”之后,更改被丢弃。 添加到您的Podfile:
1
2
3
4
5
6
7
platform :ios
inhibit_all_warnings!
pod 'FBSDKCoreKit' , :inhibit_warnings => true
然后执行:pod install
链接 down vote As it has already been answered, ObjC doesn’t support method overloading (two methods with the same name) and In swift 2 under Xcode 7 there are two options to solve this kind of problems. One option is to rename the method using the attribute: @objc(newNameMethod:)
func methodOne(par1, par2) {…}
@objc(methodTwo:) 标记为objc func methodOne(par1) {…} another option to solve this problem in Xcode 7+ is by applying @nonobjc attribute to any method, subscript or initialiser
func methodOne() {…}
@nonobjc // 标记为非objc func methodOne() {…}
//NSRange转化为range extension String { func range(from nsRange: NSRange) -> Range? { guard let from16 = utf16.index(utf16.startIndex, offsetBy: nsRange.location, limitedBy: utf16.endIndex), let to16 = utf16.index(from16, offsetBy: nsRange.length, limitedBy: utf16.endIndex), let from = String.Index(from16, within: self), let to = String.Index(to16, within: self) else { return nil } return from ..< to } }
//range转换为NSRange extension String { func nsRange(from range: Range) -> NSRange { let from = range.lowerBound.samePosition(in: utf16) let to = range.upperBound.samePosition(in: utf16) return NSRange(location: utf16.distance(from: utf16.startIndex, to: from), length: utf16.distance(from: from, to: to)) } }
swift 4
NSRange(range, in: string) //return 这个 range 转NSRange
/// string 中 查找子串 extension String { func nsranges(of string: String) -> [NSRange] { return ranges(of: string).map { (range) -> NSRange in self.nsrange(fromRange: range) } } }
// range 转 NSRange extension String { func nsrange(fromRange range : Range) -> NSRange { return NSRange(range, in: self) } }
链接:链1 链2
1
2
3
4
5
6
7
8
9
10
self.placeHolderLabel = UILabel()
self.placeHolderLabel .font = GlobalFont_32
self.placeHolderLabel .textColor = UIColor.lightGray
self.placeHolderLabel .text = "请输入内容"
self.placeHolderLabel .sizeToFit ()
self.inputeTextView .addSubview (self.placeHolderLabel)
self.inputeTextView .setValue (self.placeHolderLabel , forKey: "_placeholderLabel" )
或者用titleTextField.attributedPlaceholder 参数
—YYlabel-YY–
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
func setData (mode:MJ_UserMessage) {
self .mode = mode
let titleString = "\(mode.source_title) 赞了你的视频"
let attrText = NSMutableAttributedString (string: titleString)
attrText.yy_font = GlobalFont_32
attrText.yy_color = GlobalMainToneTextColor_lime
let fromUserRange = NSMakeRange (0 , mode.source_title.characters.count )
let fromUserHighlight = YYTextHighlight .init (backgroundColor: UIColor .clear)
fromUserHighlight.userInfo = ["MJ_UserMessage" :mode];
attrText.yy_setTextHighlight(fromUserHighlight, range: fromUserRange)
attrText.yy_setColor(UIColor (red:0.90 , green:0.30 , blue:0.25 , alpha:1.00 ), range: fromUserRange)
self .messageNameLabel.attributedText = attrText
self .messageNameLabel.sizeToFit()
self .messageNameLabel.highlightTapAction = { [weak self ](containerView:UIView ,text:NSAttributedString ,range:NSRange ,rect:CGRect ) in
if let weakSelf = self {
let highlight:YYTextHighlight = containerView.value(forKeyPath: "_highlight" ) as ! YYTextHighlight
let mode = highlight.userInfo?["MJ_UserMessage" ] as ? MJ_UserMessage
if mode == nil || mode?.source_type != "user" {return }
DispatchQueue .main.async {
let controller = MyMainPageViewController (NavTitle : mode!.source_ID, userId: mode!.source_title)
weakSelf.findController().navigationController?.pushViewController(controller, animated: true )
}
}
}
}
ios 防止锁屏
1
UIApplication.shared .isIdleTimerDisabled = true
一个oc警告忽略 忽略 “Undeclared selector…” 的 Warning
1
2
3
4
if ([someObject respondsToSelector :@selector (someSelector)])
{
[someObject performSelector:@selector(someSelector)] ;
}
以上这句代码,除非你在 someObject 的头文件中显式地声明了 someSelector,否则在 Xcode 中会提示警告: Undeclared selector ‘someSelector’ 但很多情况下我们并不想去声明它,此时我们可以禁用编译器的此类警告:
1
#pragma GCC diagnostic ignored "-Wundeclared-selector"
这样将会在整个文件内禁用此类警告,也可只在部分代码处禁用,保证编译器依然会对文件内其他代码进行警告检测,避免出现预料之外的 bug:
1
2
3
4
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"
#pragma clang diagnostic pop
记录事件, GPUImage 运行时 崩溃 8.3 系统上 ,只有debug 连着电脑运行才崩溃 , 只要正常安装正常
Provisioning Profile相关 在~/Library/MobileDevice/Provisioning Profiles目录可以看到本机所有的Provisioning Profile,但是这里显示都是.mobileprovision这样的文件,并不是很好辨认。 一般更新设备删除~/Library/MobileDevice/Provisioning 在xcode 重新下载
ios 苹果的测试 The TestFlight app 中测试 可以测试正式环境的推送
xcode 代码块 导出到其他电脑使用 cd /Users/用户名/Library/Developer/Xcode/UserData/
将CodeSnippets拷贝到新电脑的对应的目录下
swift 4 字符串
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
So, change
text .substring(to: 3 )
text .substring(from: 3 )
to
String(text .prefix(3 ))
String(text [text .index(text .startIndex, offsetBy: 3 )...])
let newStr = str .substring(to: index)
let newStr = String(str [..<index])
let newStr = str .substring(from: index)
let newStr = String(str [index...])
let range = firstIndex..<secondIndex
let newStr = = str .substring(with: range)
let newStr = String(str [range])
详情
根据字符串进行类的实例化 NSClassFromString 使用
1
2
3
4
5
6
7
Class vc_class = NSClassFromString (class_name);
let classtest = NSClassFromString ("项目名.类名" ) as ? 类名.Type
classtest?.init ()
printLog("测试 \(classtest?.init () )" )
— 代码行数统计—— 项目目录终端执行 其中 -name “*.m” 就表示扩展名为.m的文件。
1
find . "(" -name "*.m" -or -name "*.mm" -or -name "*.swift" -or -name "*.cpp" -or -name "*.h" -or -name "*.rss" ")" -print | xargs wc -l
swift KVO 需要的条件
swift 4 得 @objc dynamic 前缀 基于运行时,动态变量, 一般在swift 中用自动布局SDAutoLayout 自动cell 高度 需要使用这个
一个swift 闭包内存处理1
2
3
4
5
6
7
8
9
lazy var newBtn: UIButton = {
let obj = UIButton ();
obj.addAction({ [weak self ](btn) in
self ?.delegate?.xxx
})
return obj;
}()
player 播放器网络差处理 摘取自CLPlayerDemo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#pragma mark - 监听
- (void )observeValueForKeyPath:(NSString *)keyPath ofObject:(id )object change:(NSDictionary <NSString *,id > *)change context:(void *)context{
if ([keyPath isEqualToString:@"status" ]) {
if (self .player.currentItem.status == AVPlayerItemStatusReadyToPlay ) {
self .state = CLPlayerStatePlaying ;
self .player.muted = self .mute;
}
else if (self .player.currentItem.status == AVPlayerItemStatusFailed ) {
self .state = CLPlayerStateFailed ;
}
} else if ([keyPath isEqualToString:@"loadedTimeRanges" ]) {
NSTimeInterval timeInterval = [self availableDuration];
CMTime duration = self .playerItem.duration;
CGFloat totalDuration = CMTimeGetSeconds (duration);
[self .maskView.progress setProgress:timeInterval / totalDuration animated:NO ];
} else if ([keyPath isEqualToString:@"playbackBufferEmpty" ]) {
if (self .playerItem.isPlaybackBufferEmpty) {
[self bufferingSomeSecond];
}
} else if ([keyPath isEqualToString:@"playbackLikelyToKeepUp" ]) {
if (self .playerItem.isPlaybackLikelyToKeepUp && self .state == CLPlayerStateBuffering ){
self .state = CLPlayerStatePlaying ;
}
}
}
#pragma mark - 缓冲较差时候
- (void )bufferingSomeSecond{
self .state = CLPlayerStateBuffering ;
[self pausePlay];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC )), dispatch_get_main_queue(), ^{
[self playVideo];
if (!self .playerItem.isPlaybackLikelyToKeepUp) {
[self bufferingSomeSecond];
}
});
}
一个xcode注释文档警告忽略Bulid Settings -> Documentation Comments -> NO
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
常用的一些占位符:
%@:字符串占位符
%d:整型
%ld:长整型
%f:浮点型
%c:char类型
%%:%的占位符
BOOL studyBool = YES;
NSLog(@"打印BOOL型数据%@",studyBool?@"YES":@"NO");//打印BOOL型数据YES
NSLog(@"打印BOOL型数据%d",studyBool);//打印BOOL型数据1
BOOL alsoBool = NO;
NSLog(@"打印BOOL型数据%@",alsoBool?@"YES":@"NO");//打印BOOL型数据NO
NSLog(@"打印BOOL型数据%d",alsoBool);//打印BOOL型数据0
详细介绍:**********************************************************
%@: Objective-C对象,印有字符串返回descriptionWithLocale:如果于的话,或描述相反.CFTypeRef工作对象,返回的结果的CFCopyDescription功能.(这个翻译有问题建议按照自己的理解方式理解)。
%%: 为'%' 字符;
%d,%D,%i: 为32 位整型数(int );
%u,%U: 为32 位无符号整型数(unsigned int );
%hi: 为有符号的16 位整型数(short);
%hu: 为无符号的16 位整型数(unsigned shord);
%qi: 为有符号的64 位整型数(long long);
%qu: 为无符号的64 位整型数(unsigned long long);
%x: 为32 位的无符号整型数(unsigned int ),打印使用数字0 -9 的十六进制,小写a-f;
%X: 为32 位的无符号整型数(unsigned int ),打印使用数字0 -9 的十六进制,大写A-F;
%qx: 为无符号64 位整数(unsigned long long),打印使用数字0 -9 的十六进制,小写a-f;
%qX: 为无符号64 位整数(unsigned long long),打印使用数字0 -9 的十六进制,大写A-F;
%o,%O: 为32 位的无符号整数(unsigned int ),打印八进制数;
%f: 为64 位的浮点数(double);
%e: 为64 位的浮点数(double),打印使用小写字母e,科学计数法介绍了指数的增大而减小;
%E: 为64 位的浮点数(double),打印科学符号使用一个大写E介绍指数的增大而减小;
%g: 为64 位的浮点数(double),用%e的方式打印指数,如果指数小于4 或者大于等于精度,那么%f的风格就会有不同体现;
%G: 为64 位的浮点数(double),用%E的方式打印指数,如果指数小于4 或者大于等于精度,那么%f的风格就会有不同体现;
%c: 为8 位的无符号字符%c(unsigned char),通过打印NSLog()将其作为一个ASCII字符,或者,不是一个ASCII字符,八进制格式\ddd或统一标准的字符编码的十六进制格式\udddd,在这里d是一个数字;
%C: 为16 位Unicode字符%C(unichar),通过打印NSLog()将其作为一个ASCII字符,或者,不是一个ASCII字符,八进制格式\ddd或统一标准的字符编码的十六进制格式\udddd,在这里d是一个数字;
%s: 对于无符号字符数组空终止,%s系统中解释其输入编码,而不是别的,如utf-8 ;
%S: 空终止一系列的16 位Unicode字符;
%p: 空指针(无效*),打印十六进制的数字0 -9 和小写a-f,前缀为0x;
%L: 在明确规定的长度下,进行修正,下面的一批数据a,A,e,E,f,F,g,G应用于双精度长整型的参数;
%a: 为64 位的浮点数(double),按照科学计数法打印采用0x和一个十六进制数字前使用小写小数点p来介绍指数的增大而减小;
%A: 为64 位的浮点数(double),按照科学计数法打印采用0X和一个十六进制数字前使用大写字母小数点P界扫指数的增大而减小;
%F: 为64 位的浮点数(double),按照十进制表示法进行打印;
%z: 修改说明在%z长度以下d,i,o,u,x ,X适用于某一指定类型的转换或者适用于一定尺寸的整数类型的参数;
%t: 修改说明在%t长度以下d,i,o,u,x ,X适用于某一指定类型或一定尺寸的整数类型的转换的参数;
%j: 修改说明在%j长度以下d,i,o,u,x ,X适用于某一指定类型或一定尺寸的整数类型的转换的参数