仿网易云信结构   Xcode主工程建立多个子工程结合联编开发SDK

仿网易云信结构   Xcode主工程建立多个子工程结合联编开发SDK

1.新建Project  ZIKIMDemo.  Single View App .   

2.ZIKIMDemo文件下新建 ZIKIMDemo.workspace 

3.SDK新建文件下 新建Project ZIKIMKit   . Static libary.

4.关闭这两个新建的project.

5.打开workspace,添加 ZIKIMKit Project. 添加ZIKIMDemo Project.

platform :ios, ‘9.0’

# 忽略引入库的所有警告(强迫症者的福音啊)

inhibit_all_warnings!

workspace ‘KIMDemo.xcworkspace’

abstract_target ‘KIMDemo’ do

    pod ‘SDWebImage’

    pod ‘Toast’

    pod ‘M80AttributedLabel’

    pod ‘TZImagePickerController’

    pod ‘Socket.IO-Client-Swift’, ‘~> 11.1.3’

    pod ‘YYKit’

    pod ‘MJRefresh’

    pod ‘AFNetworking’

    pod ‘Masonry’

    pod ‘SDCycleScrollView’

    pod ‘MBProgressHUD’

    #高德地图相关SDK(无IDFA版)

    pod ‘AMapLocation-NO-IDFA’

    pod ‘AMapSearch-NO-IDFA’

    pod ‘AMap2DMap-NO-IDFA’

    

    #友盟分享

    #友盟分享 中的UMSocialPlatformConfig.h 有改动,pod 更新友盟分享时 记得改

    # U-Share SDK UI模块(分享面板,建议添加)

    pod ‘UMengUShare/UI’

    # 集成微信(精简版0.2M)

    pod ‘UMengUShare/Social/ReducedWeChat’

    # 集成QQ/QZone/TIM(精简版0.5M)

    pod ‘UMengUShare/Social/ReducedQQ’

    # 集成新浪微博(精简版1M)

    pod ‘UMengUShare/Social/ReducedSina’

    target ‘KIMDemo’ do

        project ‘KIMDemo.xcodeproj’

        pod ‘FMDB’

        pod ‘Reachability’

        pod ‘CocoaLumberjack’

        pod ‘SSZipArchive’

        pod ‘SVProgressHUD’

        pod ‘Fabric’

        pod ‘Crashlytics’

    end

    

    target ‘KIMKit’ do

        project ‘../KIMKit/KIMKit.xcodeproj’

    end

end

Downloading dependencies

Installing AFNetworking (3.2.0)

Installing AMap2DMap-NO-IDFA (5.6.0)

Installing AMapFoundation-NO-IDFA (1.4.3)

Installing AMapLocation-NO-IDFA (2.6.0)

Installing AMapSearch-NO-IDFA (6.1.0)

Installing CocoaLumberjack (3.4.2)

Installing Crashlytics (3.10.1)

Installing FMDB (2.7.2)

Installing Fabric (1.7.6)

Installing M80AttributedLabel (1.6.3)

Installing MBProgressHUD (1.1.0)

Installing MJRefresh (3.1.15.3)

Installing Masonry (1.1.0)

Installing Reachability (3.2)

Installing SDCycleScrollView (1.75)

Installing SDWebImage (4.3.3)

Installing SSZipArchive (2.1.2)

Installing SVProgressHUD (2.2.5)

Installing Socket.IO-Client-Swift (11.1.3)

Installing StarscreamSocketIO (8.0.7)

Installing TZImagePickerController (2.1.0.2)

Installing Toast (4.0.0)

Installing UMengUShare (6.4.8.2)

Installing YYKit (1.0.9)

Generating Pods project

隐藏tabbar之后在原位置新建View不响应点击事件的方法

这里指的不是跳转页面之后隐藏tabbar,如果是跳转后隐藏直接hidebarButtonItem = yes就搞定,这里是本页面隐藏之后在原tabbar位置新建一个view,并在view上添加按钮,但是接受不到点击事件,在网上看了很多人都遇到这个问题,但是解释的都不够,后来自己摸索了一个方法,拿来分享,欢迎指正。

