あたも技術ブログ

セットジャパンコーポレーションの社員が運営しています。

【C#】Windowsフォーム アプリケーションのグラデーション背景と枠線を表示できるパネルユーザコントロール

 久しぶりのWindowsフォーム アプリケーションのユーザコントロールネタです。
 WPFだとコントロールに枠線やグラデーションを行うのは容易ですが、Windowsフォーム アプリケーションだと面倒なことこの上ないです。
 Panelを継承し、OnPaintをoverrideして自力で背景と枠線を描画してやっと出来るっていう…。

 グラデーション背景と枠線を表示できるパネルユーザコントロールの実装コードです。

namespace GradationPanelSample
{
  partial class GradationPanel
  {
    /// <summary> 
    /// 必要なデザイナー変数です。
    /// </summary>
    private System.ComponentModel.IContainer components = null;

    /// <summary> 
    /// 使用中のリソースをすべてクリーンアップします。
    /// </summary>
    /// <param name="disposing">マネージ リソースを破棄する場合は true を指定し、その他の場合は false を指定します。</param>
    protected override void Dispose(bool disposing)
    {
      if (disposing && (components != null))
      {
        components.Dispose();
      }
      base.Dispose(disposing);
    }

    #region コンポーネント デザイナーで生成されたコード

    /// <summary> 
    /// デザイナー サポートに必要なメソッドです。このメソッドの内容を 
    /// コード エディターで変更しないでください。
    /// </summary>
    private void InitializeComponent()
    {
      components = new System.ComponentModel.Container();
    }

    #endregion
  }
}
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace GradationPanelSample
{
  /// <summary>
  /// グラデーションパネルユーザコントロール
  /// </summary>
  public partial class GradationPanel : Panel
  {
    #region プロパティ
    /// <summary>
    /// コントロールの境界線のスタイル
    /// </summary>
    /// <remarks>PanelのデフォルトプロパティであるBorderStyleを隠蔽している。</remarks>
    [CategoryAttribute("表示")]
    [DescriptionAttribute("コントロールの境界線スタイルを取得または設定します。")]
    [BrowsableAttribute(false)]
    public new BorderStyle BorderStyle { get; set; } = BorderStyle.None;

    /// <summary>
    /// コントロールの境界線の色
    /// </summary>
    [CategoryAttribute("表示")]
    [DescriptionAttribute("コントロールの境界線の色を取得または設定します。")]
    [BrowsableAttribute(true)]
    public Color BorderColor { get; set; } = Color.Black;

    /// <summary>
    /// コントロールの境界線の太さ
    /// </summary>
    [CategoryAttribute("表示")]
    [DescriptionAttribute("コントロールの境界線の太さを取得または設定します。0を設定した場合は枠線は描画されません。")]
    [BrowsableAttribute(true)]
    [DefaultValue(0)]
    public int BorderThickness { get; set; } = 0;

    /// <summary>
    /// コントロールのグラデーション開始色
    /// </summary>
    [CategoryAttribute("表示")]
    [DescriptionAttribute("コントロールのグラデーション開始色を取得または設定します。")]
    [BrowsableAttribute(true)]
    public Color StartColor { get; set; } = SystemColors.Control;

    /// <summary>
    /// コントロールのグラデーション終了色
    /// </summary>
    [CategoryAttribute("表示")]
    [DescriptionAttribute("コントロールのグラデーション終了色を取得または設定します。")]
    [BrowsableAttribute(true)]
    public Color EndColor { get; set; } = SystemColors.Control;

    /// <summary>
    /// コントロールのグラデーションモード
    /// </summary>
    [CategoryAttribute("表示")]
    [DescriptionAttribute("コントロールのグラデーションのモードを取得または設定します。")]
    [BrowsableAttribute(true)]
    public LinearGradientMode GradientMode { get; set; } = LinearGradientMode.Vertical;
    #endregion

    #region コンストラクタ
    /// <summary>
    /// クラスの新しいインスタンスを初期化します。
    /// </summary>
    public GradationPanel()
    {
      InitializeComponent();
    }
    #endregion

    #region protectedメソッド
    /// <summary>
    /// 描画処理
    /// </summary>
    /// <param name="pevent">Paintイベント引数</param>
    protected override void OnPaint(PaintEventArgs pevent)
    {
      using (var graphics = pevent.Graphics)
      {
        var borderThickness = GetHarfBorderThickness();
        var x = borderThickness;
        var y = borderThickness;
        var width = 0 < borderThickness ? Width - (borderThickness * 2) : Width;
        var height = 0 < borderThickness ? Height - (borderThickness * 2) : Height;

        // 幅と高さが0より小さい場合は、最小値の1を設定する
        if (width <= 0) { width = 1; }
        if (height <= 0) { height = 1; }

        // 算出した幅と高さがコントロールの領域の1/2より大きい場合は、値を設定し直す
        if ((Width / 2) < borderThickness)
        {
          borderThickness = (int)Math.Floor(Width / 2.0F);
        }
        if ((Height / 2) < borderThickness)
        {
          borderThickness = (int)Math.Floor(Height / 2.0F);
        }

        // 背景の描画領域を指定する
        var rectangle = new Rectangle(x, y, width, height);
        using (var linearGradientBrush = new LinearGradientBrush(new Rectangle(x, y, width, height), StartColor, EndColor, GradientMode))
        {
          // グラデーションブラシを生成し描画する
          graphics.FillRectangle(linearGradientBrush, rectangle);
        }

        if (0 < BorderThickness)
        {
          using (var pen = new Pen(BorderColor, BorderThickness))
          {
            graphics.DrawRectangle(pen, 0 + borderThickness, 0 + borderThickness, width, height);
          }
        }
      }
    }
    #endregion

    #region privateメソッド
    /// <summary>
    /// 枠線の太さの1/2の値を取得します。
    /// </summary>
    /// <returns>枠線の太さの1/2の値</returns>
    private int GetHarfBorderThickness()
    {
      return (int)System.Math.Floor((double)(BorderThickness) / 2 + 0.5);
    }
    #endregion
  }
}

 枠線の太さの最小値と最大値を補正するように記述しています。頭が悪いのでもっと綺麗に書けそうですが、わたしの脳みそではこれで限界です。
 Windowsフォーム アプリケーションのユーザコントロールネタにまた戻ってきましたが、そろそろネタが無くなりそう。

