日常开发问题记录

75、Sourcetree http 用别人的账号密码推拉代码存储在了钥匙串,每次还要反复输入密码
关键命令
git config --global credential.helper osxkeychain

https://newsn.net/say/sourcetree-mac-pwd.html

74、/Users/dfpo/Library/Rime/

73、约束被拉伸、被挤压


 // 垂直方向上不要被拉伸
    [img setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
    // 不被挤压
//    [img setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];

72、InjectionIII使用
oc


// 1
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

  ...
#ifdef DEBUG
    [[NSBundle bundleWithPath: @"/Applications/InjectionIII.app/Contents/Resources/iOSInjection.bundle"] load];
#endif
 ...
    
    return YES;
}
// 2
#pragma mark - 实时刷新
/// 开启 实时刷新 UI
- (void)refreshUIRealTime {
#if DEBUG
    [[NSNotificationCenter defaultCenter] addObserverForName:@"INJECTION_BUNDLE_NOTIFICATION" object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
        while (self.view.subviews.count) {
            UIView* child = self.view.subviews.lastObject;
            [child removeFromSuperview];
        }
        [self viewDidLoad];
    }];
#endif
}
// 3 
- (void)viewDidLoad {
    [super viewDidLoad];
    [self refreshUIRealTime];

    ...
}

swift

// 1
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
       ...
        #if DEBUG
        Bundle(path: "/Applications/InjectionIII.app/Contents/Resources/iOSInjection.bundle")?.load()
        #endif
        ...
        return true
    }

// 2
// MARK: - 实时刷新
    /// 开启 实时刷新 UI
    public func refreshUIRealTime() {
    #if DEBUG
    NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "INJECTION_BUNDLE_NOTIFICATION"), object: nil, queue: .main) { (note) in
        
        self.view.subviews.forEach{$0.removeFromSuperview()}
        self.viewDidLoad()
    }
    #endif
    }

// 3
override func viewDidLoad() {
        super.viewDidLoad()
        
        refreshUIRealTime()
        ...
}

71、Sourcetree克隆http的git无效url


image.png

使用命令 git clone 也是失败的
解决方案:

去掉 :8081 ,居然就好使了。

70、去除csdn登录二维码

document.getElementsByClassName('login-mark')[0].remove()
document.getElementsByClassName('login-box')[0].remove()

69、IntelliJ IDEA
http://idea.94goo.com/

68、无用方法检测
1 AppCode
2 https://github.com/xuezhulian/selectorsunref

67、Xcode12报错
xcode12one or more architectures required by this target: arm64.
https://developer.apple.com/forums/thread/656509
Try upgrading the Project Xcode compatibility to Xcode 11 and change the VALIDARCHS to $(ARCHSSTANDARD). It worked for me

image.png

image.png

$(ARCHS_STANDARD)
66、新版本微信sdk 个别手机上分享不了,11上正常分享。授权登录不回调

image.png

#pragma mark - openUrl
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler {
    
    /// fix 新版本微信授权登录无回调
    if ([userActivity.webpageURL.absoluteString rangeOfString:MAkWeChatAppID].location != NSNotFound) {
        return [WXApi handleOpenURL:userActivity.webpageURL delegate:self];
    }
    //其他第三方回调;
     return YES;
}

65、word在线编辑 online word edit
https://products.aspose.app/words/editor

image.png

64、word转pdf doc转pdf docx转pdf
https://www.zamzar.com/convert/docx-to-pdf/
63、target has transitive dependencies that include statically linked binaries Bugly
场景:想到bugly做成本地pod SXBugly,而另外一个本地pod SXPod又依赖了这个SXBugly。
尝试解决:
SXBugly.podspec中添加

s.static_framework = true
s.dependency 'Bugly', '~> 2.5.71'

SXPod.podspec中添加s.dependency 'SXBugly' 想指定本地路径再报错
解决:把SXBugly做成SXPod的一个子库

64、
chrles安装了打开就显示已经损坏
sudo xattr -d com.apple.quarantine /Applications/Charles.app
63、菜鸡UI、菜鸡设计师就喜欢一个切图一个压缩包到处发,直接上传蓝湖/Sketch多好,浪费大家时间。

62、iOS又有圆角又有阴影


