iOS开发 - Swift实现检测网络连接状态及网络类型

一、前言

在移动开发中,检测网络的连接状态尤其检测网络的类型尤为重要。本文将介绍在iOS开发中,如何使用Swift检测网络连接状态及网络类型(移动网络、Wifi)。

二、如何实现

Reachability.swift 是一个使用Swift写的第三方网络检测类,可以用来检测网络连接状态及网络类型(移动网络、Wifi)功能。

三、如何使用

1. 使用Cocopod安装Reachability.swift

use_frameworks!
pod 'ReachabilitySwift'

2. 基本使用代码示例

使用前记得导入ReachabilitySwift类,下面代码放在viewDidLoad()方法中即可。

var reachability: Reachability!

do {
    reachability = try Reachability.reachabilityForInternetConnection()
} catch {
    print("Unable to create Reachability")
    return
}

// 检测网络连接状态
if reachability.isReachable() {
    print("网络连接:可用")
} else {
    print("网络连接:不可用")
}

// 检测网络类型
if reachability.isReachableViaWiFi() {
    print("网络类型:Wifi")
} else if reachability.isReachableViaWWAN() {
    print("网络类型:移动网络")
} else {
    print("网络类型:无网络连接")
}

3. 监听网络变化

// 网络可用或切换网络类型时执行
reachability.whenReachable = { reachability in
    
    // 判断网络状态及类型
}

// 网络不可用时执行
reachability.whenUnreachable = { reachability in
    
    // 判断网络状态及类型
}

do {
    // 开始监听
    try reachability.startNotifier()
} catch {
    print("Unable to start notifier")
}

停止监听调用reachability.stopNotifier()即可。

四、项目地址

Github地址:https://github.com/ashleymills/Reachability.swift


交友互动:

本文首发于马燕龙个人博客,欢迎分享,转载请标明出处。
马燕龙个人博客:https://www.mayanlong.com
马燕龙个人微博:http://weibo.com/imayanlong
马燕龙Github主页:https://github.com/yanlongma

iOS开发 - Swift使用JavaScriptCore与JS交互

一、前言

在这个提倡敏捷开发和H5横行的年代,原生App内嵌入一些H5页面已经成为一种流行的趋势。一套H5页面就可以适配复杂的iOS和Android页面,大量节省了开发和维护时间,如果本来就有移动端网页,只需简单适配即可完成,那我们何乐而不为呢?苹果也顺应了潮流,在iOS7中提供了JavaScriptCore框架用来与网页中的JS进行交互。还有Facebook推出的React Native,也给跨平台开发提供了新的思路和解决方案,虽然目前它还不是很成熟。但作为一个开发者,对这些新技术的出现自然会感到无比的兴奋。本文主要介绍iOS开发中,Swift如何使用JavaScriptCore与网页中的JS进行交互。

二、JavaScriptCore中的类

  • JSContext:JSContext是JS的执行环境,通过evaluateScript()方法可以执行JS代码
  • JSValue:JSValue封装了JS与ObjC中的对应的类型,以及调用JS的API等
  • JSExport:JSExport是一个协议,遵守此协议,就可以定义我们自己的协议,在协议中声明的API都会在JS中暴露出来,这样JS才能调用原生的API

三、交互方式主要有两种

一)、 在Swift中,通过JSContext直接执行JS代码

import JavaScriptCore    //记得导入JavaScriptCore


// 通过JSContext执行js代码
let context: JSContext = JSContext()
let result1: JSValue = context.evaluateScript("1 + 3")
print(result1)  // 输出4

// 定义js变量和函数
context.evaluateScript("var num1 = 10; var num2 = 20;")
context.evaluateScript("function sum(param1, param2) { return param1 + param2; }")

// 通过js方法名调用方法
let result2 = context.evaluateScript("sum(num1, num2)")
print(result2)  // 输出30

// 通过下标来获取js方法并调用方法
let squareFunc = context.objectForKeyedSubscript("sum")
let result3 = squareFunc.callWithArguments([10, 20]).toString()
print(result3)  // 输出30