【iOS】Alamofire + Himotokiでいい感じのAPIクライアントを作る

どうも、社内開発でiOSを担当してる朝倉です。

現在、夏期休業中ですが、そういえばブログ更新しないといけないなと思い出したので書きます。

Alamofire + HimotokiでAPIクライアントを作るということで、n番煎じだしもっといい方法がネット上にはゴロゴロある気がするのですが、 現状、(僕が)いい感じだと思っている実装を書いてみたいと思います。

導入

CocoaPodsでAlamofireとHimotokiを導入します。

「そんなの知ってるよ」とかCarthage派の人やSPM派の人は読み飛ばしてください。

ターミナルでプロジェクトディレクトリへ移動し、

pod init

Podfileが作成されるので以下の2行を追加します。

pod 'Alamofire', '~> 4.4'
pod 'Himotoki', '~> 3.0'

このようになればOKです。

target 'プロジェクト名' do
  use_frameworks!
  pod 'Alamofire', '~> 4.4'
  pod 'Himotoki', '~> 3.0'
end

Podfileを保存し、

pod install

これで、AlamofireとHimotokiがプロジェクトに追加されたので、プロジェクト名.xcworkspaceファイルを開きます。

APIクライアントを作る

今回は、GitHubAPIを使用します。 まずは共通の通信部分を作成します。

import Alamofire
import Himotoki

enum Result<T> {
    case Success(T)
    case Error(Error)
}

protocol APIRequest {
    var baseeUrl: String { get }
    var headerTemplate: [String : String] { get }
    
    associatedtype Response
    var path: String { get }
    var method: HTTPMethod { get }
    
    var parameters: [String : Any]? { get set }
    var headers: [String : String]? { get set }
    
    func response(from object: Any) throws -> Self.Response
    
}

extension APIRequest {
    var baseeUrl: String {
        return "https://api.github.com"
    }
    var headerTemplate: [String : String] {
        return ["X-Requested-With" : "XMLHttpRequest"]
    }
    var parameters: Any? {
        return nil
    }
    var headers: [String : String]? {
        return nil
    }
    
    func request(finished: @escaping (Result<Self.Response>)->Void) {
        let encoding = JSONEncoding.default
        var header = headerTemplate as Dictionary<String, String>
        headerTemplate.forEach() {
            header[$0.0] = $0.1
        }
        
        let encodedURLString = (baseeUrl + path).addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlQueryAllowed)
        
        Alamofire.request(encodedURLString!, method: method, parameters: parameters, encoding: encoding, headers: header).responseJSON { response in
            switch response.result {
            case .success(let value):
                print(value)
                do {
                let res = try self.response(from: value)
                    finished(Result.Success(res))
                } catch {
                    finished(Result.Error(error))
                }
            case .failure(let error):
                finished(Result<Self.Response>.Error(error))
            }
        }
    }
}

続いて、Decodableプロトコルを適応したモデルとAPIRequestプロトコルを適応したリクエストオブジェクトを作成していきます。

ユーザのリポジトリを取得する

import Himotoki
import Alamofire

struct Repository: Decodable {
    let fullName: String
    let ownerAvatarUrl: String
    let language: String?
    let url: String
    let htmlUrl: String
    
    static func decode(_ e: Extractor) throws -> Repository {
        return try Repository(
            fullName: e <| "full_name",
            ownerAvatarUrl: e <| ["owner", "avatar_url"],
            language: e <|? "language",
            url: e <| "url",
            htmlUrl: e <| "html_url"
        )
    }
}