- (void)configCell {
    if (@available(iOS 14, *)) {
        self.backgroundConfiguration = [UIBackgroundConfiguration clearConfiguration];
    }
    
    
    UIView *cornerV = [[UIView alloc] initWithFrame:CGRectMake(20, 7, kScreenW-2*20,129-2*7)];
    cornerV.backgroundColor = [UIColor whiteColor];
    [self.contentView addSubview:cornerV];
    
    // 同时圆角阴影
    CALayer *layer = cornerV.layer;
    // 圆角
    layer.cornerRadius = 8;
    layer.masksToBounds = YES;
    // 阴影
    layer.shadowColor = [UIColor lightGrayColor].CGColor;
    layer.shadowOffset = CGSizeMake(3, 6);
    layer.shadowRadius = 2;
    layer.shadowOpacity = 0.3;
    layer.masksToBounds = NO;
    layer.shadowPath = [UIBezierPath bezierPathWithRoundedRect:cornerV.bounds cornerRadius:cornerV.layer.cornerRadius].CGPath;
    
}

如图:


image.png

61、Sourcetree,在Finder中查看,在终端中打开无法定位
官网下载Sourcetree_2.7.1d.zip,正常使用。
然后用app内部的检查更新,终端好使用了,但finder不能精准定位。
无奈先将就用2.7.1吧

60、preferredStatusBarStyle不调用

image.png

再搞个nav基类
image.png

59、uBlacklist 谷歌插件,从搜索结果中移除在黑名单中的网站

58、加载cpd界面
./run.sh cpdgui

image.png

image.png

57、WKWebView 不释放

-(void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];

  // 画面要消失时,移除要监听的串
    [self.wkWebView.configuration.userContentController removeScriptMessageHandlerForName:@"prompt"];
    [self.wkWebView.configuration.userContentController removeScriptMessageHandlerForName:@"appDownloadPic"];
}

56、原生集成Flutter
https://flutter.cn/docs/development/add-to-app
1、原生项目目录下执行flutter create --template module my_flutter
2、修改原生Podfile

flutter_application_path = './my_flutter'
load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')


target 'MyApp' do
  install_all_flutter_pods(flutter_application_path)
end

如果有bitcode的可加上

post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      config.build_settings['ENABLE_BITCODE'] = 'NO'
    end
  end

3、原生项目pod install
4、运行原生项目
5、VSCode打开my_flutter文件夹
6、flutter attach --app-id your.bundle.id
7、原生push Flutter ,pop无效,重新写个啥通知实现。
https://flutter.cn/docs/development/platform-integration/platform-channels#example-project
http://www.muliba.net/flutter/2018/12/09/Flutter-%E5%AD%A6%E4%B9%A04-%E9%9B%86%E6%88%90%E5%88%B0%E5%8E%9F%E6%9C%89%E7%9A%84%E9%A1%B9%E7%9B%AE%E4%B8%AD.html
8、硬上Flutter搞个简单的页面

image.png

55、JSON解析(从Xcode控制台打印的网络请求数据)
复制粘贴入网站或软件内
在线网站解析:https://www.json.cn/
或离线工具解析
http://olivierlabs.com/jason/screenshots.html
http://olivierlabs.com/jason/

54、cellForRowAtIndexPath不调用
现象:
调用了numberOfRowsInSection返回1后,没调用cellForRowAtIndexPath
原因:set方法未正确生命周期调用,导致控件添加到self.view上产生异常‘

粗暴解决:


- (void)reloadTab {
    if ([self.table.superview isEqual: self.view]) {
        [self.table reloadData];
        return;
    }
    NSArray<UITableView *> *subs = [self.view.subviews filter:^BOOL(UIView  *obj) {
        return [obj isKindOfClass:[UITableView class]];
    }];
    if (subs.count > 0) {
        self.table = subs.firstObject;
        [self.table reloadData];
        
        return;
    }
}

53、Xcode不能分屏
https://stackoverflow.com/questions/58054615/xcode-11-wont-open-new-editor-pane

52、Bugly监控

#pragma mark - Bugly
- (void) setupBugly {

    BuglyConfig * config = [[BuglyConfig alloc] init];
    config.consolelogEnable = NO;
    config.blockMonitorEnable = YES;
    config.blockMonitorTimeout = 1.5;
    config.viewControllerTrackingEnable = NO;
    #ifdef DEBUG
    config.debugMode = YES;
    #endif
    
    [Bugly startWithAppId: @"1dgh3453f7"
#ifdef DEBUG
        developmentDevice: YES
#endif
                   config:config];
    [Bugly setUserIdentifier:[NSString stringWithFormat:@"User: %@", [UIDevice currentDevice].name]];
    [Bugly setUserValue:[NSProcessInfo processInfo].processName forKey:@"Process"];
}