二). 在Swift中通过JSContext注入模型,然后调用模型的方法

1. 首先定义定义协议SwiftJavaScriptDelegate 该协议必须遵守JSExport协议

@objc protocol SwiftJavaScriptDelegate: JSExport {
    
    // js调用App的微信支付功能 演示最基本的用法
    func wxPay(orderNo: String)
    
    // js调用App的微信分享功能 演示字典参数的使用
    func wxShare(dict: [String: AnyObject])
    
    // js调用App方法时传递多个参数 并弹出对话框 注意js调用时的函数名
    func showDialog(title: String, message: String)
    
    // js调用App的功能后 App再调用js函数执行回调
    func callHandler(handleFuncName: String)
    
}

2. 然后定义一个模型 该模型实现SwiftJavaScriptDelegate协议

@objc class SwiftJavaScriptModel: NSObject, SwiftJavaScriptDelegate {
    
    weak var controller: UIViewController?
    weak var jsContext: JSContext?
    
    func wxPay(orderNo: String) {
    
        print("订单号:", orderNo)
        
        // 调起微信支付逻辑
    }
    
    func wxShare(dict: [String: AnyObject]) {
        
        print("分享信息:", dict)
        
        // 调起微信分享逻辑
    }
    
    func showDialog(title: String, message: String) {
        
        let alert = UIAlertController(title: title, message: message, preferredStyle: .Alert)
        alert.addAction(UIAlertAction(title: "确定", style: .Default, handler: nil))
        self.controller?.presentViewController(alert, animated: true, completion: nil)
    }
    
    func callHandler(handleFuncName: String) {
        
        let jsHandlerFunc = self.jsContext?.objectForKeyedSubscript("\(handleFuncName)")
        let dict = ["name": "sean", "age": 18]
        jsHandlerFunc?.callWithArguments([dict])
    }
}

3. 然后使用WebView加载对应的网页,这里加载例子中的demo.html文件

func addWebView() {
    
    self.webView = UIWebView(frame: self.view.bounds)
    self.view.addSubview(self.webView)
    self.webView.delegate = self
    self.webView.scalesPageToFit = true
    
    // 加载本地Html页面
    let url = NSBundle.mainBundle().URLForResource("demo", withExtension: "html")
    let request = NSURLRequest(URL: url!)
    
    // 加载网络Html页面 请设置允许Http请求
    //let url = NSURL(string: "https://www.mayanlong.com");
    //let request = NSURLRequest(URL: url!)
    
    self.webView.loadRequest(request)
}

4. 最后在webViewDidFinishLoad代理中将我们定义的模型注入到网页中,暴露给JS

func webViewDidFinishLoad(webView: UIWebView) {
    
    
    self.jsContext = webView.valueForKeyPath("documentView.webView.mainFrame.javaScriptContext") as! JSContext
    let model = SwiftJavaScriptModel()
    model.controller = self
    model.jsContext = self.jsContext
    
    // 这一步是将SwiftJavaScriptModel模型注入到JS中,在JS就可以通过WebViewJavascriptBridge调用我们暴露的方法了。
    self.jsContext.setObject(model, forKeyedSubscript: "WebViewJavascriptBridge")
    
    // 注册到本地的Html页面中
    let url = NSBundle.mainBundle().URLForResource("demo", withExtension: "html")
    self.jsContext.evaluateScript(try? String(contentsOfURL: url!, encoding: NSUTF8StringEncoding))
    
    // 注册到网络Html页面 请设置允许Http请求
    //let url = "https://www.mayanlong.com";
    //let curUrl = self.webView.request?.URL?.absoluteString    //WebView当前访问页面的链接 可动态注册
    //self.jsContext.evaluateScript(try? String(contentsOfURL: NSURL(string: url)!, encoding: NSUTF8StringEncoding))

    self.jsContext.exceptionHandler = { (context, exception) in
        print("exception:", exception)
    }
}