struct  UserRepository: APIRequest {
    var headers: [String : String]? = nil
    var parameters: [String : Any]? = nil
    var userName: String
    
    var path: String {
        return "/users/\(self.userName)/repos"
    }
    var method: HTTPMethod {
        return .get
    }
    typealias Response = [Repository]
    
    init(userName: String) {
        self.userName = userName
    }
    
    func response(from object: Any) throws -> Response {
        return try decodeArray(object)
    }
}

今後、エンドポイントが増えた場合にはDecodableプロトコルを適応したレスポンスモデルとAPIRequestプロトコルを適応したリクエストオブジェクトを増やしていけばいいだけなのでお手軽です。

使い方

UserRepository(userName: "asashin227").request() { result in
    switch result {
    case .Success(let responce):
        print(responce)
    case .Error(let error):
        print(error.localizedDescription)
    }
}

ソース

とりあえずGitHubにあげたので参考にご利用ください。

github.com

【NW】メールってどうなってるのか考える

前回「名前解決」という不思議なワードを攻略したので
インターネット空間をどんな目印で動いてるか分かったかなと思います。

 今回はインターネットの利用の双璧「メール」について少し書いてみます。
インターネットの中というのは、それまで使われていた現実世界の概念をネットワークの世界に持ち込んだものが多いので、てっとり早く理解するには現実世界と比較するのが一番です。

 

さて、「メール」。読んで字のごとし「手紙」です。
日本語は便利なもので、「メール」「手紙」も、もとの意味は同じなのに表現を変えるだけで、いまや「メール」といえば「電子メール」を指すのが一般的になりました。

 「メール送っといて」といわれて、手紙書いて切手貼って郵便ポストへ・・・という人はかなりレアですよね。
だいたいはPCやスマホでメールを打って送信すると、しばらくすると相手のスマホなんかに届く。この間がどうなっているのか見てみようかと思います。

 

あなたがメールを送ると、メールサーバに送られます。これはポストに手紙を出すのに相当しますが、ここは簡単に想像できるとおもいます。
どこのメールサーバに送るかといえば、自分の契約しているプロバイダーとか、会社なら自社のメールサーバに送ることになり、これはメールソフトにあらかじめ初期設定とかで設定してあります。自分専用の窓口がある郵便局のようなイメージです。

 

その後、メールを受取ったサーバは、宛先アドレスから相手のメールサーバを探します。ここで、前回の名前解決が使われます。
相手のメールサーバがわかると、そのサーバへメールの転送が行われます。ちょうど、郵便局間で手紙が運ばれるのと同じですね。


・・・でもこれでは、サーバには到着しますが、スマホには来ないですよね?
郵便局に届いても自宅に届かないと手紙は読めません。

 

ここで登場するのが「プッシュ通信」という、いわば配達員と同じ動きをする機能です
サーバに到着したメールは、「サーバー側から」(ここがミソ)送信先の携帯端末などを探して、そこへメールを送り込みます。これは携帯端末とメールアドレスが1対1なのでできる芸当。主に携帯キャリア(d社とかa社とかs社とか・・・)などのメールで使われます。最近はWebブラウザでも同様の動きができるようになってます。

 

でも、携帯キャリアのメールアドレスじゃなくても、スマホにメール、きますよね?
これは実はメールが「来る」わけではなく「届く」といったほうが適当です。
「端末から」定期的だったり手動だったりでサーバーに「メールを取りに」いってます。メールがあれば、サーバからデータを引っ張ってくるので「プル通信」といわれます。この動きは、郵便局の私書箱へ届いている手紙を取りに行く、のと同じ働きになります。 

 

これ以外にもメール関係のキーワードとしては・・
・端末にメールをもってきて読むPOP3や、メールはサーバーに置いたまま、内容を読むIMAPなどという方式の違い。パソコンやプロバイダーのメールはPOP3、携帯など移動体のメールはIMAPがよく使われます
・セキュリティ対策、特にスパム送信対策のPOP before SMTPとか、SMTP Auth」という送信認証。実はもともとメール送信というのは認証なしで送れました。ですが、これではスパム送り放題ですので実装された方式です
・ほかにもセキュリティ対策で「サブミッションポート」だったり「暗号化」「フィルタリング」MIME」「HTMLメール」・・・

などなど、メールは昔からある、比較的単純な通信ですが、なかなか奥が深いです。

 

なお。
説明の都合上、かなり端折ったり、デフォルメしていますので
もっとメールの仕組みを知りたい人はSetJapanの門をたたいてみましょう。

 

【C#】Excelの取り扱いにClosedXMLを使用する

 今回はC#Excelを使用したい場合を考えたいと思います。2008年辺りまではCOMコンポーネントを使用してMicrosoft Excel 12.0 Object Libraryを参照し、COMオブジェクトの解放地獄でかなり苦しんでおられたのではないでしょうか。
 Office2007以降の場合、xlsx、xlsmファイルとなり内部的にはXML形式となりました。これによってCOMオブジェクトうを使用せずにExcelファイルを扱えるライブラリが色々公開されています。
 その中でClosedXMLをご紹介したいと思います。
 
