ごらくらいふ

プログラミングしたりゲームしたり

FacebookSDK 3.x -> 4.x : FBRequestConnection startWithGraphPath:completionHandler:が無くなったので FBSDKGraphRequest startWithCompletionHandler:を使う

記事タイトルキャメルケースでキッツキツだな。

結論

3.xにてGraphAPIを手軽に叩くため、FBRequestConnection startWithGraphPath:completionHandler:を使っていた。

4.xでは失くなってしまったのでFBSDKGraphRequest startWithCompletionHandler:を使った。

コードで見る違い

3.x

- (void) callGraphApi:(NSString*)graphPath {
    [FBRequestConnection startWithGraphPath:graphPath completionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
    }];
}

4.x

- (void) callGraphApi:(NSString*)graphPath {
    // 一個一個変数化するとデバッグしやすくて好き
    FBSDKGraphRequest* fbRequest = [[FBSDKGraphRequest alloc] initWithGraphPath:graphPath parameters:nil];
    [fbRequest startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
    }];
}

「なんでじゃ」と思ったこと集

  • FBRequestConnectionでやってたことがFBSDKGraphRequestConnectionではなくFBSDKGraphRequestに納まっていたこと
  • FBSDKGraphRequest startWithCompletionHandler:のコールバック、FBSDKGraphRequestHandlerの定義がFBSDKGraphRequestConnectionにあったこと
  • よくみるとFBSDKGraphRequestConnectionFBSDKGraphRequestをimportしておらず、その逆だったこと
    • 依存の仕方が直感に沿わない…内部クラスかしら?って思った

FacebookSDK 3.x -> 4.x : FBLoginView無くなったのでFBSDKLoginButtonを使った

Facebook APIバージョン v2.0 が非推奨間近*1のため尻に火が点いている。 消火活動で代替処理がわかったっぽいので記録。

(追記:2016/07/21 22:13) 3.x のログイン(ログアウト)時の処理の認識が間違っていたので修正。 仮にログイン時にNavigationControllerにPushするような実装をしていたら「画面を戻ろうとしているのに戻れない」現象が発生するはず。

改修内容

3.xでの擬似コード

// TheViewController.h

#import <FacebookSDK/FacebookSDK.h>
@interface TheViewController : UIViewController<FBLoginViewDelegate>
@end
// TheViewController.m

@interface TheViewController()
@property (nonatomic) FBLoginView* loginView;

@end

@implementation TheViewController
- (void)viewDidLoad{
    self.loginView = [[FBLoginView alloc] init];
}
- (void)viewDidAppear:(BOOL)animated{
    // viewの位置を真ん中にちょちょいとする
    CGRect bounds = [UIScreen mainScreen].bounds;
    CGRect rect = self.loginView.frame;
    rect.origin.x = (bounds.size.width - rect.size.width) / 2.0;
    rect.origin.y = (bounds.size.height - rect.size.height) / 2.0;
    self.loginView.frame = rect;

    // delegateの指定
    self.loginView.delegate = self;

    // 読み込み権限の指定
    self.loginView.readPermissions = @[@"public_profile", @"read_stream"];

    // 表示
    [self.view addSubView:self.loginView];
}

// FBLoginViewDelegate
-(void)loginViewFetchedUserInfo:(FBLoginView *)loginView user:(id<FBGraphUser>)user{
    // (とくになにもしていなかった……)
}
-(void)loginViewShowingLoggedInUser:(FBLoginView *)loginView{
    // ログインしている状態でLoginViewを表示したときの処理
}
-(void)loginViewShowingLoggedOutUser:(FBLoginView *)loginView{
    // ログアウトしている状態でLoginViewを表示したときの処理
}
@end

4.xでの擬似コード

// TheViewController.h

#import <FBSDKCoreKit/FBSDKCoreKit.h>
#import <FBSDKLoginKit/FBSDKLoginKit.h>
@interface TheViewController : UIViewController<FBSDKLoginButtonDelegate>
@end
// TheViewController.m

@interface TheViewController()
@property (nonatomic) FBLoginView* loginView;
@property (nonatomic) BOOL isLoggedIN;

@end

@implementation TheViewController
- (void)viewDidLoad{
    self.loginView = [[FBLoginView alloc] init];
}
- (void)viewDidAppear:(BOOL)animated{
    // viewの位置を真ん中にちょちょいとする
    self.fbLoginButton.center = self.view.center;

    // delegateの指定
    self.fbLoginButton.delegate = self;

    // 読み込み権限の指定
    self.fbLoginButton.readPermissions = @[@"public_profile", @"read_stream"];

    // 表示
    [self.view addSubView:self.fbLoginButton];

    // ログイン状態による処理分けはここに移植する
    if([FBSDKAccessToken currentAccessToken]) {
    } else {
    }
}

// FBSDKLoginButtonDelegate