5. Swift与JS方法互相调用

JS调用Swift方法

WebViewJavascriptBridge.wxPay('TN20160526')

WebViewJavascriptBridge.wxShare({
            'title' : '马燕龙个人博客',
            'description' : '一个专注于编程的技术博客',
            'url' : 'https://www.mayanlong.com'
        })

WebViewJavascriptBridge.showDialogMessage('马燕龙个人博客', '一个专注于编程的技术博客')

Swift调用JS方法并传参

func callHandler(handleFuncName: String) {
    
    let jsHandlerFunc = self.jsContext?.objectForKeyedSubscript("\(handleFuncName)")
    let dict = ["name": "sean", "age": 18]
    jsHandlerFunc?.callWithArguments([dict])
}

这样,我们就实现了Swift与JS的交互了,Demo中给出了详细的代码,大家可以下载运行。

四、代码下载及效果图

下载地址:

Github:https://github.com/YanlongMa/SwiftJavaScriptCore
如果本Demo对您有帮助,请不要吝啬您的Start(⊙o⊙)哦。

效果图:

Swift与JS交互效果


交友互动:

本文首发于马燕龙个人博客,欢迎分享,转载请标明出处。
马燕龙个人博客:https://www.mayanlong.com
马燕龙个人微博:http://weibo.com/imayanlong
马燕龙Github主页:https://github.com/yanlongma

iOS开发 - CocoaPods安装和使用教程

一、CocoaPods 简介

1. 什么是 CocoaPods

CocoaPods 是 iOS 的包管理工具。

2. 为什么要使用 CocoaPods

在开发 iOS 项目时,经常会使用第三方开源库,手动引入流程复杂,并且库之间还存在依赖关系,更增加了手动管理的难度。开源库如果升级了,你也想用最新版本,还需要重新手动导入,这大大增加了工作量。但用了 CocoaPods 后,安装和升级都只是一句命令的事情,让你可以专于业务本身。

二、CocoaPods 安装

1. 安装 Ruby

CocoaPods 基于 Ruby 语言开发而成,因此安装 CocoaPods 前需要安装 Ruby 环境。幸运的是 macOS 系统默认自带 Ruby 环境,如果没有请自行查找安装。检测是否安装 Ruby:

$ gem -v
3.0.3.1