1. Excelを扱うプロジェクトを作成します。
2. Visual Studioを起動し、「ツール」→「NuGet パッケージマネージャー」→「ソリューションの NuGet パッケージの管理」を選択します。
f:id:atamo_dev:20170719212412j:plain
3.「NuGet パッケージ管理ウィンドウ」で左のオンラインを選択します。
4. 右上オンラインの検索欄に「OpenXML」と入力し、検索を実行します。
f:id:atamo_dev:20170719212439j:plain
5. 表示された「DocumentFormat.OpenXml」を選択すると「インストール」ボタンが表示されていますので、「インストール」ボタンを押下し、指示に従ってインストールを行います。
6. 右上オンラインの検索欄に「ClosedXML」と入力し、検索を実行します。
f:id:atamo_dev:20170719212451j:plain
7. 表示された「ClosedXML」を選択すると「インストール」ボタンが表示されていますので、「インストール」ボタンを押下し、指示に従ってインストールを行います。

 これで前準備は完了しました。

github.comOpenXML SDK
github.comClosedXML


 以下Excelを扱ったサンプルクラスです。

using ClosedXML.Excel;
using System;
using System.IO;

namespace ExcelSample
{
  /// <summary>
  /// Excelの読み込みとワークシート、セルへのアクセスを行うクラス
  /// </summary>
  public class ExcelLoader : IDisposable
  {
    #region メンバ変数
    /// <summary>
    /// Excelのワークブック(2013以降のExcelを指定すること)
    /// </summary>
    private XLWorkbook _Workbook = null;
    #endregion

    #region プロパティ
    /// <summary>
    /// 全てのワークシートを取得します。
    /// </summary>
    public IXLWorksheets Worksheets
    {
      get
      {
        if (this._Workbook != null)
        {
          return this._Workbook.Worksheets;
        }
        else
        {
          return null;
        }
      }
    }
    #endregion

    #region コンストラクタ
    /// <summary>
    /// 新しいクラスのインスタンスを作成します。
    /// </summary>
    public ExcelLoader()
    {
    }

    /// <summary>
    /// 新しいクラスのインスタンスを作成します。
    /// </summary>
    /// <param name="path">Excelファイルのパス</param>
    public ExcelLoader(string path)
    {
      if (!string.IsNullOrEmpty(path) && File.Exists(path))
      {
        // ファイルパスが設定されているかつ、そのパスのファイルが存在する場合、ファイルを開く
        this._Workbook = new XLWorkbook(path);
      }
    }
    #endregion

    #region 公開メソッド
    /// <summary>
    /// 解放処理
    /// </summary>
    public void Dispose()
    {
      CloseExcel();
    }

    /// <summary>
    /// 引数で指定されたExcelファイルを開きます。
    /// </summary>
    /// <param name="path">Excelファイルのパス</param>
    /// <returns>true:オープン成功、false:オープン失敗</returns>
    public bool OpenExcel(string path)
    {
      CloseExcel();

      if (!string.IsNullOrEmpty(path) && File.Exists(path))
      {
        // ファイルパスが設定されているかつ、そのパスのファイルが存在する場合、ファイルを開く
        this._Workbook = new XLWorkbook(path);
        return true;
      }
      else
      {
        return false;
      }
    }

    /// <summary>
    /// 指定したインデックスのワークシートの指定セルを読み込みます。
    /// </summary>
    /// <param name="row">行番号</param>
    /// <param name="col">列番号</param>
    /// <param name="index">ワークシートのインデックス番号</param>
    /// <returns>true:オープン成功、false:オープン失敗</returns>
    public string ReadCell(int row, int col, int index = 1)
    {
      if (this._Workbook == null)
      {
        return string.Empty;
      }

      try
      {
        var worksheet = this._Workbook.Worksheet(index);
        var cell = worksheet.Cell(row, col);
        return cell.Value as String;
      }
      catch
      {
        // 指定されたワークシートが存在しなかった場合、空値を返却する
        return string.Empty;
      }
    }

    /// <summary>
    /// 指定したワークシートの指定セルを読み込みます。
    /// </summary>
    /// <param name="row">行番号</param>
    /// <param name="col">列番号</param>
    /// <param name="worksheet">ワークシートのインデックス番号</param>
    /// <returns>true:オープン成功、false:オープン失敗</returns>
    public string ReadCell(int row, int col, IXLWorksheet worksheet)
    {
      if (worksheet == null)
      {
        return string.Empty;
      }

      try
      {
        var cell = worksheet.Cell(row, col);
        return cell.Value as String;
      }
      catch
      {
        // 指定されたワークシートのセルが存在しなかった場合、空値を返却する
        return string.Empty;
      }
    }

