2012年8月30日木曜日

cookie

アカウント登録時にOAuthで認証し、またすぐ別のアカウントを追加しようとすると前のアカウントでログインされた状態で許可を求める画面になることがある。そのページからOAuthの説明ページに行けばログアウトできるがそんなん多分だれも気付かないしカッコ悪い。アラートだすのもやっぱり間抜けな気がするし、ログアウトページに行ってから再度request tokenのページに飛ぶようにしたがこれもあまり美しくない。
ということで、cookie消せばいいんじゃね?と思って調べた。

このあたり。
Where are an UIWebView's cookies stored?
How to delete all cookies of UIWebView?

あとで調べる。

2012年8月29日水曜日

Preferencesとマルチアカウント

Preferences画面を作成。
UINavigationControllerとUITableViewControllerでちゃかちゃか作っていく。
このへんは参考書籍もサイトも充実してる(しすぎてて逆に探しにくいくらい)ので、デリゲートメソッドを使うやり方に戸惑いながらもハマってしまうことは少ないかな。先人たちに感謝。
このテーブルの仕様は慣れてくると非常によく考えられた汎用性の高い仕組みだと思う。


で、tumblrのマルチアカウント対応を検討中。

■アカウント登録されてない場合:
・起動時に最初にアラート、登録したいのとは別のアカウントでログインしてたらログアウトを促す。
・userdefaultの中の該当する配列(以下activeAccArr)見て空ならgetAToken貼る。
・帰ってきたらラップしたYESを配列に入れてUDに書く。(getATokenの中でやる)
・setATokenしてアカウントのusernameを取ってshortnameに入れる。
・reqDBする。

■アカウントを追加する場合:
・activeAccArrのcount分usernameとってAccounts配列に入れる。
・Accounts配列を展開して(DL完了前のNULLに注意)activeAccArrのYESの場所のAccounts配列の要素をcheckMarkする。
・追加ボタンで最初にアラート、登録したいのとは別の別アカウントでログインしてたらログアウトを促す。
・getAToken貼って、帰ってきたらactiveAccArrを全部NOにしてラップしたYESを最後に追加してUDに書く。
・setATokenしてアカウントのusernameを取ってshortnameに入れる。(変更Flag立てる?)
・変更Flag立ってたらPrefでdoneでreqDBする。

■アカウントを削除する場合:
・activeAccArrのcount分usernameとってAccounts配列に入れる。
・Accounts配列を展開して(DL完了前のNULLに注意)activeAccArrのYESの場所のAccounts配列の要素をcheckMarkする。
・削除されたrowのactiveAccArrを削除し、それがYESだった場合は最初の要素をYESにしてUDに書く。
・setATokenしてアカウントのusernameを取ってshortnameに入れる。(変更Flag立てる?)
・変更Flag立ってたらPrefでdoneでreqDBする。

■デフォルトアカウントを変更する場合:
・activeAccArrのcount分usernameとってAccounts配列に入れる。
・Accounts配列を展開して(DL完了前のNULLに注意)activeAccArrのYESの場所のAccounts配列の要素をcheckMarkする。
・選択されたら元のYESをNOにして選択されたrowのactiveAccArrをYESにしてUDに書く。
・setATokenしてアカウントのusernameを取ってshortnameに入れる。(変更Flag立てる?)
・変更Flag立ってたらPrefでdoneでreqDBする。


こんな感じか。usernameを度々読みに行くのがなんか気持ち悪いが最新のものを読むためには仕方ない。あとはこの自分にしかわからない日本語を自分にしかわからないObj-c語に翻訳するだけだ。
楽しい。

2012年8月24日金曜日

audioと虫取り

audioはMPMoviePlayerControllerとかも調べたけどどうもしっくりこないので結局AudioStreamerを入れた。バッチリ動いてる。すばらしい。mattgallagher氏に感謝。これで全type思ってた感じのインターフェイスができたかな。よくぞここまで来たものだ。

あとはUIWebViewで読込完了前に閉じてもっかい開いたらdeallocatedですよーと怒られたり、ポスト移動してたら何故か前のビューの残像が残ってたりといった虫取りに結構ハマってた。

