2015/08/17

フリーランスとして活動し始めて(2015年2月〜)、半年が経ちました

フリーランスとして活動し始めて(2015年2月〜)、半年が経ちました。
以前、三ヶ月経過後の記事を書きましたが、今回も制作実績を残しておきます。前回の記事はこちら
中には秘密保持契約のためサービス名など明記していないものもあります。

8月

  • iOS新規案件、追加機能対応(UIの挙動変更、アニメーションなど)(Swift,Realm
  • Campus Voice追加機能(Swift)
  • iPadエンタープライズアプリ(新規、Swift)

7月

  • iOS新規案件、追加機能対応(Swift,Realm)
  • Campus Voice追加機能(Swift)
  • iPadエンタープライズアプリ(新規、Swift)
  • toC向けWebサービス、サーバサイド機能追加(LAMP環境)
  • 新規iOSアプリ修正案件(iOS 8 Swift/Objective-C)

6月

  • Campus Voiceという匿名型twitterのような匿名投稿SNSアプリを新規開発(iOS8.0〜,Swift,サーバサイドAPI開発、DB構築、CentOS 6.6構築、S3画像キャッシュ、その他ミドルウェア導入。バックエンドからクライアントアプリまですべて対応)
  • Campus Voice追加機能(Swift)
  • 新規iOSアプリ修正案件、(iOS 8 Swift/Objective-C)

振り返り

前回の三ヶ月と比べると希望通りiOS案件が増えていい感じです。
残りの半年は受託案件を少し減らして、新規でアプリを作りたいなと思っています。
受託のスキームが確立できれば、落ち着いてサービス開発に重点をおけるので、ここは試行錯誤しながらやっていく。アイディアだけはたくさんある、あとは形にするだけ。

見積に関して

見積を誤ると面倒なことになるので。
パターンが何個かあるので、明記しておく。
・そもそも仕様が決まっていない場合
仕様を決めずに作りながら開発していって月額の専属契約を結ぶ、週単位での報告
・仕様が決まっている(プロトタイプ案件 数人日レベル)
見通しがつきやすいので見積が出せる。
不明点を確認し、すり合わせ後、見積、発注、着手。
・仕様がだいたい決まっている(中規模、大規模)
イメージとしてはあるが画面の構成などの具体的な仕様がない場合、
おおまかな見積を出して、当初の確定した仕様に変更があれば、
追加費用をいただく形。ただこの方法はあまりおすすめできないので、
やったことがないが、お客さんのところにいって作業後、日数分請求という形が望ましいかもしれない。お客さんも相談しやすいし、その場にいれば修正指示など、進捗報告などすぐできる。
もしくは定期的に週一で確認で作業日数分、請求。
・仕様が決まっている(中規模、大規模)
仕様が詳細なので、すり合わせの数が少なくて済むのですぐ見積が可能。
工数が大きいと、気持ちは変わるもので、やっぱりこうしたいみたいなことはあるので、そこは内容によっては柔軟に対応するか、釘を挿しておくかどちらか。
このパターンはほとんどない。

困ったこと

案件の掛け持ちが多く、余裕がなくなってきているので、ここが課題。
アウトソースするなり、方法を考える。
iOS、Swift書ける方、アルバイト募集しております。

教訓てきな

マルチタスクが当たり前になって、休むタイミングが分からない時があるが、
あえて何もせずぼーっとする時間を作って、思索にふける時間を作る。
やらないことを決めるのがいい。
ごく当たり前のことだと思いますが、
行き詰まったことや、自分でどうにも解決できそうにないことがあれば、誰かに相談したり、
アドバイスを求めること。助言いただいた方には感謝しております。
問題があれば、それを解決するための努力を怠らないこと、うやむやにしたり、
放置したり、忙しさにかまけて、無視しない、必ず解決できる方法はあると信じて、そのための時間を作る。
これはプログラムにかぎらず、顧客折衝全般にも言えること。

息抜きは

今後の目標

  • 役に立ってかつ、ひとひねりあるおもしろい、そんなサービスを企画、開発する(アイディア or サンプルはあるがリリースまでもっていけてない、、、)
    →☓アイディアは出した、あとは実装
  • 興味、関心があるプロジェクトに参画し、それをお金に変える(利益を求め過ぎない)
    →△やりたいことはできてきている
  • オープンソースに貢献する
    →githubに全然pushできてない、、
  • 来年はWWDCに行く
  • 仕事がらみで海外に行く
  • ブログの更新頻度をあげる
    →△微妙

おわりに

残りの半年は気負わずぼちぼちやっていきます。
法人化することを検討していますが、税制面でのメリットなどよく知らないので、どなたか詳しい方、教えていただけるとすごく助かります。よろしくお願い致します。

2015/08/13

Swift UIPickerViewで選択した箇所の背景色など、UIを変更する(ピッカーのカスタム)

picker.gif

Pickerの各行のラベルをカスタム

選択状態となった際に、viewForRowデリゲートメソッドにて、背景用のラベルの背景色を変更する。
下記はあくまでサンプルなので、UILabelのサブクラス作成ですっきりさせた方がよい。

//
//  ViewController.swift
//  pickerTest
//
//  Created by matz on 2015/08/13.
//  Copyright (c) 2015年 matz. All rights reserved.
//

import UIKit

final class ViewController: UIViewController,
    UIPickerViewDataSource,UIPickerViewDelegate
{

    @IBOutlet weak var picker: UIPickerView!
    private var preSelectedLb:UILabel!
    private let prefectures: NSArray =
    ["北海道","青森県","岩手県","宮城県","秋田県","山形県","福島県","茨城県","栃木県","群馬県","埼玉県","千葉県","東京都","神奈川県","新潟県","富山県","石川県","福井県","山梨県","長野県","岐阜県","静岡県","愛知県","三重県","滋賀県","京都府","大阪府","兵庫県","奈良県","和歌山県","鳥取県","島根県","岡山県","広島県","山口県","徳島県","香川県","愛媛県","高知県","福岡県","佐賀県","長崎県","熊本県","大分県","宮崎県","鹿児島県","沖縄県"
    ]

    override func viewDidLoad() {
        super.viewDidLoad()
        picker.delegate = self
        picker.dataSource = self
        // 初期選択させるのであれば
//        self.preSelectedLb = picker.viewForRow(0, forComponent: 0) as! UILabel
    }

    // 列数
    func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
        return 1
    }

    // 行数
    func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return prefectures.count
    }

    // pickerに表示するUIViewを返す
    func pickerView(pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusingView view: UIView!) -> UIView {

        let pickerLabel = UILabel()
        let titleData = prefectures[row] as! String
        let myTitle = NSAttributedString(string: titleData, attributes: [NSFontAttributeName:UIFont(name: "HiraKakuProN-W3", size: 20.0)!,NSForegroundColorAttributeName:UIColor.grayColor()])

        // fontサイズ、テキスト
        pickerLabel.attributedText = myTitle
        // 中央寄せ ※これを指定しないとセンターにならない
        pickerLabel.textAlignment = NSTextAlignment.Center
        pickerLabel.frame = CGRectMake(0, 0, 200, 30)
        // ラベルを角丸に
        pickerLabel.layer.masksToBounds = true
        pickerLabel.layer.cornerRadius = 5.0

        // 既存ラベル、選択状態のラベルが存在している
       if let lb = pickerView.viewForRow(row, forComponent: component) as? UILabel,
            let selected = self.preSelectedLb {
            // 設定
            self.preSelectedLb = lb
            self.preSelectedLb.backgroundColor = UIColor.orangeColor()
            self.preSelectedLb.textColor = UIColor.whiteColor()
        }

        return pickerLabel
    }


    // pickerに表示する値を返す ※viewForRowがあればこちらは単純にタイトルを返すだけなので不要