    /// <summary>
    /// 現在オープンされているExcelファイルをクローズします。
    /// </summary>
    public void CloseExcel()
    {
      if (this._Workbook != null)
      {
        // 既にExcelが開かれている場合、破棄する
        this._Workbook.Dispose();
        this._Workbook = null;
      }
    }
    #endregion
  }
}

 クラスインスタンス生成時にExcelファイルのパスを指定し、Excelファイルからセルの読み込みを行う簡単なメソッドを実装したクラスです。
 COMオブジェクトの時代では速度面で遅く厳しいものがありましたが、ClosedXMLを使用した場合、速度もかなり速く利用を検討すべきだと思います。

イラストレーターで保存するとき「不明なエラーが発生しました」と出る!!保存できない人集合!!

イラストレーターで保存するとき「不明なエラーが発生しました」と出る!!保存できないじゃないか!!

という人向けの内容です!
私も出て困ったんですよねー、保存できないんですから。

 

そこで解決するために!最初はネットの情報にあったものを試してみました!

作業環境:Windows10、illustratorCC2017、メモリ8GBのデスクトップPC

 

イラレの環境ファイルを削除→PCを再起動
環境ファイルの場所は…
【users→ユーザー名→AppDate→Roaming→AdobeAdobe Illustrator 21 Settings→
ja_jp→x64→Adobe Illustrator Cloud Prefs】
Adobe Illustrator Cloud Prefsを削除する

別のサイトさんだと
【users→ユーザー名→AppDate→Roaming→AdobeAdobe Illustrator Settings→
ja_jp→x64→Adobe Illustrator Prefs】
Adobe Illustrator Prefsを削除する

でしたが、ファイルが見当たらなかったのでよく似たものを消してみました。
しかし直らないイラレが壊れることはありません)


・ファイルを作り直してコピーペーストする
直らなかった!

 

・バージョンを下げる
保存のバージョンを「illustrator CC→illustrator CS6」に変える
出なくなった!

 

・レイヤーのロックを外す
直る時と直らないときがある


(´・ω・`)え?分からないじゃん……

 

レイヤーの不具合じゃないかという話だけしか分かりませんでした。
が!作業の邪魔!なんとかしたい!って思ったので色々試しました。

とりあえず色々試したり調べたりして、回避できるかもしれない方法を見つけました。


多角形ツール+変形をして、その図形があるレイヤーをロック、または非表示にすると発生しました。
※あくまで自分の場合です

f:id:atamo_dev:20170714175640p:plain


多角形を作るだけならセーフでした。
でも、多角形作成後にその多角形の頂点や線をにゅーんと動かすとエラーが発生します

三角をよく多角形で作ってフキダシなんかを作る時に使っていました。
(次からは長方形ツールで作ろ……)

ただし、パスファインダーで合成してしまう、どこかの辺を消すなら問題ないです!
(その後変形しても問題なし)


あともう一つ試してみたのが、メモリが関係あるか
自分がいつも使っているPCは8GBです。

もう少しメモリの大きいPCでやったところ、エラーは発生しませんでした
もしかするとモリーの容量なのかも知れません。
実際のところ、原因って何なんだろう(´・ω・`)ウーン

 

多くのillustrator仲間の参考になると嬉しいです!

CocoaPodsでライブラリを公開する

プロジェクトを作成

まずはライブラリを作るためにプロジェクトを作成します。

XcodeでCreate new projectしてもいいのですが、CocoaPodsがテンプレートを公開しており、ターミナルから作成できるので今回はターミナルから作成していきます。

プロジェクト作成

以下のコマンドをターミナルで実行するとカレントディレクトリにプロジェクトが作成されます。

途中、幾つかの質問があるので、回答していきます。

pod lib create ライブラリ名

質問1 使用する言語はどちらですか?

What language do you want to use?? [ ObjC / Swift ]
> ObjC or Swift で回答

質問2 デモアプリを同梱しますか?

Would you like to include a demo application with your library? [ Yes / No ]
> Yes or No で回答

質問3 テストフレームワークを使いますか?

Which testing frameworks will you use? [ Quick / None ]
> Quick or None(使わない) で回答

質問4 Viewのテストを行いますか?

Would you like to do view based testing? [ Yes / No ]
> Yes or No で回答

成功するとXcodeが起動し、作成したプロジェクトが開きます。

ライブラリの作成

開いたプロジェクト内ソースツリーの[Pods]->[Development Pods]->[ライブラリ名]->[ライブラリ名]->[Classes]ReplaceMeというファイルがあるので、削除して自作ライブラリのファイルを配置します。

GitHubで公開

ライブラリのGitHubページを作成し、リポジトリのURLをコピーしておきます。

https://github.com/ユーザ名/ライブラリ名.git

プロジェクトファイル内のライブラリ名.podspecを編集します。

s.source: コピーしたリポジトリのURL