- (void)reportExceptionWithReq:(YBBaseRequest *)request responseObject:(id)responseObject {
    if([responseObject isKindOfClass:[NSDictionary class]]) {
        NSDictionary *resDict = (NSDictionary *)responseObject;
        if(![resDict[@"code"] isEqual: @0]) {
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                
                NSString *name = [NSString stringWithFormat:@"接口失败: %@", request.requestIdentifier];
                NSString *pStr = [request.requestParameter yy_modelToJSONString];
                NSString *reason = [NSString stringWithFormat:@"参数: %@\n返回: %@", pStr, [resDict yy_modelToJSONString]];
                [Bugly reportException:[NSException exceptionWithName:name reason: reason userInfo:nil] ];
            });
        }
    }
}

51、不专业UI经常搞些有alpha的图片
50、页面上有个table,tableCell上有个view,view上有个按钮,这个按钮有事件,view上还有个collectionView, collectionView的代理就是这个view,此时不响应didSelectItemAtIndexPath事件
在view上重写方法

-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
// 点到collectionViewCell上里这个居然返回的是nil
    UIView *view = [super hitTest:point withEvent:event];
// 将点转换到collectionView上
    CGPoint newP = [self convertPoint:point toView:self.collectionView];
    for (UICollectionViewCell *cell in self.collectionView.visibleCells) {
        if (CGRectContainsPoint(cell.frame, newP)) {
// 这个点是不是在cell上
            return cell;
        }
    }
// 返回btn,响应btn事件
    return view;
}

另外种场景的事件拦截

-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    UIButton *btn = self.m_eyeBtn;
    // 父控件上的点,如果在子控件的frame里
    if (CGRectContainsPoint(btn.frame, point)) {

        return btn;
    }
    return [super hitTest:point withEvent:event];
}

49、ios post 数组,如下图是接口文档上的传参样式,files就是一个数组。

{
"phone":"13429847337",
"customerName":"测试1",
"tagId":"T20032121331300100",
"intro":"xxx",
"des":"这只是一个描述",
"files":[{"objType":"HEAD_PROTOCOL","files":[{"name":"xxxx.jpg","suffix":"jpg","format":"1"}]}]
}

对于files及其内部的数组里加入的元素保证为JSON,重点就是正面的.yy_modelToJSONObject.

MAFileReq *r1 = [MAFileReq new];
    r1.objType = @"HEAD_PROTOCOL";
    MAObjectFile *obj1 = [MAObjectFile new];
    obj1.name = @"2898D737BA8540EF8DBC63C84F387C74";
    obj1.suffix = @"png";
    obj1.format = @"1";
    r1.files = @[obj1.yy_modelToJSONObject];
    MAFileReq *r2 = [MAFileReq new];
    r2.objType = @"PROTOCOL";
    MAObjectFile *obj2 = [MAObjectFile new];
    obj2.name = @"89E96BEF172A4B4AAD05EEB27A025D57";
    obj2.suffix = @"png";
    obj2.format = @"1";

    r2.files = @[obj2.yy_modelToJSONObject];
    id files = @[r1.yy_modelToJSONObject, r2.yy_modelToJSONObject];