//    func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
//        return prefectures[row] as! String
//    }


    // pickerが選択された際に呼ばれる
    func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        println("row: \(row)")
        println("value: \(prefectures[row])")

        // 選択状態のラベルを代入
        self.preSelectedLb = pickerView.viewForRow(row, forComponent: component) as! UILabel
        // ピッカーのリロードでviewForRowが呼ばれる
        pickerView.reloadComponent(component)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

参考

2015/07/02

お手伝いさせていただいたJames Apple Watchアプリの紹介です




東京(世田谷区、港区)で利用できるコンシェルジュサービスです。
実装自体はWatch OS 1 × Swiftです。

ライトプラン月額1万円で調べ物や報告などしてくれます。
プレミアムプラン月額25万円なら、あなたのしたい、あらゆることを実現してくれます(※専任の執事が人力で。ドローンでの配達などの実証実験などもやられてますが、実現はまだ未来の話)

Watchアプリからいつでも依頼を確認、スタンプ送信や、音声依頼をお願いすることなどできますよ。
まだまだ富裕層の方向けのサービスかと思いますが、一万円でも簡単な調査(渋谷近辺で3~5,000円位で和食か洋食でビジネスランチできるところを調査。個室で静かなお店が希望とか、鼻と小鼻の皮脂でテカリとお化粧崩れしにくい効果のある化粧下地などを調査など)など何でも調査してくれます。

近辺にお住みの方は是非検討してみてください。
https://yourjam.es/

2015/07/01

Swiftでリンク検出(標準APIで検出する場合とカスタムクラスの2パターン)