s.summary: 短い説明

s.description: 長い説明

#
# Be sure to run `pod lib lint ライブラリ名.podspec' to ensure this is a
# valid spec before submitting.
#
# Any lines starting with a # are optional, but their use is encouraged
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html
#

Pod::Spec.new do |s|
  s.name             = 'ライブラリ名'
  s.version          = '0.1.0'
  s.summary          = 'A short description of ライブラリ名.'

# This description is used to generate tags and improve search results.
#   * Think: What does it do? Why did you write it? What is the focus?
#   * Try to keep it short, snappy and to the point.
#   * Write the description between the DESC delimiters below.
#   * Finally, don't worry about the indent, CocoaPods strips it!

  s.description      = <<-DESC
TODO: Add long description of the pod here.
                       DESC

  s.homepage         = 'https://github.com/ユーザ名/ライブラリ名'
  # s.screenshots     = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2'
  s.license          = { :type => 'MIT', :file => 'LICENSE' }
  s.author           = { 'ユーザ名' => 'メールアドレス' }
  s.source           = { :git => 'https://github.com/ユーザ名/ライブラリ名.git', :tag => s.version.to_s }
  # s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>'

  s.ios.deployment_target = '8.0'

  s.source_files = 'ライブラリ名/Classes/**/*'
  
  # s.resource_bundles = {
  #   'ライブラリ名' => ['ライブラリ名/Assets/*.png']
  # }

  # s.public_header_files = 'Pod/Classes/**/*.h'
  # s.frameworks = 'UIKit', 'MapKit'
  # s.dependency 'AFNetworking', '~> 2.3'
end

編集後、GitHubリポジトリにPushします。

Xcode上からSource Controlブランチ名Configure ライブラリ名を開き、RemoteからGitHubリポジトリを追加します。

Source ControlCommitを選択し、左下のPush to remoteへチェックを入れたらCommit Filesを押下します。

バージョンの指定

CocoaPods上でのバージョンはGitのタグに対応するので、ターミナルから公開時のバージョンをタグで付けます

git tag 1.0.0

リモートに反映します

git push 1.0.0

確認

podspecに誤りがないか確認します。

ターミナルでプロジェクトのディレクトリへ移動し、以下のコマンドを実行します。

pod lib lint

エラー場表示される場合は修正します。