気づき:
・UIWebViewではremoveする前にstopLoadingを入れないと次にUIWebViewをaddSubした瞬間に落ちる。
・ポスト移動のボタンを連打するとanimationのcompletionが呼ばれるときにremoveする対象のviewがずれる。

両方共気づくのに数時間を要した。次は設定画面かな。UINavigationViewControllerとUITableViewControllerの組み合わせでちゃかちゃか作っていくのかな。

2012年8月18日土曜日

スワイプ移動、photo再読込、linkとaudioリベンジ

ここ何日かでいろいろ捗った。

・スワイプ移動
でポストを移動できるようになったら、やっぱりシュルっとビジュアル的にスライドしないとなんか気持ち悪いのでやってみた。なかなか良い感じ。
- (void)npost{
 sw=self.view.bounds.size.width,sh=self.view.bounds.size.height;
 if([[pvlayer.view viewWithTag:now]isEqual:[pvArr lastObject]]) return;
 CGRect oldf=[pvlayer.view viewWithTag:now++].frame;oldf.origin.x-=sw;[self refself];
 [pvlayer.view addSubview:[pvArr objectAtIndex:now-1]];[self na];[self mkCaption];[self refpost];
 CGRect nowf=[pvlayer.view viewWithTag:now].frame;nowf.origin.x+=sw;[pvlayer.view viewWithTag:now].frame=nowf;nowf.origin.x-=sw;
 [UIView animateWithDuration:0.2 delay:0 options:UIViewAnimationOptionCurveEaseOut
      animations:^{[pvlayer.view viewWithTag:now-1].frame=oldf;[pvlayer.view viewWithTag:now].frame=nowf;}
      completion:^(BOOL finished){[[pvlayer.view viewWithTag:now-1]removeFromSuperview];}];
 if(now>100) [pvArr replaceObjectAtIndex:now-101 withObject:[NSNull null]];
 if(now+20>[contArr count]){
  if(imout||loadflg)return;
  if(target==@"dshbrd"&&offset+limit>250) offsetflg=NO;
  if(offsetflg){
   offsinceval=[NSString stringWithFormat:@"%d",offset+=limit];
  }else{
   since_id=lastid-(([[idArr objectAtIndex:0]longLongValue]-[[idArr lastObject]longLongValue])/([idArr count]-1)*(limit+1));
   offsinceval=[NSString stringWithFormat:@"%lld",since_id];
  }
  if(!loadflg)[self reqDB];
 }
}
- (void)ppost{
 sw=self.view.bounds.size.width,sh=self.view.bounds.size.height;
 if(now==1)return;
 if([[pvArr objectAtIndex:now-2]isEqual:[NSNull null]]){
  UIAlertView *lost=[[UIAlertView alloc]initWithTitle:@"DEAD END"
             message:@"sorry, but only 100 previous posts are retained for preventing a crash caused by insufficient memory."
               delegate:nil cancelButtonTitle:nil otherButtonTitles:@"oh well.",nil];
  [lost show];[self mkCtrlr:1];return;
 }
 CGRect oldf=[pvlayer.view viewWithTag:now--].frame;oldf.origin.x+=sw;[self refself];
 [pvlayer.view addSubview:[pvArr objectAtIndex:now-1]];[self na];[self mkCaption];[self refpost];
 CGRect nowf=[pvlayer.view viewWithTag:now].frame;nowf.origin.x-=sw;[pvlayer.view viewWithTag:now].frame=nowf;nowf.origin.x+=sw;
 [UIView animateWithDuration:0.2 delay:0 options:UIViewAnimationOptionCurveEaseOut
      animations:^{[pvlayer.view viewWithTag:now+1].frame=oldf;[pvlayer.view viewWithTag:now].frame=nowf;}
      completion:^(BOOL finished){[[pvlayer.view viewWithTag:now+1]removeFromSuperview];}];
 if(now==1)[bprev removeFromSuperview]; 
 [[pvlayer.view viewWithTag:now--] removeFromSuperview];[self refself];
 [pvlayer.view addSubview:[pvArr objectAtIndex:now-1]];
 [self na];[self mkCaption];[self refpost];
 if(now==1)[bprev removeFromSuperview];
}