你还得配置好AFN,我就遇到因网络底层没配置好,导致跟后台调试这个接口的数组弄了半年还没好的情况。
manager.requestSerializer = [AFJSONRequestSerializer serializer];
注意json直接就是上面的字典传进来,别转成JSONString了。
[manager POST:urlstr parameters:json progress:nil success...

总结:
之前接口一直报错的原因:
1、参数到AFN时,转成了JSONString,再给给的AFN。
2、manager.requestSerializer 为默认的AFHTTPRequestSerializer
3、没有直接调用 AFN的POST方法,而是这样的

// request
    NSError *requestError = nil;
    NSMutableURLRequest *request = [manager.requestSerializer requestWithMethod:@"POST" URLString:urlstr parameters:nil error:&requestError];
    
    // body
    NSData *postData = [json dataUsingEncoding:NSUTF8StringEncoding];
    [request setHTTPBody:postData];
    
    NSLog(@"\n请求地址: %@ \n请求头:%@", urlstr,manager.requestSerializer.HTTPRequestHeaders);
    NSLog(@"请求参数:%@ \n",  json);
    
    NSURLSessionDataTask *dataTask = [manager.session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _
...
 [dataTask resume];
    return dataTask;

48、
JavaScript execution returned a result of an unsupported type
执行JavaScript返回结果的类型不受支持

原生调用h5一个方法时,一直报错。
后面发现h5写的这个方法有个return this;
this这东西返回给iOS,必然不支持这种返回类型啊。

47、最近xtrafinder有新版本,下载dmg后,有个自动安装的脚本一点后,终端启动不了了居然
https://www.trankynam.com/xtrafinder/

进恢复模式
csrutil enable
46、IB操作下的自动高度table


@interface MAAutoHeightTableView : UITableView
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *tableHeightC;
@end

#import "MAAutoHeightTableView.h"

@implementation MAAutoHeightTableView
- (void)layoutSubviews {
    [super layoutSubviews];
    
    CGFloat realH = self.contentSize.height;
    NSLayoutConstraint *hc = self.tableHeightC;
    if (hc && hc.constant != realH) {
        
        hc.constant = realH;
    }
}


@end


@interface MAAutoHeightCollectionView : UICollectionView
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *collectionViewHeightC;

@end


#import "MAAutoHeightCollectionView.h"

@implementation MAAutoHeightCollectionView
- (void)layoutSubviews {
    [super layoutSubviews];
    
    CGFloat realH = self.contentSize.height;
    NSLayoutConstraint *hc = self.collectionViewHeightC;
    if (hc && hc.constant != realH) {
        
        hc.constant = realH;
    }
}

@end

45、UIMenuController死活显示不出来
升级三方pod 'DoraemonKit/Core', '~> 3.0.0'

44、MacBook Pro可扩展内存不(没有在此表格中列出的 Apple 笔记本配有不可拆卸的内存。)
https://support.apple.com/zh-cn/HT201165

43、清理不可用的模拟器
xcrun simctl delete unavailable

42、MVVM如何实现绑定
MVVM 的实现可以采用KVO进行数据绑定,也可以采用RAC。其实还可以采用block、代理(protocol)实现。
MVVM比起MVC最大的好处就是可以实现自动绑定,将数据绑定在UI组件上,当UI中的值发生变化时,那么它对应的模型中也跟随着发生变化,这就是双向绑定机制,原因在于它在视图层和数据模型层之间实现了一个绑定器,绑定器可以管理两个值,它一直监听组件UI的值,只要发生变化,它将会把值传输过去改变model中的值。绑定器比较灵活,还可以实现单向绑定。

实际开发中的做法:
1、让Controller拥有View和ViewModel属性,VM拥有Model属性;Controller或者View来接收ViewModel发送的Model改变的通知
2、用户的操作点击或者Controller的视图生命周期里面让ViewModel去执行请求,请求完成后ViewModel将返回数据模型化并保存,从而更新了Model;Controller和View是属于V部分,即实现V改变M(V绑定M)。如果不需要请求,这直接修改Model就是了。
3、第2步中的Model的改变,VM是知道的(因为持有关系),只需要Model改变后发一个通知;Controller或View接收到通知后(一般是Controller先接收再赋值给View),根据这个新Model去改变视图就完成了M改变V(M绑定V) 。
使用RAC(RactiveCocoa)框架实现绑定可以简单到一句话概括:ViewModel中创建好请求的信号RACSignal, Controller中订阅这个信号,在ViewModel完成请求后订阅者调用sendNext:方法,Controller里面订阅时写的block就收到回调了。

41、pod search 卡住
rm ~/Library/Caches/CocoaPods/search_index.json

或者确保本地最新pod repo update
然后直接网页搜索最新版本 https://cocoapods.org/

image.png

40、Socket 抓包
自动代理
地址如:https://chls.pro/192.168.1.5:8988.socks.pac

39、view不响应上下拖动手势

// 设置代理
panGesture.delegate = self;

#pragma mark - UIGestureRecognizerDelegate
-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
    if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) {
        // 不响应上下拖动
        UIPanGestureRecognizer *pan = (UIPanGestureRecognizer *)gestureRecognizer;
        CGFloat moveY = [pan translationInView:self].y;
        if (moveY > 0.0f || moveY < 0.0f) {
            return NO;
        }
    }
    return [super gestureRecognizerShouldBegin:gestureRecognizer];
}