安装则会提示当前 Ruby 版本。gem 介绍:gem 是一个管理 Ruby 库和程序的标准包,它通过 Ruby Gem(如 http://rubygems.org/ )源来查找、安装、升级和卸载软件包,非常的便捷。

2. 更换 gem 源

因为国内网络的问题导致 gem 源间歇性中断,原因你懂的。因此我们需要更换 gem 源,使用国内的 gem 源 https://gems.ruby-china.com/

第一步:移除默认的源

$ gem sources --remove https://rubygems.org/

第二步:指定国内的源

$ gem sources -a https://gems.ruby-china.com/

第三步:查看是否更换成功

$ gem sources -l
*** CURRENT SOURCES ***

https://gems.ruby-china.com/

如果是 https://gems.ruby-china.com/,则更换成功。

3. 安装 CocoaPods

终于开始安装 CocoaPods,说实话本人都快忘记是在写 CocoaPods 的教程了,囧!确认改成国内源后执行以下命令进行安装:

$ sudo gem install cocoapods

稍等片刻即可安装完成,输入以下命令检测是否安装成功:

$ pod --version
1.11.2

成功则会提示 CocoaPods 版本,到此安装已告一段落。

三、CocoaPods 使用实例

首先新建一个 iOS 工程 MyDemo,在该工程中演示 CocoaPods 的使用。

1. 创建 Podfile

进入工程的根目录,创建 Podfile 文件,创建完毕的目录如下图:
创建 Podfile 文件后的工程目录结构

2. 编辑 Podfile

根据需要,我们可以在 Podfile 文件中写入我们需要的第三方库,这里以 AFNetworking 和 MJRefresh 为例,Podfile 内容如下:

platform :ios, '7.0'
pod 'AFNetworking', '~> 3.0'
pod 'MJRefresh','~> 3.1'

这段代码的意思是,当前类库支持的iOS最低版本是iOS 7.0, 要下载的两个类库的版本分别为 3.0、3.1。

3. pod install 导入第三方库

这时候,你就可以利用CocoPods下载AFNetworking和MJRefresh类库了。在终端中进入工程根目录,运行以下命令:

$ cd /Users/myl/Desktop/IOS/MyDemo
$ pod install
Analyzing dependencies
Downloading dependencies
Installing AFNetworking (3.0.4)
Installing MJRefresh (3.1.0)
Generating Pods project
Integrating client project

[!] Please close any current Xcode sessions and use `MyDemo.xcworkspace` for this project from now on.
Sending stats

注意最后一句话,意思是:以后打开工程就用 MyDemo.xcworkspace 打开,而不是之前的.xcodeproj文件。你也许会郁闷,为什么会出现.xcworkspace文件呢。这正是你刚刚运行pod install命令产生的新文件。除了这个文件,你会发现还多了另外一个文件“Podfile.lock”和一个文件夹“Pods”。点击 MyDemo.xcworkspace 打开工程之后,你会发现工程目录多了一些,你会惊喜地发现,AFNetwoking和MJRefresh已经成功导入项目了!

新的目录结构:
CocoaPods_03.png

4. pod update 更新第三方库

如果需要引入或删除类库,只需要修改Profile文件后执行以下命令即可:

pod update

5. 工程中使用类库

如果是OC项目,只需在使用的文件中导入该类库的头文件即可:

#import "AFNetworking.h"
#import "MJRefresh.h"

如果是Swift项目,使用OC的类库,需要新建桥接头文件(MyDemo-Bridging-Header.h),在头文件中导入要使用的类库:

#import <AFNetworking/AFNetworking.h>
#import <MJRefresh/MJRefresh.h>

四、常见问题

1. install,update速度慢

出现原因:你本地的repo库太长时间没有更新了
解决办法:pod repo update

原因在于当执行以上两个命令的时候会升级CocoaPods的specs仓库,如果不想在install,update的时候升级specs库,可以使用参数忽略掉
pod install --no-repo-update
pod update --no-repo-update

2. 导入Swift类库

导入Swift语言编写的类库时需要加use_frameworks!,下面以导入Alamofire为例:

platform :ios, '8.0'
use_frameworks!
pod 'Alamofire', '~> 1.3'

3. 官方文档

对于Podfile参数细节,可以查阅官网,再此不做过多介绍。
http://guides.cocoapods.org/


交友互动:

本文首发于马燕龙个人博客,欢迎分享,转载请标明出处。
马燕龙个人博客:https://www.mayanlong.com
马燕龙个人微博:http://weibo.com/imayanlong
马燕龙Github主页:https://github.com/yanlongma

浅谈Github多人合作开发

前言:

之前的一篇文章介绍了如何搭建自己的Git服务器,在自己搭建的Git服务器上,多人合作一般都采用创建证书登录方式(文章中也有介绍),即简单又方便。今天主要介绍Github上多人合作的开发方式。

Github多人合作开发方式主要分两种:

  1. Collaborators
  2. Fork & Pull request

本文首发于马燕龙个人博客,欢迎分享,转载请标明出处。


1、Collaborators:

使用场景:

Collaborators适用于一个Team之间的团队开发。比如张三有一个项目,Repo地址为ZhangSan/RepoA,这时张三就可以邀请自己的项目组成员或小伙伴一起开发这个项目了。

怎样邀请:

进入Repo,点击Settings-> Collaborators-> Add collaborator 即可邀请。

clone及push代码:

被邀请的开发者clone地址为:https://github.com/ZhangSan/RepoA,开发者修改代码(branch、commit、merge、push),push后会更新ZhangSan/RepoA。
第一次push代码时需要输入自己的账号密码进行验证,如果账号在Collaborators中,就可以push成功。

2、Fork & Pull request

使用场景:

Fork & Pull request方式适用于开源项目。比如张三有一个很牛的开源项目,Repo地址为ZhangSan/RepoA。李四看着不错想做点贡献,就Fork一个到自己的Repo中,地址为LiSi/RepoA。

clone及push代码:

李四clone地址为:https://github.com/LiSi/RepoA,李四可以任意修改该仓库的代码(branch、commit、merge、push),push后只会更新LiSi/RepoA,任何操作都不会影响ZhangSan/RepoA。

化学反应:

有一天,李四开发了一个不错的功能,想推荐给张三,就可以在自己Fork的仓库LiSi/RepoA里发一个pull request,问问张三要不要。

提交后张三的仓库ZhangSan/RepoA将会收到一个pull request。张三如果觉得不错,就可以将LiSi/RepoA Merge ZhangSan/RepoA,如果觉得有问题,也可以用comment讨论。(ZhangSan/RepoA 所有的Collaborators都可以处理)


交友互动:

本文首发于马燕龙个人博客,欢迎分享,转载请标明出处。
马燕龙个人博客:https://www.mayanlong.com
马燕龙个人微博:http://weibo.com/imayanlong
马燕龙Github主页:https://github.com/yanlongma

Typecho - MyTagCloud标签云插件

一、前言:

标签云是博客、CMS类系统的常见功能,读者可以根据标签快速的查找和浏览自己喜欢的文章。个人很喜欢Typecho的简洁,但对于后台不能控制前台标签栏目的显示还是略表遗憾。令人高兴的是Typecho的插件机制可以让Typecho Fans很容易的开发出自己想要的插件,于是决定自己开发一个标签云插件。

该插件已被Typecho官方Merge。本文首发于马燕龙个人博客,欢迎分享,转载请标明出处。

二、资料:

三、效果:

MyTagCloud02.gif

四、使用帮助:

  1. 下载插件(点击下载
  2. 将插件上传到/usr/plugins/目录
  3. 在需要使用标签云的模板中放入如下PHP代码 Typecho_Plugin::factory('usr/themes/sidebar.php')->tagCloud();
  4. 登陆后台,在菜单“控制台->插件”中启用插件,并根据自己需求进行配置即可轻松使用
  5. 如果标签云模板结构不同,重写插件中render()方法即可

代码如下:

<?php
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
/**
 * MyTagCloud插件,后台控制前台标签智能显示
 *
 * @package MyTagCloud
 * @author  Ma Yanlong
 * @version 1.0.0
 * @link https://www.mayanlong.com
 */
class MyTagCloud_Plugin implements Typecho_Plugin_Interface
{

    // 是否启用
    const ENABLE_YES = 10;  //启用
    const ENABLE_NO = 20;  //不启用

    // 是否显示没使用的标签
    const ZERO_SHOW = 10;   //显示
    const ZERO_HIDE = 20;   //不显示

    /**
     * 激活插件方法,如果激活失败,直接抛出异常
     *
     * @access public
     * @return void
     * @throws Typecho_Plugin_Exception
     */
    public static function activate()
    {
        // factory('name') name是插件接口名称 可以取任何名称 为方便寻找我们以文件目录命名
        Typecho_Plugin::factory('usr/themes/sidebar.php')->tagCloud = array('MyTagCloud_Plugin', 'process');
    }

    /**
     * 禁用插件方法,如果禁用失败,直接抛出异常
     *
     * @static
     * @access public
     * @return void
     * @throws Typecho_Plugin_Exception
     */
    public static function deactivate(){}

    /**
     * 获取插件配置面板
     *
     * @access public
     * @param Typecho_Widget_Helper_Form $form 配置面板
     * @return void
     */
    public static function config(Typecho_Widget_Helper_Form $form)
    {

        // 是否启用
        $compatibilityMode = new Typecho_Widget_Helper_Form_Element_Radio('enable', array(
            self::ENABLE_YES   =>  _t('启用'),
            self::ENABLE_NO   =>  _t('不启用')
        ), self::ENABLE_YES, _t('是否启用该插件'), _t("启用后将这段PHP代码放到需要显示标签的模板中即可 Typecho_Plugin::factory('usr/themes/sidebar.php')->tagCloud(); "));
        $form->addInput($compatibilityMode->addRule('enum', _t('必须选择一个模式'), array(self::ENABLE_YES, self::ENABLE_NO)));

        // 是否显示没使用的标签
        $compatibilityMode = new Typecho_Widget_Helper_Form_Element_Radio('zero', array(
            self::ZERO_SHOW   =>  _t('显示'),
            self::ZERO_HIDE   =>  _t('不显示')
        ), self::ZERO_SHOW, _t('显示没使用的标签'), _t("默认显示所有标签,请根据自己需要进行设置。"));
        $form->addInput($compatibilityMode->addRule('enum', _t('必须选择一个模式'), array(self::ZERO_SHOW, self::ZERO_HIDE)));

        // 前台显示栏目标题
        $title = new Typecho_Widget_Helper_Form_Element_Text('title', NULL, '标签', _t('前台显示栏目标题'));
        $form->addInput($title);

        // 最多显示标签数量
        $limit = new Typecho_Widget_Helper_Form_Element_Text('limit', NULL, '20', _t('最多显示标签数量'));
        $form->addInput($limit);
    }

    /**
     * 个人用户的配置面板
     *
     * @access public
     * @param Typecho_Widget_Helper_Form $form
     * @return void
     */
    public static function personalConfig(Typecho_Widget_Helper_Form $form){}

    /**
     * 插件实现方法
     *
     * @access public
     * @return void
     */
    public static function process()
    {
        $enable = Typecho_Widget::widget('Widget_Options')->plugin('MyTagCloud')->enable;
        $zero = Typecho_Widget::widget('Widget_Options')->plugin('MyTagCloud')->zero;
        $title = Typecho_Widget::widget('Widget_Options')->plugin('MyTagCloud')->title;
        $limit = (int)Typecho_Widget::widget('Widget_Options')->plugin('MyTagCloud')->limit;

        // 是否启用
        if ($enable != self::ENABLE_YES) {
            return;
        }

        // 查找满足条件的标签
        $tags = Typecho_Widget::widget('Widget_Metas_Tag_Cloud', array(
            'sort' => 'count',
            'ignoreZeroCount' => $zero == self::ZERO_HIDE ? true : false,
            'desc' => true,
            'limit' => $limit
        ));

        // 是否有标签
        if ($tags->have()) {
            self::render($title, $tags);
        }
    }

    /**
     * 输出Html标签
     *
     * @access public
     * @return void
     */
    public static function render($title, $tags)
    {
        // 拼接并输出html
        $html = '<section class="widget">
                    <h3 class="widget-title">'. $title .'</h3>
                    <div class="widget-list">';

                        while ($tags->next()) {
                            $html .= "<a href='{$tags->permalink}' style='display: inline-block; margin: 0 5px 5px 0;'>{$tags->name}</a>";
                        }

        $html .=    '</div>
                </section>';

        echo $html;
    }


}

交友互动:

本文首发于马燕龙个人博客,欢迎分享,转载请标明出处。
马燕龙个人博客:https://www.mayanlong.com
马燕龙个人微博:http://weibo.com/imayanlong
马燕龙Github主页:https://github.com/yanlongma

iOS开发 - Swift实现清除缓存功能

前言:

开发移动应用时,请求网络资源是再常见不过的功能。如果每次都去请求,不但浪费时间,用户体验也会变差,所以移动应用都会做离线缓存处理,其中已图片缓存最为常见。但是时间长了,离线缓存会占用大量的手机空间,所以清除缓存功能基本是移动应用开发的标配。

本文首发于马燕龙个人博客,欢迎分享,转载请标明出处。

实现:

本文介绍在iOS开发中,Swift实现清除缓存功能。主要分为统计缓存文件大小和删除缓存文件两个步骤:

1、统计缓存文件大小

func fileSizeOfCache()-> Int {
    
    // 取出cache文件夹目录 缓存文件都在这个目录下
    let cachePath = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.CachesDirectory, NSSearchPathDomainMask.UserDomainMask, true).first
    //缓存目录路径
    print(cachePath)
    
    // 取出文件夹下所有文件数组
    let fileArr = NSFileManager.defaultManager().subpathsAtPath(cachePath!)
    
    //快速枚举出所有文件名 计算文件大小
    var size = 0
    for file in fileArr! {
        
        // 把文件名拼接到路径中
        let path = cachePath?.stringByAppendingString("/\(file)")
        // 取出文件属性
        let floder = try! NSFileManager.defaultManager().attributesOfItemAtPath(path!)
        // 用元组取出文件大小属性
        for (abc, bcd) in floder {
            // 累加文件大小
            if abc == NSFileSize {
                size += bcd.integerValue
            }
        }
    }
    
    let mm = size / 1024 / 1024
    
    return mm
}

2、删除缓存文件

func clearCache() {
    
    // 取出cache文件夹目录 缓存文件都在这个目录下
    let cachePath = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.CachesDirectory, NSSearchPathDomainMask.UserDomainMask, true).first
    
    // 取出文件夹下所有文件数组
    let fileArr = NSFileManager.defaultManager().subpathsAtPath(cachePath!)
    
    // 遍历删除
    for file in fileArr! {
        
        let path = cachePath?.stringByAppendingString("/\(file)")
        if NSFileManager.defaultManager().fileExistsAtPath(path!) {
            
            do {
                try NSFileManager.defaultManager().removeItemAtPath(path!)
            } catch {
                
            }
        }
    }
}