・photo再読込
SpeedLimitを使ってtimeoutさせてシングルタップで読込ミスったphotoを再読込したりalt_sizeなphotoの場合はoriginalを読むようにしたりした。これはコード書くまでもないかな。

・linkの当たり判定
よりリンクらしく、ボタンじゃなくてCoreText自体をクリックしたらページを開くようにしたくなって当たり判定を調べて入れた。tap時の座標をとってもいいけどとりあえずマーカー的にuiimageviewを貼ってそいつにgesture取らすようにした。
- (id)initWithFrame:(CGRect)frame string:(NSString *)string url:(NSString *)url_
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
  url=url_;
  NSMutableDictionary *attrDic=[NSMutableDictionary dictionaryWithCapacity:0];
  CTFontRef ctFont=CTFontCreateWithName((__bridge CFStringRef)@"Helvetica",24, NULL);
  [attrDic setObject:(__bridge id)ctFont forKey:(NSString *) kCTFontAttributeName];
  [attrDic setObject:(__bridge id)[UIColor blueColor].CGColor forKey:(NSString *)kCTForegroundColorAttributeName];
  [attrDic setObject:@((int)kCTUnderlineStyleSingle) forKey:(NSString *)kCTUnderlineStyleAttributeName];
  NSMutableAttributedString *linkedText=[[NSMutableAttributedString alloc]initWithString:string attributes:attrDic];
  CGMutablePathRef path=CGPathCreateMutable();
  CTFramesetterRef framesetter=CTFramesetterCreateWithAttributedString((__bridge CFMutableAttributedStringRef)linkedText);;
  CGPathAddRect(path,NULL,self.bounds);
  ctFrame=CTFramesetterCreateFrame(framesetter,CFRangeMake(0,[linkedText length]),path,NULL);
  CFArrayRef lines=CTFrameGetLines(ctFrame);
  for(int i=0;i<CFArrayGetCount(lines);i++){
   CGPoint orig;CGFloat ascent,descent,leading,width;
   CTFrameGetLineOrigins(ctFrame,CFRangeMake(i,1),&orig);
   width=CTLineGetTypographicBounds(CFArrayGetValueAtIndex(lines,i),&ascent,&descent,&leading);
   UIImageView *blank=[[UIImageView alloc]initWithImage:[UIImage imageNamed:@"img_black"]];
   [blank setFrame:CGRectMake(0,self.bounds.size.height-orig.y-ascent+descent,width,ascent+descent)];blank.alpha=0;
   self.userInteractionEnabled=YES;blank.userInteractionEnabled=YES;
   UITapGestureRecognizer *st=[[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(openPage:)];
   st.numberOfTapsRequired=1;
   [blank addGestureRecognizer:st];
   [self addSubview:blank];
  }
  CGPathRelease(path);
  self.backgroundColor=[UIColor clearColor];
    }
    return self;
}
-(void)openPage:(UITapGestureRecognizer *)gesture{
 openPage=[[OpenPage alloc]initWithURL:url];
 [self.superview.superview.superview addSubview:openPage.view];
}

・audio_url
ここまで来たらaudioもリンクじゃなくて直接再生したくなって一度挫折してるけどもっかい調べてみたらなんか行けそうな記事があったので再挑戦中。ただmp3のURLからストリーミングさせるのが結構大変そう。ちょっとがんばる。

2012年8月14日火曜日

SpeedLimit

それから、今まで贅沢にもoriginal sizeのphotoを読み込んで使っていたが、3G環境をシミュレートしてどれくらいのストレスになるか調べてみた。いろいろ探してSpeedLimitなるものを入れて3Gを模してみたが、はっきり言ってoriginal sizeでは話にならない。60secでは読み込みが終わらん。こりゃまずいということで、tumblrのAPIから返ってくるalt_sizesを使ってみた。1,2段階低い解像度なら行けそうなので、5段階くらいを任意に選択できるようにして、original size以外ならダブルタップでoriginalを読むようにしてみた。
あと、スワイプでのpost移動もUISwipeGestureRecognizer使ったら簡単にいけた。着実に完成に近づいてるが、夏休み終わるまでの完了は無理かなー。