首先就是两个方法,隐藏和显示tabbar

#pragma mark – 隐藏Tabbar

– (void)hideTabBar {

    if (self.tabBarController.tabBar.hidden == YES) {

        return;

    }

    UIView *contentView;

    if ( [[self.tabBarController.view.subviews objectAtIndex:0] isKindOfClass:[UITabBar class]] )

        contentView = [self.tabBarController.view.subviews objectAtIndex:1];

    else

        contentView = [self.tabBarController.view.subviews objectAtIndex:0];

    contentView.frame = CGRectMake(contentView.bounds.origin.x,  contentView.bounds.origin.y,  contentView.bounds.size.width, contentView.bounds.size.height + self.tabBarController.tabBar.frame.size.height);

    self.tabBarController.tabBar.hidden = YES;

}

#pragma mark – 展示Tabbar

– (void)showTabBar

{

    if (self.tabBarController.tabBar.hidden == NO)

    {

        return;

    }

    UIView *contentView;

    if ([[self.tabBarController.view.subviews objectAtIndex:0] isKindOfClass:[UITabBar class]])

        contentView = [self.tabBarController.view.subviews objectAtIndex:1];

    else {

        contentView = [self.tabBarController.view.subviews objectAtIndex:0];

    }

    contentView.frame = CGRectMake(contentView.bounds.origin.x, contentView.bounds.origin.y,  contentView.bounds.size.width, contentView.bounds.size.heightself.tabBarController.tabBar.frame.size.height);

    self.tabBarController.tabBar.hidden = NO;

}

在你需要调用的地方调用这两个函数就可以了,然而重点并不在这里,这些代码百度到处都是,重点是,当你隐藏之后在原位置添加一个VIew但是接受不到点击事件,一开始遇到这个问题我认为是View的交互事件没有打开,因为新建的View可以显示,并没有被遮住,说这么多,一句最简单的代码搞定问题

[self.tabBarController.view addSubview:viewForEidit];

其中viewForEdit是我自己新建的view,初始化过程等就不赘述了。尝试很多方法后,之前一直是把viewForEdit加在self.view上,所以一直无果。这里面的机制我也没有搞清楚,但是就是可以实现。希望大家明白深入一点的可以多指教。

IOS 正则表达式匹配文本中URL位置并获取URL所在位置(解决连接中文问题)

需求很简单,是从一段文本中匹配出其中的超链接。基本的做法就是用正则表达式去匹配。但是有这样一个问题。

网上大部分的识别URL的正则表达式url末尾有空格的情况下可以正确识别。比如这样的情况。