(僕は説明が短すぎると言うエラーが出ました

CocoaPods trunkへ登録する

ターミナルでコマンドを実行します

pod trunk register 公開するメール '公開する名前' --description='説明'

入力したメールアドレスへ確認メールが来るので記載されているリンクを押下します。

ターミナル上で以下のコマンドを実行して名前が表示されていれば登録が完了しています。

pod trunk me

CocoaPods trunkへ登録します。

以下のコマンドを実行

pod trunk push ライブラリ名.podspec

pod try ライブラリ名 を実行してサンプルプロジェクトが開けば登録できています。

商用フリー 和柄パターン素材

 

f:id:atamo_dev:20170701161927p:plain

個人的に作成した和柄模様の素材です。

 

素材ファイルは下記URLに配置してあります。

https://drive.google.com/drive/folders/0B9dZ314mf8WoVGxla3hXeEVBSGc?usp=sharing

再配布以外でしたら個人用途に限りご自由にお使いください。

報告も、配布元の表示も不要です。

 

各素材とも下記2種類ずつあるので用途別にお使いいただければと思います。

Illustratorスウォッチ登録用aiファイル

Photoshopのパターン定義用にpngファイル

 

By SetJapanCorporation,Inc. Designer : すんすん。

【NW】名前解決って、なに?

「名前解決」・・・不思議な言葉ですよね。
この言葉ですぐわかる人は業界の人だけでしょう
ここでいう「名前」はインターネットURL、「解決」はIPアドレス検索、でしょうか
言い換えれば「インターネットURLからサーバのIPアドレスをさがす」イメージです。

皆さんがWebサイトなど見るときよくあるパターンは・・・
インターネットURLがLINEで来たり、QRコード読んだりして、
ブラウザでWebサイト見たりします
でも、見たいWebサイトが世界のどこにあるかは知りません。

Webサイトを公開するひとは、作ったら、どこかのWebサーバに格納します。
そして、このサーバはIPアドレスを持っています。

しかし、あなたWebサーバの間にはインターネットっていう空間がある・・・
ここをどうやってくっつけているのか、かなりざっくりと見てみます。

 

では、わかりやすくRPGにたとえてみましょう。
http://www.setjapan.co.jp」のWebサイトを見るというのは・・・
「setjapan.co.jp城にいるwww王http語を使って話したい」
という感じのクエストになります。

とりあえず、あなたは一番手近にいるDNSサーバってローカルな賢者に聞きます。
パソコンやらスマホやらに設定されているけど、大体は管理者が入れてるから、ほぼユーザは知らなくてよい話。

 

 あなたsetjapan.co.jp城www王話がしたいんすけど?
ローカル賢者.jpか。それなら賢者JPRSに聞くのじゃ。」

さすがはローカル賢者、なんも知りませんが、親切な彼は次の賢者を教えてくれます。
ちなみに”.jp”は、japanの意味で、JPRSが管理しているドメイン(TLD)です。

 

 あなたsetjapan.co.jp城ってどこすか?www王っています?
賢者JPRSsetjapan.co.jp城はこの場所にある。そこのNSというものに聞け」
どうやら、たらいまわしは賢者の得意技のようです。

場所は(なんとなく)わかったので、そこいってNSって人に聞きましょう。
このNSがsetjapan.co.jp内のIPアドレス(とか、諸々)の管理してます。

 

あなた「ここsetjapan.co.jp城っすか?www王っています?」
従者NSwww王はこの場所にいる。」と、王のIPアドレスを教えてくれます

やっと、王様に会えたので、http語で話しかけてみます。
あなた「王様、あのニュースどうなってんすか?」
www王「ほれ。こんな感じじゃ。うひゃひゃひゃw」
さすがwww王、名前通り草不可避です。

とまぁ、皆さんがWebを楽しんでる裏では
毎度こんな冒険が繰り広げられてるわけです。

 

でも、そうそううまくいかないこともあり
途中でどの賢者に聞いたらいいかわからなくなったり(ドメインサーバ不明)
王の場所分かったけどいなかったり(サーバダウン)
そもそも最初の賢者がいない(DNSサーバ未設定)
などをひっくるめて、「名前解決ができない」などと言ったりします。

なお。
説明の都合上、かなり端折ったり、デフォルメしていますので
もっとDNSサーバのことを知りたい人はSetJapanの門をたたいてみましょう。

 

【C#】デバッグ時に実行されるメソッドのトレースを出力する

 今回はC#デバッグ時に実行のトレースを行う方法を紹介します。用途としては非同期の場合にどこから呼出しされているか調査したいときなどに利用できるかと思います。
 方法としては2通りでCallerMemberNameAttributeクラスを利用する方法と、StackFrameクラスを利用する方法があります。

 以下はフォームにボタンのみを配置し、ボタンを押下すると出力ウィンドウへトレースの結果が出力されるサンプルとなっています。

デザイナー側実装

namespace DebugSample
{
  partial class Form1
  {
    /// <summary>
    /// 必要なデザイナー変数です。
    /// </summary>
    private System.ComponentModel.IContainer components = null;

    /// <summary>
    /// 使用中のリソースをすべてクリーンアップします。
    /// </summary>
    /// <param name="disposing">マネージ リソースが破棄される場合 true、破棄されない場合は false です。</param>
    protected override void Dispose(bool disposing)
    {
      if (disposing && (components != null))
      {
        components.Dispose();
      }
      base.Dispose(disposing);
    }

    #region Windows フォーム デザイナーで生成されたコード

    /// <summary>
    /// デザイナー サポートに必要なメソッドです。このメソッドの内容を
    /// コード エディターで変更しないでください。
    /// </summary>
    private void InitializeComponent()
    {
      this.button1 = new System.Windows.Forms.Button();
      this.SuspendLayout();
      // 
      // button1
      // 
      this.button1.Location = new System.Drawing.Point(84, 64);
      this.button1.Name = "button1";
      this.button1.Size = new System.Drawing.Size(75, 23);
      this.button1.TabIndex = 0;
      this.button1.Text = "出力";
      this.button1.UseVisualStyleBackColor = true;
      this.button1.Click += new System.EventHandler(this.button1_Click);
      // 
      // Form1
      // 
      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
      this.ClientSize = new System.Drawing.Size(255, 146);
      this.Controls.Add(this.button1);
      this.Name = "Form1";
      this.Text = "Form1";
      this.ResumeLayout(false);

    }

    #endregion

    private System.Windows.Forms.Button button1;
  }
}


 実行サンプル用にボタンが配置してあるだけのウィンドウズフォームです。

コードビハインド側実装

using System;
using System.Windows.Forms;

namespace DebugSample
{
  /// <summary>
  /// サンプル用フォーム
  /// </summary>
  public partial class Form1 : Form
  {
    /// <summary>
    /// クラスの新しいインスタンスを生成します。
    /// </summary>
    public Form1()
    {
      InitializeComponent();
    }

    /// <summary>
    /// button1がクリックされたときに発生します。
    /// </summary>
    /// <param name="sender">呼び出し元オブジェクト</param>
    /// <param name="e">イベント引数</param>
    private void button1_Click(object sender, EventArgs e)
    {
      DebugUtil.DebugTrace("出力テスト");

      Console.WriteLine("");

      DebugUtil.DebugTrace(5);
    }
  }
}


 実行のトレース出力を行うためのユーティリティクラスです。

デバッグ用のユーティリティクラス実装

using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.CompilerServices;

namespace DebugSample
{
  /// <summary>
  /// デバッグ用のユーティリティクラス
  /// </summary>
  public static class DebugUtil
  {
    /// <summary>
    /// 呼び出し元メンバーを出力します。
    /// </summary>
    /// <param name="message">デバッグ出力するメッセージ</param>
    /// <param name="member">呼び出し元のメンバー</param>
    /// <param name="filePath">呼び出し元のファイルパス</param>
    /// <param name="line">呼び出し元の行番号</param>
    public static void DebugTrace(string message = "", [CallerFilePath] string sourceFile = "", [CallerLineNumber] int line = 0, [CallerMemberName] string member = "")
    {
      if (!String.IsNullOrEmpty(message)) { Console.WriteLine(String.Format("Message => {0} ", message)); }
      Console.WriteLine(String.Format("Source File Name => {0}", Path.GetFileName(sourceFile)));
      Console.WriteLine(String.Format("Source Directory Path => {0}", Path.GetDirectoryName(sourceFile)));
      Console.WriteLine(String.Format("Method Name => {0}", member));
      Console.WriteLine(String.Format("Line Number => {0}", line));
    }

    /// <summary>
    /// 指定したフレーム数の呼び出し元メンバーを出力します。
    /// </summary>
    /// <param name="outputLevel">スキップするスタック上のフレーム数</param>
    public static void DebugTrace(int skipFrames)
    {
      // フレーム数が0より小さい場合、処理を行わない
      if (skipFrames < 0) return;

      // フレームが1つ前になるまで出力する
      for (int i = skipFrames; 1 <= i; i--) { FrameTrace(i); }
    }

    /// <summary>
    /// 指定したフレーム数の呼び出し元メンバーを出力します。
    /// </summary>
    /// <param name="outputLevel">スキップするスタック上のフレーム数</param>
    private static void FrameTrace(int skipFrames)
    {
      var frame = new StackFrame(skipFrames);
      var method = frame.GetMethod();
      Console.WriteLine(String.Format("Method Name => {0}", method.ReflectedType.FullName + "." + method.Name));
    }
  }
}


 以下は出力結果です。

Message => 出力テスト 
Source File Name => Form1.cs
Source Directory Path => c:\Users\xxxxxx\Documents\Projects\DebugSample\DebugSample
Method Name => button1_Click
Line Number => 26

Method Name => System.Windows.Forms.Button.OnMouseUp
Method Name => System.Windows.Forms.Button.OnClick
Method Name => System.Windows.Forms.Control.OnClick
Method Name => DebugSample.Form1.button1_Click
Method Name => DebugSample.DebugUtil.DebugTrace

 ユーティリティクラスのDebugTraceメソッドでメッセージ引数を持つメソッドの場合、行番号までが出力されます。
 DebugTraceメソッドでフレーム数引数を持つメソッドの場合、名前空間.クラス.メソッド名で出力されます。

ポートフォリオの表紙の作り方!(テンション高め)

ハローこんにちは!初めまして!


突然ですが!今就活をしているデザイナーさんやイラストレーターさん向けに、ポートフォリオについてのお話をしようかと思います。
ポートフォリオ片手に?いやいや、お菓子やコーヒー片手に!
まったーりしながらお聞きくださいね。

あなたはポートフォリオをどのように作っていますか?
真っ白な背景に頑張って作った作品を並べて印刷!ハイ完成!
というのはやめましょう。
分かります、まる分かりです、時間なかったとかバイト忙しいとか言い訳です、世界は残酷です……。
でも、あなたの夢を目指す魂はそんなもので尽きませんよね!
「作品に心をこめて、全ての思いを相手に伝える」ポートフォリオを作りましょう!


……いろいろ言いたいことはありますが、まずは一個だけ。


表紙には命をかける!


これです。ハイ。

……正直、文字って読むのが面倒なんですよねー。
文字の集合体を見ると、拒絶反応が起きますね!
もっとわかりやすくしてほしいなー……。
って思った私が、表紙を作っちゃいました。

 

ポイントとしては……

表紙は見られるか見られないかということも関わる顔の役目なので、いい作品を持ってくること。

ただし、全力を出すのはだめですよ?
全力を出せば、それ以上見る意味が無くなりますから。
そこで「チラ見(試し読み)」のような手段を使います。
「続きを見なきゃ!気になる!」って思わせる方法です。
ここでレイアウトが役に立ちます。
いい作品をチラ見させ、あえて全体が見えないようにする。
パッと見てまとまりがあるうえ、綺麗に整頓されていることで上級感を出します。
項目ごとのピックアップをひとつづつ……だとさらにいいと思いますよ!

 

f:id:atamo_dev:20170602181514p:plain


そんな感じで実際に創った表紙がこれです。

何が出来るの?っていうのが一発で分かるけど、細かいところは中じゃないと分からないっていうのがいいですよっ!


どうですか?

めくってみたくなるでしょう?