3、效果图

清除缓存01.gif


交友互动:

本文首发于马燕龙个人博客,欢迎分享,转载请标明出处。
马燕龙个人博客:https://www.mayanlong.com
马燕龙个人微博:http://weibo.com/imayanlong
马燕龙Github主页:https://github.com/yanlongma

搭建自己的Git服务器

前言:

GitHub是一个免费托管开源代码的远程仓库,使用起来即方便又安全,但在国内有时访问巨慢,原因你懂得。还有一些公司和个人视源码如生命,既不想开源代码又不想给Github交保护费。这时搭建一个自己的Git服务器就很有必要了,下面介绍如何在CentOS上搭建自己的Git服务器。

本文首发于马燕龙个人博客,欢迎分享,转载请标明出处。

一、搭建Git服务器及使用

1、安装Git

执行以下命令安装git

$ yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel perl-devel
$ yum install git

接下来我们创建一个git用户组和用户,用来运行git服务:

$ groupadd git
$ useradd git -g git
$ passwd yourpwd

最好切换到git用户 不然后面新建的git仓库都要改权限 烦烦烦!!

$ su - git    

2、创建证书登录

收集所有需要登录的用户的公钥,公钥位于id_rsa.pub文件中,把我们的公钥导入到/home/git/.ssh/authorized_keys文件里,一行一个。