38、checkra1n 崩溃

sudo spctl --master-disable

37、升级到Catalina后,Alfred老是搜索不到app
开启Spotlight

sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.metadata.mds.plist

36、接手新项目,调整UI,很麻烦地是找控件,经常会改变某个控件的背景色,来看是不是需要改的目的控件。


image.png

image.png

35、国际化频繁在百度谷歌翻译汉字为英文、韩文很麻烦,自己写了个谷歌插件
https://github.com/songxing10000/iOS-Internationalization-Tool

34、 Btn 默认的图片文字,增加图片文字之间的间距

 btn.titleEdgeInsets = UIEdgeInsetsMake(0, 4, 0, 0);

33、 layer上加图片

    CALayer *imgLayer = [CALayer layer];
    CGImageRef img = [UIImage imageNamed: @"icon"].CGImage;
    imgLayer.frame = CGRectMake(16, 376-80-8, 102, 25);
    imgLayer.contents = (__bridge id _Nullable)(img);
    [self addSublayer: imgLayer];

32、查看今天提交了啥代码

git log --author $GIT_USERNAME --no-merges --since=am |       cat |       grep -v '^commit ' |       grep -v '^Author: ' |       grep -v '^Date: ' |       grep -v "^$" |       tail -r

31、Xcode Application Loader 不见了
11.2.1版本中一直上传不了,准备尝试Application Loader,结果没找到。
去市场下载Transporter
发包建议,导出ipa上传,实际场景经常出现,直接上传失败还得重新等待的耗时场景。
30、UIImageView的startAnimating居然没有效果


// 先清空image,在重新设置一下
self.connectingImageView.image = nil;
 self.connectingImageView.image = [NTESTeamMeetingCollectionViewCell getGifImg];
    [self.connectingImageView startAnimating];

29、升级完系统后,解锁mac输入密码z键不能用。

image.png

再点下右上角的输入法abc就可以了
28、sdwebimage加载图片999
证书问题
项目里有老的证书过期的
更换图片地址上的证书至项目,加载就行,困扰了很久没换证书的原因是,安卓说没加载这个证书,可能系统机制不一样吧,iOS一换证书就正常了。坑,用http也加载不了图片,允许无效ssl也不行。
27、SnippetsLab在mac beta系统上居然不上换字号,
定位偏好文件
~/Library/Containers/com.renfei.SnippetsLab/Data/Library/Preferences/com.renfei.SnippetsLab.plist
修改User EditorFont即可修改字号

<62706c69 73743030 d4010203 04050618 19582476 65727369 6f6e5824 6f626a65 63747359 24617263 68697665 72542474 6f701200 0186a0a4 07081112 55246e75 6c6cd409 0a0b0c0d 0e0f1056 4e535369 7a65584e 5366466c 61677356 4e534e61 6d655624 636c6173 73234038 00000000 00001010 80028003 5d4d656e 6c6f2d52 6567756c 6172d213 1415165a 24636c61 73736e61 6d655824 636c6173 73657356 4e53466f 6e74a215 17584e53 4f626a65 63745f10 0f4e534b 65796564 41726368 69766572 d11a1b54 726f6f74 80010811 1a232d32 373c424b 525b6269 72747678 868b969f a6a9b2c4 c7cc0000 00000000 01010000 00000000 001c0000 00000000 00000000 00000000 00ce>

26、vscode跳转方法
Ctrl+Shift+O
25、在用vscode写weex时,之前一直有个功能不爽,就是点class时不会跳转,但是现在有个插件实现了此功能
https://marketplace.visualstudio.com/items?itemName=chenzefeng.ymt-weex-vscode&ssr=false#overview
template里点某个class跳转去了style,再按control-可回来
24、swif4过滤元素
比如从一个数组中取某个id的元素
之前的做法是用filter
更高效的方法是 first

// 此方法,来自 [https://www.objc.io/blog/2018/06/14/quick-performance-timing/](https://www.objc.io/blog/2018/06/14/quick-performance-timing/)

@discardableResult
func measure<A>(name: String = "", _ block: () -> A) -> A {
    let startTime = CACurrentMediaTime()
    let result = block()
    let timeElapsed = CACurrentMediaTime() - startTime
    print("Time: \(name) - \(timeElapsed)")
    return result
}