delegate

reblogメッセージはUIImageViewのサブクラスを作ってそいつが自らreblogのrequestを投げてresponseが返ってきたら自分の表示位置を示すシリアル番号(配列の添字)をdelegateに投げて表示位置をリセットして自分をフェードアウトしてremovefromsuperviewする形に変更。まだスマートかな。

rootのvc
- (void)rblg{
 int i;
 for(i=0;i<[rposArr count];i++){
  if([[rposArr objectAtIndex:i]isEqual:[NSNull null]]){
   [rposArr replaceObjectAtIndex:i withObject:@"used"];break;
  }
 }
 rblk=[[ReblogLike alloc]initWithFrame:CGRectMake(0,(sh-16)/2+i*16,sw,16) rorl:@"reblog" rid:[idArr objectAtIndex:now-1] rkey:[rblgkArr objectAtIndex:now-1] rpos:i
            num:now type:[typeArr objectAtIndex:now-1] cons:_consumer token:_accessToken
            url:[NSURL URLWithString:[NSString stringWithFormat:@"http://api.tumblr.com/v2/blog/%@.tumblr.com/post/reblog",shtname]]];
 rblk.delegate=self;
 [self.view addSubview:rblk];
}
-(void)rposReset:(int)rpos{
 [rposArr replaceObjectAtIndex:rpos withObject:[NSNull null]];
}
ReblogLike.h
@protocol ReblogLikeDelegate 
-(void)rposReset:(int)rpos;
@end

@interface ReblogLike : UIImageView{
 int rpos;
 iddelegate;
}

@property(strong,nonatomic)iddelegate;

- (id)initWithFrame:(CGRect)frame rorl:(NSString *)rorl rid:(NSNumber *)rid rkey:(NSString *)rkey rpos:(int)rpos_ num:(int)num type:(NSString *)type
      cons:(OAConsumer *)cons token:(OAToken *)token url:(NSURL *)url;