如果没有该文件则创建它:

$ cd /home/git/
$ mkdir .ssh
$ chmod 700 .ssh
$ touch .ssh/authorized_keys
$ chmod 600 .ssh/authorized_keys

3、初始化Git仓库

首先我们选定一个目录作为Git仓库,假定我们放在git用户的宿主目录/home/git/,在/home/git/目录下输入命令:

$ cd /home/git
$ git init --bare test.git
Initialized empty Git repository in /home/git/test.git/

以上命令会创建一个空仓库,服务器上的Git仓库通常都以.git结尾。

4、克隆仓库

$ git clone git@your-ip:test.git
Cloning into 'test'...
warning: You appear to have cloned an empty repository.
Checking connectivity... done.

your-ip 为您 Git 所在服务器 ip 。

5、禁止Shell登录

出于安全考虑,git用户不允许登录shell,这可以通过编辑/etc/passwd文件完成。
找到类似下面的一行:

git:x:502:502::/home/git:/bin/bash

改为

git:x:502:502::/home/git:/usr/bin/git-shell

这样,git用户可以正常通过ssh使用git,但无法登录shell,因为我们为git用户指定的git-shell每次一登录就自动退出。


二、注意事项及说明

1、git仓库可以放在任何目录

放在/home/git目录下(clone相对于git宿主目录 /home/git/)