measure {
    let numbers = [1, 2, 3, 4, 5, -4, 2, 4]
    if let firstNegative = numbers.first(where: { $0 < 0 }) {
        print(firstNegative)
    }
}
measure {
    let numbers = [1, 2, 3, 4, 5, -4, 2, 4]
    if let firstNegative = numbers.filter({$0 < 0}).first {
        print(firstNegative)
    }
}

但是用我之前的filter再first明显比直接用first更高效,但是写法上first这个更简洁


Snip20190828_1.png
Snip20190828_2.png

23、js判断数组,es6判断是数组

Array.isArray([]); // => true 
Array.isArray({0: 'a', length: 1}); // => false

22、项目太卡,可利用 InjectionIII结合模拟器
https://github.com/johnno1962/InjectionIII
Swift4.0 + Xcode10.3测试成功
1、下载https://github.com/johnno1962/InjectionIII/releases
2、appdelegate处载入

        #if DEBUG
        Bundle(path: "/Applications/InjectionIII.app/Contents/Resources/iOSInjection.bundle")?.load()
        #endif

3、需要经常调试的位置载入

    @objc func injected(){
        
        print("I've been injected: \(self)")
        self.title = "??å"
        self.cellImageConfig=[]
        self.cellTitleConfig=[]
        self.tableView.reloadData()
//        self.viewDidLoad()
//        self.viewWillAppear(true)
//        self.viewDidAppear(true)
        
    }

20、对软件进行重签名
准备工作
安装xcode
安装xCode,你可以在App Store中下载安装,并且至少运行一次。

安装Command Line Tools 工具
打开终端工具输入如下命令:
xcode-select --install
弹出后选择继续安装。

签名
打开终端工具输入并执行如下命令:
codesign --force --deep --sign - /Applications/name.app

注意后面的文件路径,你可以打开访达找到应用程序,找到要签名的软件,直接拖入 终端 界面,即可自动生成路径。
19、swift4队列组简单使用

/// 1、vc上加个属性
    private let m_group = DispatchGroup()
/// 2、加入一个任务
        m_group.enter()
///  在这个任务的成功和失败回调里执行             `self.m_group.leave()`

        task1()
        /// 3、加入一个任务
        m_group.enter()
///  在这个任务的成功和失败回调里执行    
        task2()
        /// 4、执行最后的任务
        m_group.notify(queue: .main, execute:{
           // 你的代码
        })

18、网易云信图片崩溃,云信黑图
原因,webP格式

# 兼容云信接收webP格式的图片
    pod 'SDWebImage', '~> 4.2.3'
    pod 'SDWebImage/WebP'
#import <UIImage+WebP.h>
#import <NSData+ImageContentType.h>

/// 原来直接加载图片
    UIImage * image              = [UIImage imageWithContentsOfFile:imageObject.thumbPath];
/// 这里判断下webP
    if([[NSFileManager defaultManager] fileExistsAtPath: imageObject.thumbPath]){
        NSData *imgData = [NSData dataWithContentsOfFile:imageObject.thumbPath];
        if ([NSData sd_imageFormatForImageData:imgData] == SDImageFormatWebP) {
            image = [UIImage sd_imageWithWebPData:imgData];
        }
    }

17、项目太卡,对比UI还原度时
a、使用最新x的Reveal

    pod 'Reveal-iOS-SDK', :configurations => ['Debug']

加上Reveal
b、腾讯出品的Lookin
pod 'LookinServer', :configurations => ['Debug']
加上Lookin

image.png

16、swift discardableResult

///   表示取消不使用返回值的警告
@discardableResult
    func isLogin(jump: Bool, success: Closure = nil, failed: Closure = nil) -> Bool

15、自定义CollectionView布局:常规挨着布局、九宫格布局、田字格布局
常规挨着布局

image.png


@interface MACustomFlowLayout : UICollectionViewFlowLayout

@end


#import "MACustomFlowLayout.h"