実現方法

①正規表現書かなくていい場合
NSDataDetectorでリンク検出
let msg:NSString = "http://hoge.com"
let dataDetector =  NSDataDetector(types:NSTextCheckingType.Link.rawValue, error: nil)

let resultArray:NSArray = dataDetector?.matchesInString(msg as String!, options: nil, range: NSMakeRange(0, msg.length)) as NSArray!

for result in resultArray {
    if result.resultType == NSTextCheckingType.Link {
        var url:NSURL! = result.URL!
        linkExist = true
    }
}
②自前で用意する場合
class Regex {
    let internalExpression: NSRegularExpression
    let pattern: String

    init(_ pattern: String) {
        self.pattern = pattern
        var error: NSError?
        self.internalExpression = NSRegularExpression(pattern: pattern, options: .CaseInsensitive, error: &error)!
    }

    func test(input: String) -> Bool {
        let matches = self.internalExpression.matchesInString(input, options: nil, range:NSMakeRange(0, count(input)))
        return matches.count > 0
    }
}

if Regex("^https?://.*").test("http://hoge.com") {  
    // linkExist
}

参考

2015/06/19

Swift 丸アイコン内、テキストセンター描画

UIViewのカスタムクラスにて、overrideしたdrawRect内で、
// 丸描画
let roundRect = UIBezierPath(roundedRect: CGRectMake(1, 1, 28, 28), cornerRadius: 10)
UIColor.blueColor().setStroke()
roundRect.lineWidth = 2
roundRect.stroke()

// フォント属性
let fontAttr = [NSFontAttributeName: UIFont.systemFontOfSize(10)]
// テキスト
let str = self.initial_txt! as NSString!
// サイズ取得
let size = str.sizeWithAttributes(fontAttr)

let x_pos = (roundRect.bounds.size.width - size.width) / 2
let y_pos = (roundRect.bounds.size.height - size.height) / 2

// テキスト描画
str.drawAtPoint(CGPointMake(roundRect.bounds.origin.x + x_pos, roundRect.bounds.origin.y + y_pos),
    withAttributes: fontAttr)

結果

initial.png

参考


2015/06/17

Swiftでテキスト内リンク&テキストタップ検出


指定したテキスト内にリンクを設定したいことがあります。
@you_matz #swiftなどをリンクとして埋め込みたい場合
そしてそのリンクをタップした際に別の画面に遷移させるなど。

実現方法

①UITextViewのプロパティの設定

textView.userInteractionEnabled = true
textView.editable = false

// tapでテキストのポジション検出可能とするため
textView.selectable = true

// 行間レイアウト用
// textView.layoutManager.delegate = self

②テキスト内リンク範囲指定

let text = "Swiftでテキスト内リンク&テキストタップ検出"
let linkText = "リンク"
let nsTex = text as NSString
let link = text.rangeOfString(linkText)
let attributedString = NSMutableAttributedString(string: text)
let start = distance(text.startIndex, link!.startIndex)
let length = distance(link!.startIndex, link!.endIndex)

// リンク位置範囲生成
range = NSMakeRange(start, length)

③textviewに指定した色、カラー、下線を指定後、代入

// テキスト全体文字色
attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.whiteColor(), range: NSMakeRange(0, nsTex.length))

// リンクカラー
attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.blueColor(), range: range)

// リンク下線
attributedString.addAttribute(NSUnderlineStyleAttributeName, value: NSUnderlineStyle.StyleSingle.rawValue, range: range)
// 属性を代入
textView.attributedText = attributedString

④textViewにgesture追加

// gesture追加
let tap = UITapGestureRecognizer(target: self, action: "tapText:")
textView.addGestureRecognizer(tap)

⑤tap時の動作

func tapText(tap: UITapGestureRecognizer) {

    // タップされた座標をもとに最寄りの文字列の位置を取得
    let location = tap.locationInView(textView)
    let textPosition = textView.closestPositionToPoint(location)

    // テキストの先頭とタップした文字の距離をNSIntegerで取得
    let selectedPosition = firstTextView.offsetFromPosition(firstTextView.beginningOfDocument, toPosition: textPosition!)

    // タップした文字がリンク文字のrangeに含まれるか判定
    if NSLocationInRange(selectedPosition, range) {

        // リンクタップ時の処理
        // let webVC = WebViewController()
        // self.presentViewController(webVC, animated: true, completion: nil)    
    }
}

参考

NSAttributedStringを使ってリンク文字を作る(Objective-C)
https://gist.github.com/yoshimin/858d14751fc1c00807d2
UITextView でタップ可能なリンクをカスタマイズする
http://kishikawakatsumi.hatenablog.com/entry/20130605/1370370925