Swiftのインスタンスから型メソッド(クラスメソッド)を呼び出す方法
背景
あるクラスのインスタンスから、そのクラスの型メソッド(クラスメソッド)を呼び出したいときにObjective-Cでは下記のようにやっていたけれどSwiftだとどう書くのか知りたかった
[[instance class] classMethod];
結論
dynamicTypeを使うことでインスタンスから型メソッド(クラスメソッド)へのアクセスが可能になる
class SampleClass() { //型メソッド(クラスメソッド) static func sampleClassMethod() { print("sampleClassMethod") } } //普通の型メソッド(クラスメソッド)の呼び出し方 SampleClass.sampleClassMethod() //sampleClassMethod //インスタンスからクラスメソッドへのアクセス let sampleClass = SampleClass() sampleClass.dynamicType.sampleClassMethod() //sampleClassMethod
dynamicTypeとはなんぞや?
dynamicTypeを使うとインスタンスのクラス自身(サブクラス化されていればサブクラス)が参照できるようです
let sampleClass = SampleClass() print(sampleClass.dynamicType) //SampleClass if sampleClass.dynamicType == SampleClass.self { print("true") //true }
tableViewCell上にUISliderを載せてアニメーションしたらおかしくなる件
事象
カスタムのUITableViewCell上にUISliderをaddしてcellforRowで読み込まれると同時にSliderをアニメーションしてみたのだけれど、minimumTrackTintColorとmaximumTrackTintColor割合がおかしく、明らかに変なアニメーションをしだした。
解決方法
Sliderのアニメーションをdispatch_afterで遅らせてやるとうまくいった。
ちなみに[UIView animateKeyframesWithDuration...のdelay:をセットしてもダメだった。
下記サンプルではtag10にUISliderが紐付けられているものとする。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ UISlider *slider = (UISlider *)[cell viewWithTag:10]; slider.value = 0; [UIView animateKeyframesWithDuration:1 delay:0 options:UIViewKeyframeAnimationOptionAllowUserInteraction animations:^{ [slider setValue:0.8 animated:YES]; } completion:^(BOOL finished) { }]; }); return cell; }
うまくいかない時は遅延処理させると解決するのは結構あるけど、 delayじゃなくdispatch_after使わないとダメだったとは。。
かなりの時間を使ってしまったので久しぶりにメモ。
Android Studio0.8.14にしたらエラーしまくった
背景
Android Studioのverを0.8.14にしたらエラーになったので解決方法をメモ
解決方法
まず、アップデートしているとAndroid Studio配下にsdkフォルダを配置するなと怒られるので、sdkの場所をmvコマンドで適当な場所に移す。
sdkを移した後にリトライすれば0.8.14に上がる。
Android Studioを起動した際にsdkがないと言われるので、sdkを移動したパスを設定する。
その後に、新規プロジェクト作成したら今度はAndroid APIの最新である21を使うにはjdk1.7を使えというエラー。
OracleからJava SE Development Kit 7u71をダウンロードしてjdkをjdk1.7.0_71.jdk/Contents/Homeを使うように設定してようやく動いた。
Android Studioはまだbeta版だからいろいろと仕様が変わるのですね。
ありえん。。
追記 新規でAndroid Studio0.8.14をインストールする場合はここが大変参考になります。
NSLayoutConstraintを使ってAutoLayoutをコードで書く
背景
AutoLayoutをxib上で使っているのだけれどxibでは表現できるAutoLayoutに限界があると思いコードで書く方法を調べたのでメモ。
サンプル
1.self.viewから左20,上20のマージンをとった位置にwidth100,height100の赤いViewを配置
UIView *redView = [[UIView alloc] init]; redView.backgroundColor = [UIColor redColor]; redView.translatesAutoresizingMaskIntoConstraints = NO; [self.view addSubview:redView]; NSLayoutConstraint *redLeftConstraint = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1 constant:20]; NSLayoutConstraint *redTopConstraint = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.topLayoutGuide attribute:NSLayoutAttributeTop multiplier:1 constant:20]; NSLayoutConstraint *redWidthConstraint = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:100]; NSLayoutConstraint *redHeightConstraint = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:100]; [self.view addConstraints:@[redLeftConstraint, redTopConstraint, redWidthConstraint, redHeightConstraint]];
2.self.viewのbottom部分に幅=端末幅,高さ40の青いView配置
UIView *blueView = [[UIView alloc] init]; blueView.backgroundColor = [UIColor blueColor]; blueView.translatesAutoresizingMaskIntoConstraints = NO; [self.view addSubview:blueView]; NSLayoutConstraint *blueLeftConstraint = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1 constant:0]; NSLayoutConstraint *blueRightConstraint = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1 constant:0]; NSLayoutConstraint *blueHeightConstraint = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:40]; NSLayoutConstraint *blueTopConstraint = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1 constant:-blueHeightConstraint.constant]; [self.view addConstraints:@[blueLeftConstraint, blueRightConstraint, blueTopConstraint, blueHeightConstraint]];
3.self.viewのcenter座標に幅=self.view.frame.width/2 高さ=self.view.frame.height/2 の黄色Viewを配置
UIView *yellowView = [[UIView alloc] init]; yellowView.backgroundColor = [UIColor yellowColor]; yellowView.translatesAutoresizingMaskIntoConstraints = NO; [self.view addSubview:yellowView]; NSLayoutConstraint *yellowCenterXConstraint = [NSLayoutConstraint constraintWithItem:yellowView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]; NSLayoutConstraint *yellowCenterYConstraint = [NSLayoutConstraint constraintWithItem:yellowView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]; NSLayoutConstraint *yellowWidthConstraint = [NSLayoutConstraint constraintWithItem:yellowView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeWidth multiplier:.5 constant:0]; NSLayoutConstraint *yellowHeightConstraint = [NSLayoutConstraint constraintWithItem:yellowView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeHeight multiplier:.5 constant:0]; [self.view addConstraints:@[yellowCenterXConstraint, yellowCenterYConstraint, yellowWidthConstraint, yellowHeightConstraint]];
共通する部分としてViewのtranslatesAutoresizingMaskIntoConstraintsプロパティは必ずNOにすること。
これをしないとAutolayoutが適用されない。
Viewを作成する際にinitWithFrame:で幅と高さを指定しても意味はないのでNSLayoutConstraintのメソッドで幅と高さの制約を作る必要がある。
組み合わせや使い方によっては柔軟なものができそうであるが、それにしてもNSLayoutConstraintはマゾい
なので今度Masonryを試してみようと思う。
iOS7とiOS8でUIScreenのboundsのサイズが違うので対応する
背景
iOS8からUIScreenのboundsを取得すると端末の向きに応じてwidthとheightの値が変更されるようになりLandscape対応でちょっと困ったのでメモ
iOS7とiOS8で差分を埋める
+ (CGSize)mainScreenSize { CGSize screenSize = [UIScreen mainScreen].bounds.size; if ((NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1) && UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)) { return CGSizeMake(screenSize.height, screenSize.width); } return screenSize; }
これでiOS7でもiOS8と同様のサイズを返すです。
重複件数まで取得できるNSCountedSet
背景
例えばこんな問題があったとする。
インプットした文字列の単語の重複件数を求めなさい。
例) banana
答) b: 1 a: 3 n: 2
この問題を何か効率的に処理できる方法はないかと考えたときにNSCountedSetを見つけたので使い方をメモ。
使い方
NSCountedSetはNSMutableSetのサブクラスなので当然、格納した際に重複しているものは取り除かれるのだが、取り除く際に重複のcount数を保持している。
なので上記の問題に対応するコードをNSCountedSetを使用して書くとこうなる。
NSString *text = @"banana"; NSCountedSet *countSet = [NSCountedSet set]; int total = [text length]; for (int i = 0; i < total; i++) { [countSet addObject:[text substringWithRange:NSMakeRange(i, 1)]]; } for (NSString *word in countSet) { NSLog(@"%@:%@", word, @([countSet countForObject:word])); }
出力結果
b:1 a:3 n:2
ちょっと便利な気がするー。
git clone --recursive をするとサブモジュールも一緒に持ってきてくれる
背景
SDWebImageのDemoを動かしたくてgit cloneして動かしたらfile not foundでエラーになった。
解決方法
SDWebImageはサブモジュールを使用しているので、それも一緒に入れてやる必要がある。
なのでgit clone する際に --recursive オプションをつけてやるとサブモジュールも一緒に入れてくれる。
git clone --recursive https://github.com/rs/SDWebImage.git Cloning into 'SDWebImage'... remote: Reusing existing pack: 2754, done. remote: Total 2754 (delta 0), reused 0 (delta 0) Receiving objects: 100% (2754/2754), 3.64 MiB | 294.00 KiB/s, done. Resolving deltas: 100% (1600/1600), done. Checking connectivity... done. Submodule 'Vendors/libwebp' (http://git.chromium.org/webm/libwebp.git) registered for path 'Vendors/libwebp' Cloning into 'Vendors/libwebp'... remote: Counting objects: 11978, done. remote: Compressing objects: 100% (3941/3941), done. remote: Total 11978 (delta 9284), reused 10570 (delta 8029) Receiving objects: 100% (11978/11978), 4.53 MiB | 431.00 KiB/s, done. Resolving deltas: 100% (9284/9284), done. Checking connectivity... done. Submodule path 'Vendors/libwebp': checked out '68e7901da53cbda6ec93ddf93e039346d3c6a531'
--recursiveを使っていきましょー。