@implementation MACustomFlowLayout
- (NSArray *) layoutAttributesForElementsInRect:(CGRect)rect {

   // 获取系统默认的布局信息
   NSArray *layoutAttributes = [super layoutAttributesForElementsInRect:rect];
    
for(int i = 1; i < [layoutAttributes count]; ++i) {
  UICollectionViewLayoutAttributes *currentLayoutAttributes = layoutAttributes[i];
        UICollectionViewLayoutAttributes *prevLayoutAttributes = layoutAttributes[i - 1];
   // cell之间的间距为17        
   NSInteger maximumSpacing = 17;
   NSInteger origin = CGRectGetMaxX(prevLayoutAttributes.frame);
        
   if(origin + maximumSpacing + currentLayoutAttributes.frame.size.width < self.collectionViewContentSize.width) {
   // 如果上个cell的maxX 加上间距加上当前cell的宽度没超过collectionView
            CGRect frame = currentLayoutAttributes.frame;
            frame.origin.x = origin + maximumSpacing;
            currentLayoutAttributes.frame = frame;
        }
    }
    return layoutAttributes;
}
@end

九宫格布局、田字格布局

image.png

image.png
image.png
image.png
import UIKit
private let kItemMargin: CGFloat = 8
private let kSectionLRMargin: CGFloat = 15
private let kOneRowItemCount: Int = 3
private let itemWH: CGFloat = (UIScreen.main.bounds.size.width - 2*kSectionLRMargin-(CGFloat(kOneRowItemCount)-1)*kItemMargin)/CGFloat(kOneRowItemCount)

class CustomLayout : UICollectionViewFlowLayout {

    override func prepare() {
        super.prepare()
        
        scrollDirection = .vertical
        
        minimumLineSpacing = kItemMargin
        minimumInteritemSpacing = kItemMargin
        sectionInset = UIEdgeInsets(top: 0, left: kSectionLRMargin, bottom: 0, right: kSectionLRMargin)
        
        itemSize = CGSize(width: itemWH, height: itemWH)
    }
    // 内容区域总大小,不是可见区域
    override var collectionViewContentSize: CGSize {
        let needWidth = collectionView!.bounds.size.width - collectionView!.contentInset.left
            - collectionView!.contentInset.right
        /// 一共有多少行
        var rows: Int = collectionView!.numberOfItems(inSection: 0) / kOneRowItemCount
        if collectionView!.numberOfItems(inSection: 0) % kOneRowItemCount != 0 {
            // 能取到余说明还得占用一行
            rows += 1
        }

        let needHeight: CGFloat = CGFloat(rows) * itemWH + (CGFloat(rows) - 1) * kItemMargin+collectionView!.contentInset.top+collectionView!.contentInset.bottom
        return CGSize(width: needWidth, height: needHeight)
    }
//    
    // 所有单元格位置属性
    override func layoutAttributesForElements(in rect: CGRect)
        -> [UICollectionViewLayoutAttributes]? {
            var attributesArray = [UICollectionViewLayoutAttributes]()
            let cellCount = self.collectionView!.numberOfItems(inSection: 0)
            for i in 0..<cellCount {
                let indexPath =  IndexPath(item:i, section:0)
                let attributes =  self.layoutAttributesForItem(at: indexPath)
                attributesArray.append(attributes!)
            }
            return attributesArray
    }
    
    // 这个方法返回每个单元格的位置和大小
    override func layoutAttributesForItem(at indexPath: IndexPath)
        -> UICollectionViewLayoutAttributes? {
            
            let attribute =  UICollectionViewLayoutAttributes(forCellWith:indexPath)
            
            /// 当前所在行号从0开始数起
            var itemRowNum:Int =  indexPath.item / kOneRowItemCount
            /// 当前所在列号从0开始处
            var itemColNum: Int =  indexPath.item % kOneRowItemCount
            if  collectionView!.numberOfItems(inSection: 0) == 4 , indexPath.item > 1{
                // 默认正常九宫格,当为4个时,田布局
                itemRowNum = 1
                itemColNum = indexPath.item % 2
            }
            let itemY =  (itemWH + kItemMargin) * CGFloat(itemRowNum)
            // 从左入右排
//            let itemX = kSectionLRMargin + (itemWH+kItemMargin) * CGFloat(itemColNum)
            // 从右往右排
            let itemX = UIScreen.main.bounds.size.width -
                (kSectionLRMargin + (itemWH+kItemMargin) * CGFloat(itemColNum)) - itemWH
            attribute.frame = CGRect(x: itemX, y: itemY, width: itemWH, height: itemWH)
            
            return attribute
    }
    
}

14、weex平台判定,style绑定

export const isWeb = WXEnvironment.platform === 'Web';    
 :style="{width: width + 'px'}" 
:style="{width: (width * domLen) + 'px'}" 

13、swift4解析推送里的串

deviceToken.map { String(format: "%02.2hhx", $0) }.joined()

