原文(NSString)から改行とスペースを除いてラベル表示
▼やりたいこと
【改行と空文字が入っている文字列から
改行とスペースを除き、2行分まで表示して残りを省略】
▼つまりこういうこと
[原文]
///////////////////////////////////////////////////////////////////////////
はじめまして。
プロフィールを読んで頂きありがとうございます!
□□に住んで□□年になります。
出身は□□です。
仕事は□□をしています。
趣味は□□や□□です。
最近の休日はカフェで本を読んだり、ショッピングに出かけることが多いです。
///////////////////////////////////////////////////////////////////////////
↓
[表示]
///////////////////////////////////////////////////////////////////////////
はじめまして。プロフィールを読んで頂きありがとうございま
す!□□に住んで□□年になります。出身は□□です。仕事...
///////////////////////////////////////////////////////////////////////////
▼STEP①
一発で出来たら便利だなーと思いながらとりあえずぐぐる。
出た!
http://obc-fight.blogspot.jp/2012/07/nsstring-trim-spaces.html
これでいけるんじゃ?(´゜∀゜`)とかテンション高めに使ってみたが
何も起こらない。w
▼STEP②
と思ったら、同じようにハマっている方がいた。
なるほどー。「文字列の両端から」ってのは多分英文とかそゆことなのかな?
よし、じゃあこれで@"\n"を@""に置換しちゃえー(´゜∀゜`)
とかテンション高めに使ってみたが
何も起こらない。w
とりあえずここで全角スペースだけは空文字に置換するようにしてと。
▼STEP③
気を取り直してようやく発見!
http://qiita.com/Ushio@github/items/828d0c806b72c4b71d8d
これを使うと下記のように一行ごとに配列に格納される。
("はじめまして。",
"プロフィールを読んで頂きありがとうございます!",
"",
"□□に住んで□□年になります。", ...);
あとはNSMutableStringをいっこ用意して、
for文で配列の要素分回して
空文字(空の行)じゃなかったらどんどんappendして繋げてあげればひとまず
///////////////////////////////////////////////////////////////////////////
はじめまして。プロフィールを読んで頂きありがとうございます!□□に住んで□□年になります。出身は□□です。仕事は□□をしています。趣味は□□や□□です。最近の休日はカフェで本を読んだり、ショッピングに出かけることが多いです。
///////////////////////////////////////////////////////////////////////////
という文章が完成。おしゃ!\(^ω^\)( /^ω^)/
▼ラベルを用意
ここまで来たらあとはLabel側で調整。
numberOfLinesを2に設定して、sizeToFitをかけるのと、
尻すぼみにするのはこちらを参考にして実装。
http://pirosikick.hateblo.jp/entry/20100816/1281972881
▼完成版コード
ちょっと複雑なことしてるのは
テーブルビューのセルを可変にするためにやってるだけです。
廃止になったメソッドのケアもして、iOS7とiOS6でラベルの作り方わけてます。
+ (UILabel *)createLabel:(NSString *)originalText
{
if ([originalText isEqualToString:@""]) {
//空文字なら処理しない
return nil;
}
NSLog(@"original:%@",originalText);
originalText = [originalText stringByReplacingOccurrencesOfString:@" "withString:@""];//全角除去
NSMutableArray *lines = [NSMutableArrayarray];
[originalText enumerateLinesUsingBlock:^(NSString *line, BOOL *stop) {
[lines addObject:line];
}];
NSMutableString *text = [[NSMutableStringalloc] init];
for (int i = 0; i < [lines count]; i++) {
if (![lines[i] isEqualToString:@""]) {
[text appendString:lines[i]];
}
}
NSLog(@"text:%@",text);
UILabel *label;
UIFont *font = [UIFont systemFontOfSize:13.0];
if (OS_VERSION_LESS_THAN(@"7.0")) {
//iOS6
NSLog(@"OS6:%s",__func__);
CGSize size = [(text ? text : @"") sizeWithFont:font
constrainedToSize:(CGSize){MSG_MAX_WIDTH, MSG_MAX_HEIGHT}
lineBreakMode:NSLineBreakByTruncatingTail];
label = [[UILabel alloc] initWithFrame:(CGRect){0, 0, size.width, size.height}];
label.backgroundColor = [UIColorclearColor];
label.textColor = [UIColor darkGrayColor];
label.lineBreakMode = NSLineBreakByTruncatingTail;
label.text = (text ? text : @"");
label.font = font;
label.numberOfLines = 2;
label.tag = COMMENT_LABEL;
[label sizeToFit];
return label;
} else {
//iOS7
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStylealloc] init];
paragraphStyle.lineBreakMode = NSLineBreakByTruncatingTail;
paragraphStyle.alignment = NSTextAlignmentLeft;
NSDictionary *attr = @{NSFontAttributeName : font,
NSParagraphStyleAttributeName : paragraphStyle};
NSAttributedString *str = [[NSAttributedString alloc] initWithString:(text ? text : @"")
attributes:attr];
CGRect rect = [str boundingRectWithSize:(CGSize){MSG_MAX_WIDTH, MSG_MAX_HEIGHT}
options:NSStringDrawingUsesLineFragmentOrigin
context:nil];
label = [[UILabel alloc] initWithFrame:rect];
label.backgroundColor = [UIColorredColor];
label.textColor = [UIColor darkGrayColor];
label.lineBreakMode = NSLineBreakByTruncatingTail;
label.attributedText = str;
label.numberOfLines = 2;
label.tag = COMMENT_LABEL;
[label sizeToFit];
return label;
}
}
Production(Distribution)の証明書が期限切れになったときの更新
DistributionのProvisioning ProgileがExpiredになってしまった...
なんで?といろいろ画面をさまよってみたところ、
どうやらCertificates > Productionの欄にDistribution用の証明書がない。
これか。
でも、リリース後・運用中のアプリいくつかあるし、
ついこないだようやく審査通過してくれたアプリも一本あるし、
今となっては期限切れの証明書を使って
Distributionのプッシュ通知証明書とかも作ってたし...
なにやら、おおごとな気がする...(;´・3・`)
やな感じね...(;´・3・`)
だが立ち向かうしかない。
いざ更新!
▼懸念点
それはズバリ、公開済・運用中のアプリへの影響。
Distribution用のCertificationを作り直すことで
アプリの紐付け解除(謎)が行われたりだとか
プッシュが全アプリで届かなくなるだとか...こわい...
で、ググってみると、同じようなことを調べてくれている人がいた!
http://maikoo811.tumblr.com/post/30725604344/ios-provisioning-portal-distribution
こちらを見る限り、
Standard iOS Developer Programでは上記の問題に関して特に問題がないとのこと。
さらに、「Distributeの証明書というのは、AppStoreにアップする際の証明書」やと。
ほほぉ。
※でもあとからよく見たら上記のサイト「期限内の場合」って書いてあったw
▼というわけで更新作業へ
更新作業の際に参考にさせて頂いたのが以下のリンク。
http://ameblo.jp/kazatmac/entry-11078956765.html
詳細はこちらのリンクで確認して頂きたいのですが、
ちょっと変更点もあったので、やったことをざざっと並べておきます。
(キャプチャなくて申し訳ないです!)
*更新手続きまとめ*
-- 1、Distribution証明書の再発行 --
①キーチェーンアクセスからCSRファイルを作成する→ディスクに保存
(「認証局に証明書を要求」みたいなあれね。
作り方はプッシュの証明書を発行するときと同じ。
わからない方は⑯のリンクを見て下さい)
②Apple Developerにログイン > Certificates, Identifiers & Profilesへ
③Certificates > Production で新規作成マーク(+)を押す
④「どの種類の証明書を作りたいんだい?」みたいな英語が出るので
Profuction > AppStore and Ad hoc を選択
⑤そのまま進むとCSRファイルのアップロードを要求されるので、
①で作ったCSRファイルをあげる
⑥作成できたらそのcerファイルをダウンロード、ダブルクリック!
⑦キーチェーンに⑥の証明書が登録されたのを確認
-- 2、Provisioning Profileの更新 --
⑧再びApple Developer > Provisioning Profile > Distribution へ
⑨ExpiredのステータスになっているProvisioningたちのEditを選択
⑩先ほど作成した新しいPeoduction用の証明書が
Certificates: の欄に出現していると思うのでそちらにチェックしてDone
⑪DLしてダブルクリックするとXcodeのOrgnizerに入りますので古いやつを破棄!
-- 3、APNS Production(プッシュ用証明書)の更新 --
⑫再びApple Developer > Identifiers > App IDs へいき、
プッシュが届かなくなってしまったアプリIDを選択して
利用中のApplication Serviceのステータス一覧を確認すると、
おそらくPush Notificationsの欄が黄色信号(Configurable)になっていて、
「未設定だぜ」みたいな英語が書かれているはずなので、
この証明書をGenerate作業する。
⑬④のときみたいに「どの証明書が欲しいのね」って聞かれるので
Production > Apple Push Notification service SSL (Production)を選択。
⑭またCSRファイルを要求されると思うので、①で作成したCSRファイルをアップロード。
作成完了したら、DLしてダブルクリック!
⑮キーチェーンに⑭の証明書が登録されるので、該当証明書の上で右クリック
→証明書を書き出す
⑯パスワードはどちらとも空欄でp.12形式で書き出して保存
(補足:プッシュ通知の証明書関連は下記がわかりやすくてオススメ
http://himaratsu.hatenablog.com/entry/objc/push_certification)
と、これで完了ー!!
無事、問題なく全て動きました。
▼その他
「Adhocのプロビジョニングファイルの期限が切れますよー」っていうお知らせは
何日か前から来ていた気がするけど、
実際この更新が可能なタイミングって何日前くらいからなのだろう...
というのが残った疑問。
とりあえずプッシュが打てなくなるのはきついってことで、
Productionのプッシュの証明書の有効期限は確認したので、
次回期限が近くなったらこまめに見に行ってみようっと!
お疲れ様でした(○'ω'○)!
Adhoc版でプッシュ通知が届かない問題を解決!!
まーたやってもうた。
毎回、テスト配布でAdhoc版のProvisioningを設定して
Releaseモードでアーカイブすると、
そのときに取得したAPNSのtokenと
ストアのリリース版からのAPNStokenがサーバー側で混在してしまって
プッシュが届かないという現象が。。。
これを今回限りでこの現象とはおさらばする!打破!\( ^ヮ゜)>ダハ!
▼まずはこちらを参考に
http://peter78.wordpress.com/2011/04/01/apple-push-notification-service-deployment-tips/
要点は以下。おさらいも兼ねて。
1:Adhoc版=開発環境(≠本番環境)
2:開発環境では本番環境のAPNSを取得することはできない。
3:本番環境(Release版)で取得するAPNSは本番用のもの、
なのでこの本番用APNS tokenが本番用サーバと紐づけられて使用されなきゃだめ。
おまけ:テストで開発版をビルドした端末でストアからリリース落とす場合、
一回アプリを削除してからインストールすること。
つまりは、やっぱり開発環境のAPNS tokenと本番環境のAPNS tokenは絶対混ぜたらあかんで。
ってことらしい。
Adhoc版ってどちらかというと本番環境と同じだ(というか開発環境ではない)と思ってた....
(だってDistributionに紐づけられてるもんね(´・ω・`))
▼仮説
Adhoc版 Provisioningを設定してRelease版でArchiveしたテストアプリを入れた端末は、
AppleのAPNSサーバーに対して本番用のProvisioningでtokenを要求する。
するとAPNSサーバーは
その端末に向けて本番用のtokenを登録してしまう。
そいつは本当は開発環境であるAdhoc版なのに。(悲劇)
そしていざ製品がリリースされて、プッシュ打ちます!
てなったときに、
本当の本番環境で作成されていない登録済みtokenを
端末の本番用tokenとして紐づけてしまうから、
本番サーバーから該当端末に届かなくなるって事なんかな?
でもリリース前テストは限りなく本番に近い環境で行いたいよね。
アーカイブしたもので配布したいよね。
▼解決策を考える
一番簡単そうなのは、
Edit SchemeでArchiveの設定を「Debug」に設定してしまう。
そうしたら登録要求をしてもそれは完全に開発環境版のtokenだから
問題ない気がしたんだよな。
でも、「本番環境になるべく近づけたい」という観点から、
このやり方は結局試すのやめた。
で、思った。
「Adhocモード」っていうのが存在して、
そのときにはAPNSに登録要求自体しない
っていう風にすればいいんじゃない?
例えばマクロ定義しちゃって、
#ifdef文とかでコード自体呼ばれなければいいんよね。
というわけで作戦を開始。
▼STEP1
ということで、以下の方法でまずはAdhocモードなるものを追加!
下のサイトを参考に。
http://qiita.com/uasi/items/79aecac40f1b2a5f929b
このときに、
「Duplicated "Debug" configuration/Duplicated "Release" configuration」
つまり、
「開発環境ベースに作るか本番環境ベースに作るか、どうする?」って聞かれるけど、
私は本番に近い環境にしたかったので本番環境ベースに作った。
「Release Copy」なるものが作られるので、名前を「Adhoc」にする。
で、作ったらPreprocessor Macroに「ADHOC=1(ADHOCですよー)」てマクロを定義する。
▼STEP2
ここまで出来たら、マクロで呼び出し制限をかける!
APNS tokenをAPNSに登録要求するコードはアプリ起動時とかに呼び出すと思うんやけど、
この文を#ifdef文で囲む。
今回は、「Adhoc版じゃなかったら呼んで欲しい」ので、
以下のように。
#ifndef ADHOC
[[UIApplicationsharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge
| UIRemoteNotificationTypeSound
| UIRemoteNotificationTypeAlert)];
#endif
▼STEP3
そして、Edit SchemeからArchive時の設定を「Adhoc」にする。
これでアーカイブするときにAdhoc版でコンパイルされる。
するとAdhoc版では上のコードがスルーされて呼ばれないので
APNSに向けて登録要求がされない=本番環境での混在は起こらない!はず!
ちなみにProvisioningの設定は、
Debug→Development
Adhoc→Adhoc(Distribution)
Release→Distribution
とします。
▼確認
とりあえず本当にマクロがスルーされるのか確認のために
ViewDidLoadでアラート表示のテストをしてみた。
本来ならばReleaseと比較してみたいところやけど無理なので、
Debug(Runでの設定)とAdhoc(Archive)で
BundleIDをかえてそれぞれ挙動をチェック。
これでビルドしてみると...
こちらがDebugビルド こちらがAdhocビルド
できてるう\(^o^)/
というわけでおそらく、これでDebug時とRelease時のみ
APNSの登録要求が呼ばれるはず!
▼注意
今までだとArchive時のデフォルト設定は「Release」になっているけど
テスト配布時には「Adhoc」に変更しているので、
ストアにSubmitするときは必ずこの設定を「Release」に戻してArchiveすること!
PROJECTのDeployment Target設定はTARGETSだけで大丈夫なのか?
Xcodeで対象OSを設定したいときに、
Depoyment Targetを変更するところが2箇所ありますね。
(PROJECT と TARGETS)
TARGETS > SUMMARYのほうはアプリのバージョンとかBundle Iddentifierとか
もろもろ設定できますよね。
なので私はこっちのDeploymentment Targetは5.0にしてたのですが、
PROJECT > Info > Deploymentment Target のほうは6.1のまま
ストアにあげてしまいました。(´・ω・`)
(つまり一致させずにあげてしまった)
デバッグ中(Debug版)は、このSUMMARYの方の対象OSを例えば6.0とかに設定して
それを5.1の端末でビルドしようとすると、エラーが出て怒られたりしていたのだけど、
テストも終盤になってくると、Release版でアーカイブしたものを実機でテストしてました。
(そのときはもちろんSUMMARYの対象OS設定を5.0以上にして)
そのときは問題なく動いていた。
で、今日上記のPROJECT > InfoのほうのDeploymentment Targetが
6.1のまま5.0に設定されていないことが発覚して、
「どうしよう....adhoc版ではOS5.1の端末でも問題なく動いたけど、
これストアにあがったら6.1からしか動かんとかなったら...!!」
てめっちゃ不安になった。(´・ω・`)
色んな情報ぐぐったけど、「こっちだけで大丈夫ー!」って言ってる情報ないし。
■調査してみた
①AppleさんのReferenceによると、
「絶対PROJECTの方も設定しろよナ!!(Д゚))」とかは書いていないし、
SUMMARYの設定だけで大丈夫くさい。
でもちょっと情報が古い。(´・ω・`)
②そしてこの英語のQ&Aによると
どうやらTARGETSのほうで設定した項目があればそちらが上書きされるので問題なさげ。
でも他のブログとかではみんなPROJECTのほうから設定してるし、信頼性がなんとも。(´・ω・`)
■そこで....
ためしにTARGETS(SUMMARY)のほうのDeveloment Targetを削除してみる。
すると、デフォルト値である最新OSがグレーの文字で設定された。
で、この状態でPROJECTSのほうを5.1とかにすると、
コンパイラで5.1でビルドしているのが確認できた。
■つまり...
Q&Aの情報は正しい説に一票?
「TARGETのSUMMARYで設定している値があれば、
それがアプリのDevelopmentTargetとして設定される」
ということであってくれ・・・・!!
■補足
iTunes Connectからアプリの詳細画面にいって 「Binary Details」ってところにいくと「Minimum OS Requirements」に 対象OS(最低)が書いてあったよ!
という先輩のアドバイスをもとにすぐさま確認しにいくと
ステータスはWaiting For Reviewではあるけど
アプリのMinimum OS Requirementsは確かに5.0になっていました。
これってAppleが受け取ったバイナリデータを元に情報作成してくれてるとしたら
ストア版も5.0からで確実。なはず。
ガクブル!(ω・`))キョロ(( ´・ω)
またストアでどうなったか報告します。
iPhone5/iOS6になってのTips
■viewDidunLoadは呼ばれない
これけっこう気をつけること。
NotificationとかObserverとか、
removeしてあげないといつまでも通知してくれる健気な彼ら。
プログラムに旋風を巻き起こすことになります。
結果、
「なんでこのメソッド2回も呼ばれるんだ..!」とか、
「呼ばれる回数がどんどん増えている..!怪現象か..!」とか、
そんなことになるので、
viewWillDisappearでremoveしてあげること。
ということはセットするのはviewWillAppearとかが良いですね。
■iPhone5でのimageNamedでの画像指定
用意する画像は3つ。
・abc.png
・abc@2x.png
・abc-568h@2x.png
iPhone4SのRetina Displayでは
UIImage* image = [UIImage imageNamed:@"abc.png"];
と書けば呼び出してくれる。
でiPhone5ではっていうと、
UIImage* image = [UIImage imageNamed:@"abc-568h.png"];
とすれば良いです。
この場合に、abc-568h.pngとかっていう画像は不要です。
3種類あればok。
(ただし568-h@2xサイズを用意してね)
それはなぜかっていうと、画像ファイルのほうに@2xとついていると、
自動的に「Retinaサイズだ!」と認識してくれるから。
かつ、568hの画像(=iPhone5)は必ずRetina Displayなので、
1/2サイズは用意しなくていい。
if (IPHONE5) {
image = [UIImage imageNamed:@"abc-568h.png"];
} else {
image = [UIImage imageNamed:@"abc.png"];
}
みたいな感じ!
ちなみにIPHONE5てのはマクロ定義してます。こんな感じ。
#define IPHONE5 ([UIScreen mainScreen].bounds.size.height == 568)
むしろもう3Gとか対応するのいいんでは..orz って思ってしまうけど
まだ若干ユーザーいるみたいね。
iOSbeta版からのアクティベーション(復活)
iPhoneアプリを開発していると、Appleから「最新OSのbeta版が出たよ!」
ってお知らせが来て、Apple DevelopperからiOSのbeta版をインストールして
開発することがあるかと思います。
beta版のインストールについては各所でやり方がのっていると思うのですが、
Appleが正式にOSを公開したときに、
このbeta版端末が死亡することがあります。アーメン。
画面には「アクティベーションが必要です」の文字。。
この状態になると、にっちもさっちもいかなくなります。
(キャリアすらつながらなくなったような。)
再起動してもこの文字が出るだけ...
さて困った。
調べたところ、beta版には期限があるということでした。
つまり、beta版で開発していた端末をしばらく放置していて、
電池とか切れちゃって、久々に立ち上げたら
Oh NO...What's activate..?(;゚Д゚)みたいな感じですね。
色々ネット上での情報を調べていると、
緊急電話を押して、番号を早押しすると入れます!
とか裏ワザチックなことも書いてあって、
もちろん全力で試したけど、10回目くらいで
これ無理だわ..絶対冷静なやり方あるわ..と悟った。
■解決法■
こうなったらストアにももちろん接続ができなくなってしまうので、
beta版をインストールしたやり方と同じように
端末に正式版をインストールしてあげます。
つまり、
==== ====================================================
①Apple Developperにいき、正式版(Restore版)のOSをダウンロードしてくる。
※なんかファイルのアイコンが実体がないみたいなもやっとした感じになってますが
無事ダウンロード内に保存されるかと思います。
②iTunesを開いて端末画面へ行き、Optionキーを押しながら[アップデート]を選択し、
先ほどDLしたRestore版を端末へ入れる。
========================================================
これで復活すると思います。
ハマったのでメモ!
指定したUIColorとCGRectで、塗りつぶしのUIImageを生成する
四角いカスタムボタンを透明で色指定して作ったときに
押したときにわかるようにしたい!と思い、
でもたしかカスタムボタンって
選択状態のときUIImage設定せんといけんかったっけ...
と思ったのですが、
デザイナーさんにわざわざぺた塗りの画像を切り出してもらうのも悪いし
UIColorからUIImageって生成できんのけ?絶対できるやろー
と思い調べてみたところ、
なんだか色々な人が色々なやり方でやっていて
しかもなんだかどれも「これ!」ってのが無かったのですが
見つけました。※こっちは使わないほうがいいよ。下まで読むべし
//指定したUIColorでCGRectの大きさを塗り潰したUIImageを返す
UIImage *(^createImageFromUIColor)(UIColor *) = ^(UIColor *color)
{
CGRect rect = CGRectMake(0, 0, 1, 1);
UIGraphicsBeginImageContext(rect.size);
CGContextRef contextRef = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(contextRef, [color CGColor]);
CGContextFillRect(contextRef, rect);
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
};
[使用例]
//塗りつぶし
UIImage* fill = createImageFromUIColor([UIColor colorWithRed:0 green:0 blue:0 alpha:0.2]);
[linkBtn setBackgroundImage:fill forState:UIControlStateHighlighted];
なんだこのメソッドの書き方、初めてみた!わかんね!
とか思いつつ、呼び方(生成)自体は簡単だし理想の挙動だし
しばらく使ってたのですが、
別ファイルでも同じことをしようとまったく同じように仕込んでみたところ、
Mach-O-Linker-Error とかいうエラーが出てビルドできなくなった...
うわー、これ嫌な感じのエラーなやつやん(;´ x`)と思いながら
解決策をググっていると
どうやらなんかさっき追加したこのコードが重複していることが原因くさい...
消してみたらうまくいった。
でもね、どっちのファイルでも使いたいんだよおお!ってことで
仕方なく別の方法を探す。
きっと似たようなことをやっているメソッドは落ちているはずだ!
要はreturnでUIImageが返ってきてる感じで、
できれば一言で呼べちゃうメソッドがいいなーと思っていたら、
落ちてた!!
★ということでこっち使ったほうがいい。↓(すいませんまわりくどくて)
やってることはまったく同じ!呼び方も簡単!
これで指定した色・サイズでUIImageが生成できます。
//指定したUIColorでCGRectの大きさを塗り潰したUIImageを返す
- (UIImage *)imageWithColor:(UIColor *)color {
CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextFillRect(context, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
[使用例]
UIImage* temp = [self imageWithColor:[UIColorcolorWithRed:0green:0blue:0alpha:0.2]];
[linkBtn setBackgroundImage:temp forState:UIControlStateHighlighted];