static NSString *M80URLExpression = @”((([A-Za-z]{3,9}:(?:\\/\\/)?)(?:[\\-;:&=\\+\\$,\\w]+@)?[A-Za-z0-9\\.\\-]+|(?:www\\.|[\\-;:&=\\+\\$,\\w]+@)[A-Za-z0-9\\.\\-]+)((:[0-9]+)?)((?:\\/[\\+~%\\/\\.\\w\\-]*)?\\??(?:[\\-\\+=&;%@\\.\\w]*)#?(?:[\\.\\!\\/\\\\\\w]*))?)”;

我是一段中文https://github.com/TinyQ 我还是一段中文

但是如果去掉TinyQ 后面的空格。匹配到的将是 “https://github.com/TinyQ我还是一段中文” 是连上的。

最后替换过好多正则才得以解决。这里贴上代码:

复制代码
NSError *error;
    NSString *regulaStr = @"\\bhttps?://[a-zA-Z0-9\\-.]+(?::(\\d+))?(?:(?:/[a-zA-Z0-9\\-._?,'+\\&%$=~*!():@\\\\]*)+)?";
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:regulaStr
                                                                           options:NSRegularExpressionCaseInsensitive
                                                                             error:&error];
    NSArray *arrayOfAllMatches = [regex matchesInString:string options:0 range:NSMakeRange(0, [string length])];
    
    for (NSTextCheckingResult *match in arrayOfAllMatches)
    {
        NSString* substringForMatch = [string substringWithRange:match.range];
     NSLog(@"substringForMatch");
    }
复制代码

这里做个更新。下面这个正则也是可以的。而且应该更好一些。

比如这种 Explorerwww.chiphell.com/ 。 也是可以识别出 www.chjiphell.com 的

((http[s]{0,1}|ftp)://[a-zA-Z0-9\\.\\-]+\\.([a-zA-Z]{2,4})(:\\d+)?(/[a-zA-Z0-9\\.\\-~!@#$%^&*+?:_/=<>]*)?)|(www.[a-zA-Z0-9\\.\\-]+\\.([a-zA-Z]{2,4})(:\\d+)?(/[a-zA-Z0-9\\.\\-~!@#$%^&*+?:_/=<>]*)?)

iOS11文件存储最佳实践(转)

iOS11文件存储最佳实践

众所周知,iOS11之前的版本我们无法看到应用里边的任何文件,这主要是由于iOS的沙盒机制导致的。在我们应用的沙盒里边,有三个文件夹供我们使用来存储文件。分别是DocumentsLibrarytmp

  • Documents
    您应该将所有的应用程序数据文件写入到这个目录下。这个目录用于存储用户数据。该路径可通过配置实现iTunes共享文件。可被iTunes备份。
  • Library
    Preferences 目录:包含应用程序的偏好设置文件。您不应该直接创建偏好设置文件,而是应该使用NSUserDefaults类来取得和设置应用程序的偏好.
    Caches 目录:用于存放应用程序专用的支持文件,保存应用程序再次启动过程中需要的信息。
    可创建子文件夹。可以用来放置您希望被备份但不希望被用户看到的数据。该路径下的文件夹,除Caches以外,都会被iTunes备份。
  • tmp
    这个目录用于存放临时文件,保存应用程序再次启动过程中不需要的信息。该路径下的文件不会被iTunes备份。

不过由于iOS11系统中增加了一个Files的应用,导致DocumentsLibrary有些细微的变化。

Files 是什么

Files 可以集中管理iOS上应用内创建的文件,以及各个云盘服务中保存的文件。

Files使用

Files会自动整合应用内公开的所有文件,其实就是Documents文件夹中所有的文件。但是有时候我们存储的用户的数据不想让用户看到,这时应该怎么办呢?这时候我们可以将数据存储到ApplicationSupport文件夹。这个文件夹与Documents基本一样,除了一个能被用户看到,一个是隐藏的。

实践

我们新建一个工程,然后在Info.plist中增加Application supports iTunes file sharing和Supports opening documents in place这两个选项,并且设置为YES
1519629565974.jpg

Application supports iTunes file sharing 可以通过iTunes操作手机上APP的Documents中的内容,实现了文件的共享

加上了这两个值之后,此时应用的Documents文件夹中的内容就可以通过Files应用看到了。
WechatIMG31.jpeg
WechatIMG32.jpeg

设置Documents或Library文件夹下的文件不被备份至iCloud

1
2
3
4
5
6
7
8
9
10
11
12
13
– (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
{
assert([[NSFileManager defaultManager] fileExistsAtPath: [URL path]]);
NSError *error = nil;
BOOL success = [URL setResourceValue:[NSNumber numberWithBool: YES]
forKey: NSURLIsExcludedFromBackupKey error: &error];
if(!success){
NSLog(@”Error excluding %@ from backup %@”, [URL lastPathComponent], error);
}
return success;
}

检查可用空间大小

主要用于当我们下载某个文件到手机的时候,如果此时手机的存储空间不够用,可以先提示用户。否则不会下载,增加用户的体验

1
2
3
4
5
6
7
8
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:NSTemporaryDirectory()];
NSError *error = nil;
NSDictionary *results = [fileURL resourceValuesForKeys:@[NSURLVolumeAvailableCapacityForImportantUsageKey] error:&error];
if (!results) {
NSLog(@”Error retrieving resource keys: %@\n%@”, [error localizedDescription], [error userInfo]);
abort();
}
NSLog(@”Available capacity for important usage: %@”, results);
  • NSURLVolumeAvailableCapacityKey 获取到整个手机剩余的可用空间
  • NSURLVolumeTotalCapacityKey 获取到整个手机的存储空间,比如32G的手机获取的数据时32G
  • NSURLVolumeAvailableCapacityForImportantUsageKey和NSURLVolumeAvailableCapacityForOpportunisticUsageKey 第一个获取的空间比第二个获取到的大。具体怎么计算的不知道,NSURLVolumeAvailableCapacityForImportantUsageKey与NSURLVolumeAvailableCapacityKey获取的值比较接近;NSURLVolumeAvailableCapacityForOpportunisticUsageKey获取到的值比NSURLVolumeAvailableCapacityKey小一些。作者猜想可能这几个枚举与沙河里边的文件夹相对应吧。(如果有知道具体怎么回事的可以留言哦)

使用virtualenv搭建独立的Python环境(转)

http://blog.51cto.com/qicheng0211/1561685

virtualenv可以搭建虚拟且独立的python环境,可以使每个项目环境与其他项目独立开来,保持环境的干净,解决包冲突问题。

一、安装virtualenv

virtualenv实际上是一个python包,所以我们可以用easy_install或者pip安装。下面介绍在CentOS系统上的安装方法。

easy_install安装方式:

1
2
[root@localhost ~]# yum install python-setuptools python-devel
[root@localhost ~]# easy_install virtualenv

pip安装方式:

1
2
[root@localhost ~]# easy_install pip
[root@localhost ~]# pip install virtualenv

yum安装方式(epel源):

1
[root@localhost ~]# yum install python-virtualenv

二、创建python虚拟环境

使用virtualenv命令创建python虚拟环境:virtualenv [虚拟环境名称]。

1
2
3
[root@localhost ~]# virtualenv env1
New python executable in env1/bin/python
Installing setuptools, pip...done.

执行后,在本地会生成一个与虚拟环境同名的文件夹。

如果你的系统里安装有不同版本的python,可以使用–python参数指定虚拟环境的python版本:

1
2
3
4
5
[root@localhost ~]# virtualenv --python=/usr/local/python-2.7.8/bin/python2.7 env1
Running virtualenv with interpreter /usr/local/python-2.7.8/bin/python2.7
New python executable in env1/bin/python2.7
Also creating executable in env1/bin/python
Installing setuptools, pip...done.

实测默认情况下虚拟环境不会依赖系统环境的global site-packages。比如系统环境里安装了MySQLdb模块,在虚拟环境里import MySQLdb会提示ImportError。如果想依赖系统环境的第三方软件包,可以使用参数–system-site-packages。此外,也可使用virtualenvwrapper的toggleglobalsitepackages命令控制当前环境是否使用global site-packages。

1
2
3
[root@localhost ~]# virtualenv --system-site-packages env1
New python executable in env1/bin/python
Installing setuptools, pip...done.

三、启动虚拟环境

进入虚拟环境目录,启动虚拟环境,如下:

1
2
3
4
[root@localhost ~]# cd env1/
[root@localhost env1]# source bin/activate
(env1)[root@localhost env1]# python -V
Python 2.7.8

此时命令行前面会多出一个括号,括号里为虚拟环境的名称。以后easy_install或者pip安装的所有模块都会安装到该虚拟环境目录里。

四、退出虚拟环境

退出虚拟环境:deactivate

1
2
(env1)[root@localhost env1]# deactivate
[root@localhost env1]#

五、使用virtualenvwrapper

virtualenvwrapper是virtualenv的扩展工具,可以方便的创建、删除、复制、切换不同的虚拟环境。

1.安装virtualenvwrapper

1
[root@localhost ~]# easy_install virtualenvwrapper

或者:

1
[root@localhost ~]# pip install virtualenvwrapper

创建一个文件夹,用于存放所有的虚拟环境:

1
[root@localhost ~]# mkdir ~/workspaces

设置环境变量,把下面两行添加到~/.bashrc里。

1
2
[root@localhost ~]# export WORKON_HOME=~/workspaces
[root@localhost ~]# source /usr/bin/virtualenvwrapper.sh

然后就可以使用virtualenvwrapper了。
2.创建虚拟环境:mkvirtualenv [虚拟环境名称]

1
2
3
4
5
6
7
[root@localhost ~]# mkvirtualenv env1
New python executable in env1/bin/python
Installing setuptools, pip...done.
(env1)[root@localhost ~]# mkvirtualenv env2
New python executable in env2/bin/python
Installing setuptools, pip...done.
(env2)[root@localhost ~]#

注意:mkvirtualenv可以使用virtualenv的参数,比如–python来指定python版本。创建虚拟环境后,会自动切换到此虚拟环境里。虚拟环境目录都在WORKON_HOME里。

3.列出虚拟环境:lsvirtualenv -b

1
2
3
(env2)[root@localhost ~]# lsvirtualenv -b
env1
env2

4.切换虚拟环境:workon [虚拟环境名称]

1
2
3
(env2)[root@localhost ~]# workon env1
(env1)[root@localhost ~]# echo $VIRTUAL_ENV
/root/workspaces/env1

5.查看环境里安装了哪些包:lssitepackages

6.进入当前环境的目录:cdvirtualenv [子目录名]

1
2
3
4
5
6
(env1)[root@localhost ~]# cdvirtualenv
(env1)[root@localhost env1]# pwd
/root/workspaces/env1
(env1)[root@localhost env1]# cdvirtualenv bin
(env1)[root@localhost bin]# pwd
/root/workspaces/env1/bin

进入当前环境的site-packages目录:cdsitepackages [子目录名]

1
2
3
4
5
6
(env1)[root@localhost env1]# cdsitepackages
(env1)[root@localhost site-packages]# pwd
/root/workspaces/env1/lib/python2.6/site-packages
(env1)[root@localhost site-packages]# cdsitepackages pip
(env1)[root@localhost pip]# pwd
/root/workspaces/env1/lib/python2.6/site-packages/pip

7.控制环境是否使用global site-packages:toggleglobalsitepackages

8.复制虚拟环境:cpvirtualenv [source] [dest]

1
2
3
[root@localhost ~]# cpvirtualenv env1 env3
Copying env1 as env3...
(env3)[root@localhost ~]#

9.退出虚拟环境:deactivate

10.删除虚拟环境:rmvirtualenv [虚拟环境名称]

1
2
[root@localhost ~]# rmvirtualenv env2
Removing env2...

欢迎2018

犹记得小时候满大街的衬衫上标着2008,那时觉得2008年的奥运会还早,还有好几年呢!2008高二,高中的记忆属于幸福和被试卷反复打磨的规律生活。暗恋也有点甜蜜,一起坐车回家都很紧张的温暖。2008,奥运会开幕式,为了祖国的强大而情不自禁,看到如此宏伟的开幕式,自豪感让喉咙很蓝受,香菇。2018飞逝而来,迎面而来的是家庭的责任,过去的一年人生最美好的礼物是有了可爱的宝贝儿子小树苗,小家伙很可爱,有个贤惠,而且能忍让我的媳妇也是人生幸事,谢谢你亲爱的,为了这个家付出了太多辛劳。我是幸福的,幸福的生活是父母给的,天使是存在的那就是我们的父母,无怨无悔任劳任怨,还能说些什么感谢的话呢,人世间没有可以表达的这份爱意。谢谢父母的爱,宇宙的时间刻度会停留在这辈子,为了这无法报答的爱。2018.1.2,为了我爱的人,也为了爱我的人,我需要更加努力的工作。只希望家人平安健康幸福,朋友们健康如意。2018,欢迎你的到来。敬那些逝去的岁月,敬那些逝去的美好,敬现今以后美好的生活,敬2018.