-(BOOL)loginButtonWillLogin:(FBSDKLoginButton *)loginButton{
    // ログイン前処理
    // NOを返すと処理を中止するらしい。APIリファレンスに書いておいてほしい。
    return YES;
}
-(void)loginButton:(FBSDKLoginButton *)loginButton didCompleteWithResult:(FBSDKLoginManagerLoginResult *)result error:(NSError *)error {
    // ログイン処理を完了した時
    if (error) {
        return;
    }    
    if (result.isCancelled) {
        return;
    }
    if ([result.declinedPermissions containsObject:@"required permission"]) {
        return;
    }
    
    // ログイン完了
    // ログイン時の処理
}
-(void)loginButtonDidLogOut:(FBSDKLoginButton *)loginButton{
    // ログアウト完了
    // ログアウト時の処理
}
@end

*1:v2.1が公開されてから2年になるため

既存のXcodeプロジェクトにCocoaPodsを入れたらビルドエラー ld: library not found for -lPods

既存のプロジェクトにCocoaPodsを入れて、早速buildしたら次のようなエラーが出た。

ld: library not found for -lPods-ProjectName

対処方法をggrといくつかあって悩んだので、*1*2公式を確認した。

guides.cocoapods.org

Using the CocoaPods Project項目4 に答えがあった。

If Xcode complains when linking, e.g. Library not found for -lPods, it doesn't detect the implicit dependencies:
  • Go to Product > Edit Scheme
  • Click on Build
  • Add the Pods static library, and make sure it's at the top of the list
  • Clean and build again

以下にも続きがあるが、自分はこの時点で解決した。

他プロジェクトの生成物を使うので、先にbuildしましょう。ということかと。

Manage schemeで別途buildすると、「ライブラリのアップデートが反映されねぇ!」ってなりそうだからこっちの方法が良さそう。

*1:Manage schemeからPodsプロジェクトをshowするとか

*2:Edit schemeで対処するとか

続・リリースするファイルに対応したバックアップを作る

↓この処理をシェルスクリプトにした。 yajamon.hatenablog.com

#!/bin/bash

src=$1
dest=$2
backup=$3

# backupのパスがファイルなら終了
if [ -f $backup ] ; then
    echo "\$backup is file"
    exit 1
fi

# srcと同じディレクトリ構造のbackupディレクトリを作る
if [ ! -e $backup ] ; then
    echo "make directory: $backup"
    mkdir $backup
    echo "create: "$(cd $backup; pwd)
fi

# 続行するか念のために確認
echo "   src: $src"
echo "  dest: $dest"
echo "backup: $backup"
while [ "$goSign" = "" ]
do
    echo "execute ok? (yes/no)"
    read goSign
done

if [ $goSign != "yes" ] ; then
    echo "abort"
    exit 1
fi

cp -rv $src/* $backup/
echo "clean to $backup"
find $backup -type f -exec rm -v {} \;

# src内のファイルパスをもとに、destからbackupへコピーする
for item in $(find ${src} -type f | sed -e "s/^${src}//g")
do
    cp -v $dest$item $backup$item
done

feedlyでニコニコ動画のマイリストRSSを監視して新着を逃さないようにした

おれ しった かく。

マイリストの新着管理

  • プレイ動画とかシリーズ物の追跡をしたい。
  • RSS配信が生きてるらしいのでfeedlyに登録する。

chrome拡張入れると画面右下にボタン追加されて登録が楽。 chrome.google.com

手順

  1. 追跡したいマイリストを開く
    • f:id:yajamon:20160610190328p:plain
  2. feedly拡張をポチッとして登録する
    • f:id:yajamon:20160610190415p:plain
  3. 新着を待つ

手軽。

手軽だわ。どれブラウザから試しにひとつ…

f:id:yajamon:20160610191236p:plain

f:id:yajamon:20160610191553g:plain

ワンクッションおいて解決

IFTTTでSlackに流し込んで解決した。

togglを三日坊主する

こういう脇道をせずにそのまま仕事をすればそのまま成果になるだろうに、逸れちゃうんだな、これが。

time tracking web service "toggl"を、とりあえず三日坊主する。

また三日坊主するときのために書き方まとめ。

何を記入するか

タスク

  • 行動のタイトルをサッと書く。

プロジェクト

  • プロジェクト名が明確ならそのまま書く
  • プロジェクト名が無いようなタスクの場合
    • 飯を食うとか風呂とか→生活→Life
    • アニメを見る→期毎に分けてもいい→Anime-YYYY-春

アルファベット表記を使えるなら使う。フィルタかけるのが楽になるから。

クライアント
  • 自社のプロジェクト→自社とわかるやつ
  • 他者のプロジェクト→他社とわかるやつ
  • 自分用→Me

タグ

  • すきなように

iPadでdvorak jpほしい

f:id:yajamon:20160419210359p:plain

無いから作ってる。

とりあえずアルファベット直輸入と末梢できるようにしたよ。

f:id:yajamon:20160419210541p:plain

f:id:yajamon:20160419210640p:plain

ハハッワロス

入力中の文字列をinputAccessoryViewに表示したいけど、UITextViewとか入力先が保持してるパターンの資料しか見つかってないので辛い。

ローマ字テーブルも作らなきゃ