@end
ReblogLike.m
- (id)initWithFrame:(CGRect)frame rorl:(NSString *)rorl rid:(NSNumber *)rid rkey:(NSString *)rkey rpos:(int)rpos_
    num:(int)num type:(NSString *)type cons:(OAConsumer *)cons token:(OAToken *)token url:(NSURL *)url
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
  sw=self.bounds.size.width,sh=self.bounds.size.height;
  rpos=rpos_;
  self.image=[UIImage imageNamed:@"img_black"];self.autoresizingMask=15;
  UIView *rBase=[[UIView alloc]initWithFrame:CGRectMake(0,0,sw,16)];rBase.autoresizingMask=13;
  title=[[UILabel alloc]init];
  title.text=[NSString stringWithFormat:[rorl isEqual:@"reblog"]?@"REBLOG-ing...":@"LIK-ing..."];
  title.font=sf(13);title.textColor=[UIColor whiteColor];title.backgroundColor=[UIColor clearColor];
  CGFloat titlewidth=[title.text sizeWithFont:title.font constrainedToSize:CGSizeMake(sw,15) lineBreakMode:UILineBreakModeTailTruncation].width;
  UILabel *info=[[UILabel alloc]init];
  info.text=[NSString stringWithFormat:@"(number %d - %@)",num,type];
  info.font=sf(10);info.textColor=[UIColor whiteColor];info.backgroundColor=[UIColor clearColor];
  CGFloat infowidth=[info.text sizeWithFont:info.font constrainedToSize:CGSizeMake(sw,12) lineBreakMode:UILineBreakModeTailTruncation].width;
  title.frame=CGRectMake(ceilf((sw-(titlewidth+infowidth))/2),0,titlewidth,15);
  info.frame=CGRectMake(ceilf(title.frame.origin.x+titlewidth+10),2,infowidth,12);
  [rBase addSubview:title];[rBase addSubview:info];
  [self addSubview:rBase];//return self;

  OAMutableURLRequest *request=[[OAMutableURLRequest alloc] initWithURL:url consumer:cons token:token realm:nil signatureProvider:nil];
  [request setHTTPMethod:@"POST"];
  NSMutableArray *prmt=[NSMutableArray arrayWithObject:[[OARequestParameter alloc]initWithName:@"id" value:[NSString stringWithFormat:@"%@",rid]]];
  [prmt addObject:[[OARequestParameter alloc]initWithName:@"reblog_key" value:rkey]];
  //[prmt addObject:[[OARequestParameter alloc]initWithName:@"comment" value:@"comment"]];
  [request setParameters:prmt];
  OADataFetcher *fetcher=[[OADataFetcher alloc] init];
  [fetcher fetchDataWithRequest:request delegate:self
     didFinishSelector:@selector(rblgTicket:didFinishWithData:)
       didFailSelector:@selector(rblgTicket:didFailWithError:)];

    }
    return self;
}
- (void)rblgTicket:(OAServiceTicket *)ticket didFinishWithData:(NSData *)data{
 NSDictionary *bd=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
 if([[bd valueForKeyPath:@"meta.status"]intValue]==201){
  title.text=@"REBLOG-ed.";
  [UIView animateWithDuration:3 delay:0 options:UIViewAnimationOptionCurveEaseIn
       animations:^{self.alpha=0;}
       completion:^(BOOL finished){
        [self.delegate rposReset:rpos];
        [self removeFromSuperview];
       }];
  //NSLog(@"rebloged.");
 }
 else NSLog(@"rblg failed.");
}
- (void)rblgTicket:(OAServiceTicket *)ticket didFailWithError:(NSError *)error{
 NSLog(@"rblg Error! %@",error);
}

できた。
delegateも難しく考えてたけど、単にずーっとやりたかったallocate元のインスタンスにメッセージを投げる方法だと考えればどーってことない。というか非常に使える。むしろ必須。わざわざnotification使ってたaccessTokenの取得ルーチンもdelegateに書き換えた。

2012年8月12日日曜日

ずっこけ

reblog中及び完了のメッセージングを、どのポストを対象にしてるかわかって尚且つ並列で処理中であることがわかるように頑張ってたが、reblog完了時のレスポンスに含まれるidが、reblog元のポストのidではなく作成後の新ポストのidであることが最後の最後に分かって脱力。tumblrAPIの仕様はなんかちょっと抜けてる気がする。わざと?
他の手立てを考えてみたが素人に豊富なオプションが有るわけもなく、散々悩んだ挙句メッセージングをなんかのサブクラスにしてdelegateとしてレスポンスを受けるようにしてみることを思いついたからとりあえず寝る。うまくいくかは分からん。やっぱりプログラミングはおもしろい。

2012年8月10日金曜日

reblog!

setHTTPMethodの位置が悪くてnot authorizedとか出て冷や汗かいたりidのフォーマッティングがうまく行かずにinvalidとか言われたりしたけど、とりあえずリブログ完成。

-(void)reqUInfo{
 NSURL *url=[NSURL URLWithString:@"http://api.tumblr.com/v2/user/info"];
 OAMutableURLRequest *request=[[OAMutableURLRequest alloc] initWithURL:url consumer:_consumer token:_accessToken realm:nil signatureProvider:nil];
 [request setHTTPMethod:@"POST"];
 OADataFetcher *fetcher=[[OADataFetcher alloc] init];
 [fetcher fetchDataWithRequest:request delegate:self
    didFinishSelector:@selector(reqUInfoTicket:didFinishWithData:)
      didFailSelector:@selector(reqUInfoTicket:didFailWithError:)];
}
- (void)reqUInfoTicket:(OAServiceTicket *)ticket didFinishWithData:(NSData *)data{
 NSDictionary *bd=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
 shtname=[bd valueForKeyPath:@"response.user.name"];
}
- (void)reqUInfoTicket:(OAServiceTicket *)ticket didFailWithError:(NSError *)error{
 NSLog(@"reqUInfo Error! %@",error);
}