git clone git@your-ip:test.git

放在根目录,新建git目录作为仓库(绝对路径 /git/)

git clone git@your-ip:/git/test.git

如果域名绑定IP就可以直接用域名clone

git clone git@www.mayanlong.com:test.git

    

2、目录权限问题

如果不是用git用户创建的,注意以下目录文件的权限问题。

.ssh
test.git...
    

如果有问题,可以把该目录的所属者改成git。

$ chown -R git:git test.git    


交友互动:

本文首发于马燕龙个人博客,欢迎分享,转载请标明出处。
马燕龙个人博客:https://www.mayanlong.com
马燕龙个人微博:http://weibo.com/imayanlong
马燕龙Github主页:https://github.com/yanlongma

Markdown - 语法简介

本文首发于马燕龙个人博客,欢迎分享,转载请标明出处。

标题

在文字里书写不同数量的“#”可以完成不同的标题,如下:

# 一级标题
## 二级标题
### 三级标题
#### 四级标题
##### 五级标题
###### 六级标题

列表

无序列表的使用,在符号“-”后加空格使用。如下:

- 无序列表1
- 无序列表2
- 无序列表3

如果要控制列表的层级,则需要在符号“-”前使用空格。如下:

- 无序列表1
- 无序列表2
  - 无序列表2.1
     - 列表内容
     - 列表内容