12、js 数组过滤

this.rows = this.rows.filter(function(value, index, arr){
          return value.id != 8;
   } )

11、swift中闭包类型别名

typealias ActivityCellBlock = ((IndexPath, ActivityCellEvent) -> Void)

应该使用泛型别名通用闭包

10、Swift中如果数组不与NSArray交互尽量使用ContiguousArray

private let hashInitialValue: ContiguousArray<UInt32> = [0x67452301]

9、Swift中如果类不被重写尽量使用 final

8、VS Code 回到上一个浏览位置
Ctrl + -

7、weex自动提示属性
https://zhuanlan.zhihu.com/p/42163515

一般类型

/**

 * @type {number[]}

 */

let numList;

/** 

 * @type {Array<string>} 

 */

let strList;

定义好了的对象类型

/**

 * @type {user[]} 

 */

let userList;

/** 

 * @type {goods[]} 

 */

let goodsList;

在script最尾部,加入类型注释,然后在用到的地方指名类型,敲属性时就有提示了

1、尾部申明

/**

 * *@typedef* {Object} goods 

 * *@prop* {string} name 这里name的一个注释

 * *@prop* {number} code 这里code的一个注释

 */

</script>

2、用处指明类型

/**  

* *@type* {goods}  

 */

 *let* phone;

这样在敲 [phone.co](http://phone.co)的时候就会有code这是一个注释的提示了

6、weex中之前写在body里的参数转换成get方式拼接
https://howchoo.com/g/nwywodhkndm/how-to-turn-an-object-into-query-string-parameters-in-javascript

var queryString = Object.keys(params).map(key => key + '=' + params[key]).join('&');

5、控制台pod obj baseModel自动打印属性

extension CustomStringConvertible {
    var description : String {
        var description: String =  "***** \(type(of: self))  <\(Unmanaged.passUnretained((self as AnyObject)).toOpaque()) >***** \n"
        
        let selfMirror = Mirror(reflecting: self)
        for child in selfMirror.children {
            if let propertyName = child.label {
                description += "\(propertyName): \(child.value)\n"
            }
        }
        return description
    }
}

4、JSON could not be serialized because of erro时看服务器到底返回的啥
https://stackoverflow.com/questions/54674453/json-could-not-be-serialized-because-of-error

image.png

if let data = response.data,
     let str = String(data: data, encoding: String.Encoding.utf8){
                        
       print("Server Error: \(str)")
  } 

3、拖线private

@IBOutlet private weak var userNameLabel: UILabel!

2、swift4 CGFloat max

CGFloat.greatestFiniteMagnitude

1、swift访问不了宏定义

#define KWBDetailTopMargin  15   //邻里圈详情顶部留白
#define KWBExpendButtonWidth 35  //展开的收缩按钮宽度
#define KWBExpendButtonHeight 22 //展开收缩按钮高度

直接在swift定义

import UIKit
//// 邻里圈宽高宏定义
let KWBDetailTopMargin: CGFloat =   15
/// 邻里圈详情顶部留白
let KWBExpendButtonWidth: CGFloat =   35
/// 展开的收缩按钮宽度
let KWBExpendButtonHeight: CGFloat =   22

oc的访问不了swift的,swift的访问不了OC的,互不打扰。

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

推荐阅读更多精彩内容

  • 记录下日常开发中遇到的问题。Q1:idea中执行maven命令控制台中文乱码。A:需要在idea的设置中修改mav...
    不会游泳的余先生阅读 173评论 0 0
  • iOS OC 转 Swift开发问题记录 之前一直使用OC语言开发iOS应用,时代在进步,使用Swift语言开发已...
    Cocoa_Coder阅读 662评论 0 1
  • 我是黑夜里大雨纷飞的人啊 1 “又到一年六月,有人笑有人哭,有人欢乐有人忧愁,有人惊喜有人失落,有的觉得收获满满有...
    陌忘宇阅读 8,520评论 28 53
  • 信任包括信任自己和信任他人 很多时候,很多事情,失败、遗憾、错过,源于不自信,不信任他人 觉得自己做不成,别人做不...
    吴氵晃阅读 6,180评论 4 8
  • 怎么对待生活,它也会怎么对你 人都是哭着来到这个美丽的人间。每个人从来到尘寰到升入天堂,整个生命的历程都是一本书,...
    静静在等你阅读 4,956评论 1 6