- (void)rblg{
 NSURL *url=[NSURL URLWithString:[NSString stringWithFormat:@"http://api.tumblr.com/v2/blog/%@.tumblr.com/post/reblog",shtname]];
 OAMutableURLRequest *request=[[OAMutableURLRequest alloc] initWithURL:url consumer:_consumer token:_accessToken realm:nil signatureProvider:nil];
 [request setHTTPMethod:@"POST"];
 NSString *idstr=[NSString stringWithFormat:@"%lld",[[idArr objectAtIndex:now-1]longLongValue]];
 NSMutableArray *prmt=[NSMutableArray arrayWithObject:[[OARequestParameter alloc]initWithName:@"id" value:idstr]];
 [prmt addObject:[[OARequestParameter alloc]initWithName:@"reblog_key" value:[NSString stringWithFormat:@"%@",[rblgkArr objectAtIndex:now-1]]]];
 //[prmt addObject:[[OARequestParameter alloc]initWithName:@"comment" value:@"comment"]];
 [request setParameters:prmt];
 OADataFetcher *fetcher=[[OADataFetcher alloc] init];
 [fetcher fetchDataWithRequest:request delegate:self
    didFinishSelector:@selector(rblgTicket:didFinishWithData:)
      didFailSelector:@selector(rblgTicket:didFailWithError:)];
}
- (void)rblgTicket:(OAServiceTicket *)ticket didFinishWithData:(NSData *)data{
 NSDictionary *bd=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
 if([[bd valueForKeyPath:@"meta.status"]intValue]==201){
  NSLog(@"rebloged.");
 }
 else NSLog(@"failed.");
}
- (void)rblgTicket:(OAServiceTicket *)ticket didFailWithError:(NSError *)error{
 NSLog(@"rblg Error! %@",error);
}

できた。あとはメッセージング処理をやるか。

2012年8月9日木曜日

回転終了

やっと終了。かなり長い戦いだった。

・type=audio:autoresizingMask=45の置き場所によって動作が変わって手こずった。
・type=video:UIWebViewから映像を再生してその間に回転してMoviePlayerをdoneするとstatusBar分下にずれる。まさにこれと同じ状況:After playing HTML5 video, status bar white space remains
結局回転時にrootのvcを[UIScreen mainScreen].boundsでsetFrameし直したらいけた。ここにたどり着くのに死ぬほど苦労した。MoviePlayerから抜けた瞬間をnotificationさせて-20pxさせるもcaptionは除外したいとか考えてたらうわーってなったけど解決策はいつも単純。
・type=answer:まあこれはそんなに苦労はなかった。UIScrollViewにbaseとなるUIViewを貼ってたら画面の下半分でしかスクロールのタッチを検出しなくて悩んでたけど直接UIScrollViewにパーツ貼ったら解決した。

これでsinglepostviewの見栄えは完成。なかなか満足。timeline行く前に、いよいよ、reblogいくかー。OAuthの使い方だいぶ抜けてるから復習から。

昨日は來來亭@北巽でチャーハン定食麺堅め醤油濃い目ネギ背脂多め、今日はマッチョ@千日前でいつもの。ここは野菜マシマシがほかより少ない。でもうまかった。

2012年8月2日木曜日

回転は続く

次はchat。UILabelを使ってたけどUITextViewに変更。ていうかなんでUILabel使ったんやろ。縦幅制限したい場合は→UILabel、それ以外はUITextViewでいいんじゃないの。ただautoresizingMaskでtextのframeは変わるけどdialogueごとに入れてる線のyは可変にはできないから再描画or2viewの切替が必要。結局link同様切替にした。answerも同じ理由で切替が必要かな。とりあえずchatのみ修正。回転検知後のメソッドもちょっと変えた。