有序列表的使用,在数字及符号“.”后加空格几个,如下:

1. 有序列表1
2. 有序列表2
3. 有序列表3

有序列表如果要区分层级,也可以在数字前加空格。

引用

引用的格式是使用符号“>”后面书写文字,及可以使用引用。如下:

> 这个是引用
> 是不是和电子邮件中的
> 引用格式很像

粗体与斜体

斜体的使用则是在需要斜体的文字前后各加一个“*”,而粗体的使用是在需要加粗的文字前后各加两个“*”,如果要使用粗体和斜体,那么就是在需要操作的文字前后各加三个“*”。如下:

*这个是斜体*
**这个是粗体**
***这个是粗体加斜体***

链接与图片

在文中直接加链接,中括号中是需要添加链接的文字,圆括号中是需要添加的链接,如下:
[link text](http://example.com/ "optional title")

在引用中加链接,第一个中括号添加需要添加的文字,第二个中括号中是引用链接的id,之后在引用中,使用id加链接:如下:
[link text][id]
[id]: http://example.com/ "optional title here"

在文中直接引用链接,直接使用尖括号,把链接加入到尖括号中就可以实现,如下:
<http://example.com/> or <address@example.com>

插入互联网上图片,格式如下:
![这里写图片描述](http://img3.douban.com/mpic/s1108264.jpg)
![这里写图片描述][jane-eyre-douban]
[jane-eyre-douban]: http://img3.douban.com/mpic/s1108264.jpg

分割线与删除线

可以在一行中用三个以上的星号、减号、底线来建立一个分隔线,同时需要在分隔线的上面空一行。如下:

---
****
___

删除线的使用,在需要删除的文字前后各使用两个符合“~”,如下

~~Mistaken text.~~

代码块与语法高亮

在需要高亮的代码块的前一行及后一行使用三个反引号“`”,同时第一行反引号后面表示代码块所使用的语言,如下:

``` swift
print("Hello World!")
```

交友互动:

本文首发于马燕龙个人博客,欢迎分享,转载请标明出处。
马燕龙个人博客:https://www.mayanlong.com
马燕龙个人微博:http://weibo.com/imayanlong
马燕龙Github主页:https://github.com/yanlongma