SinglePost2.m
}else if([type isEqualToString:@"chat"]){
  if(![cont isEqual:[NSNull null]]){
   for(int pl=0;pl<2;pl++){
    CGFloat npy=0;int j=1;
    UIScrollView *chatScr=[[UIScrollView alloc]initWithFrame:CGRectMake(0,30,pl?sh:sw,(pl?sw:sh)-50)];[self.view addSubview:chatScr];
    UIView *chatBase=[[UIView alloc]initWithFrame:CGRectMake(0,0,pl?sh:sw,pl?sw:sh)];
    for(id dialogue in cont){
     UITextView *npv=[[UITextView alloc]initWithFrame:CGRectMake(20,npy,(pl?sh:sw)-40,0)];
     npv.text=[NSString stringWithFormat:@"%@%@",[dialogue objectForKey:@"label"],[dialogue objectForKey:@"phrase"]];npv.font=sf(15);
     npv.textColor=[UIColor blackColor];npv.backgroundColor=[UIColor clearColor];npv.editable=NO;[chatBase addSubview:npv];
     CGRect f=npv.frame;f.size.height=npv.contentSize.height;npv.frame=f;
     npy+=npv.contentSize.height+10;j++;
     UIImage *line=[UIImage imageNamed:@"gray"];
     UIImageView *linev=[[UIImageView alloc]initWithImage:line];linev.alpha=0.7;[linev setFrame:CGRectMake(25,npy-8,(pl?sh:sw)-50,4)];
     UIImage *fuki=[UIImage imageNamed:j%2?@"fuki":@"fuki2"];
     UIImageView *fukiv=[[UIImageView alloc]initWithImage:fuki];fukiv.alpha=0.7;
     [fukiv setFrame:CGRectMake(j%2?5:(pl?sh:sw)-fuki.size.width-5,npy-8-fuki.size.height,fuki.size.width,fuki.size.height)];
     [chatBase addSubview:linev];[chatBase addSubview:fukiv];[chatBase setTag:(pl?4000000:3000000)+now];
     [chatScr addSubview:chatBase];
     if(UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)){if(!pl)chatBase.hidden=YES;}
     else if(pl)chatBase.hidden=YES;
    }
    [chatScr setContentSize:CGSizeMake((pl?sh:sw)-40,npy)];
   }
  }
 }
rootのvc
-(void)refpost{
 int plid;
 if([[typeArr objectAtIndex:now-1]isEqual:@"link"]) plid=1000000;
 else if([[typeArr objectAtIndex:now-1]isEqual:@"chat"]) plid=3000000;
 if(UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)){
  [self.view viewWithTag:plid+now].hidden=YES;
  [self.view viewWithTag:plid+1000000+now].hidden=NO;
 }else{
  [self.view viewWithTag:plid+now].hidden=NO;
  [self.view viewWithTag:plid+1000000+now].hidden=YES;
 }
}
できた。ていうかここまで書いて気付いたけどUITextViewに線と吹き出し貼ったらautoresizingMask効くかな?あとで確認する。残すはaudio,video,answer。いけるやろ。
最近ラーメンは昼じゃなく夜食べるようにしたけど結局 並野菜マシマシ背脂ちょいマシカラメ@マッチョになる。今日も行ってきた。取り憑かれてんのかな。

2012年8月1日水曜日

基礎

coretextをdrawしたUILabelを回転に対応させた。

・縦横それぞれのUIViewを作ってUILabelにaddSubView。
・各viewにtagを貼る。縦は1000000+ポストNo.、横は2000000+ポストNo.。百万件掘る人がいたら再考する。
・rootのvcで回転を検知するたびに片方のviewのhiddenをYESにする。
・ボタンのcgrectを参照してrootのvcから縦横2つのviewに貼るのは面倒かつ醜いのでpostのviewが自前で貼るようにして、メッセージをrootのvcで受けるようにdelegateを使う。(初挑戦)
・viewDidLoadでself.view.boundsが呼ばれるたびに現状のウィンドウを取得すると思ってたらviewDidAppearでやらんとダメということを知ったので改修。

とりあえずこれで動いてる様子。

rootのvc
- (void)mkSinglePostView{
 for(int i=[pvArr count];i<[contArr count];i++){
  postv=[[SinglePost2 alloc]init];postv.delegate=self;
  [postv constructWithtype:[typeArr objectAtIndex:i] cont:[contArr objectAtIndex:i] bnamet:[bnameArr objectAtIndex:i] now:i+1];
  [naxArr addObject:postv.nax];
  if(postv.linkurl)[openArr insertObject:postv.linkurl atIndex:i];
  [postv.view setTag:i+1];
  [pvArr addObject:postv.view];
 }
 [pvlayer.view addSubview:[pvArr objectAtIndex:now-1]];[pvlayer.view setFrame:self.view.bounds];
 if(!now_all) now_all=[[UILabel alloc]init];[self na];
 if(!caption) caption=[[UILabel alloc]init];[self mkCaption];
}

-(void)reflink{
 if([[typeArr objectAtIndex:now-1]isEqual:@"link"]){
  if(UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)){
   [self.view viewWithTag:1000000+now].hidden=YES;[self.view viewWithTag:2000000+now].hidden=NO;
  }else{
   [self.view viewWithTag:1000000+now].hidden=NO;[self.view viewWithTag:2000000+now].hidden=YES;
  }
 }
}
SinglePost2.m
}else if([type isEqualToString:@"link"]){
  _linkurl=[cont objectAtIndex:1];
  for(int pl=0;pl<2;pl++){
   Link *link=[[Link alloc]initWithFrame:CGRectMake(10,30,(pl?sh:sw)-20,(pl?sw:sh)-80)
             string:[[cont objectAtIndex:0]isEqual:[NSNull null]]||[[cont objectAtIndex:0]isEqual:@""]?@"(no text)":[cont objectAtIndex:0]];
   UIImage *openlinkimg=[UIImage imageNamed:@"openlink"],*openlinkimg_on=[UIImage imageNamed:@"openlink_on"];
   UIButton *open=[UIButton buttonWithType:UIButtonTypeCustom];
   [open setImage:openlinkimg forState:UIControlStateNormal];[open setImage:openlinkimg_on forState:UIControlStateHighlighted];
   [open addTarget:delegate action:@selector(openPage) forControlEvents:UIControlEventTouchUpInside];
   [open setFrame:CGRectMake(10,(pl?sw:sh)-link.origin.y-30,openlinkimg.size.width,openlinkimg.size.height)];
   UIView *lv=[[UIView alloc]initWithFrame:CGRectMake(0,0,pl?sh:sw,pl?sw:sh)];
   [lv addSubview:link];[lv addSubview:open];[lv setTag:(pl?2000000:1000000)+now];
   if(UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)){if(!pl)lv.hidden=YES;}
   else if(pl)lv.hidden=YES;
   [self.view addSubview:lv];
  }
}
OpenPage.m
- (void)viewDidLoad
{
    [super viewDidLoad];
 // Do any additional setup after loading the view.
}

-(void)viewDidAppear:(BOOL)animated{
 page=[[UIWebView alloc]initWithFrame:self.view.bounds];page.scalesPageToFit=YES;page.delegate=self;page.autoresizingMask=18;[self.view addSubview:page];
 toolbar=[[UIToolbar alloc]initWithFrame:CGRectMake(0, self.view.bounds.size.height-36, self.view.bounds.size.width,36)];
 toolbar.tintColor=[UIColor blackColor];toolbar.translucent=YES;
 [self.view addSubview:toolbar];toolbar.autoresizingMask=42;
 back=[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemRewind target:self action:@selector(back)];
 forward=[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFastForward target:self action:@selector(forward)];
 done=[[UIBarButtonItem alloc]initWithTitle:@"done" style:UIBarButtonItemStyleDone target:self action:@selector(killme)];
 NSArray *buttons=[[NSArray alloc]initWithObjects:done,back,forward,nil];
 [toolbar setItems:buttons animated:YES];
 [page loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]]]; 
}
できた。あとはchat,audio,video,answerの回転対応。余裕やと思ってたけどまだまだベーシックな部分で理解と知識が足りてない。