What Is Software Design?

程式設計不是 “building software”,而是 “designing software”。

Is Design Dead?

軟體系統的設計是演進來的,不能一步到位,而是要藉由憑繁與使用者互動得到的回饋來修改系統設計。

Programming is Gardening, not Engineering

與其把程式設計比喻成蓋房子,實際上更像是園藝。

Orthogonality and the DRY Principle

所有程式設計活動其實都是維護,因為絕大部分的時間都在改code,寫一點改一點。即使是新專案,也很快需要回頭作修改。

2013年7月25日 星期四

iOS 設計出 facebook 留言的 bottom bar 隨著 text 鍵盤上升出現





step1.
首先要創一個 ViewController 

step2.
ViewController 後面加上UITextViewDelegate 如下

@interface ViewController ()<UITextViewDelegate >

{
        UITextView * commentTextView;
        UITextView * realCommentTextView;
}


step3.
ViewController 的viewDidLoad

//新增一個bottomview

 UIToolbar *bottomView = [[UIToolbar alloc] initWithFrame:CGRectMake(0,[UIScreen mainScreen].bounds.size.height-49, 320, 49)];
    [self.view addSubview:bottomView];
    bottomView.backgroundColor = [UIColor blackColor];
    bottomView.tintColor = [UIColor grayColor];
    
//新增一個輸入textview

    commentTextView = [[UITextView alloc] initWithFrame:CGRectMake(8, 10, 250, 30)];
    [bottomView addSubview:commentTextView];
    commentTextView.delegate = self;
    commentTextView.backgroundColor = [UIColor whiteColor];
    [commentTextView.layer setCornerRadius:5];
    commentTextView.clipsToBounds = YES;
    [commentTextView.layer setBorderWidth: 1.0];
    [commentTextView.layer setBorderColor: [[UIColor grayColor] CGColor]];

    commentTextView.font = [UIFont systemFontOfSize:16];

//新增一個輸入button

    UIButton *commentButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    commentButton.frame = CGRectMake(265, 10, 45, 30);
    [commentButton setTitle:NSLocalizedString(@"Send", nil) forState:UIControlStateNormal];
    [bottomView addSubview: commentButton];
    [commentButton addTarget:self action:@selector(addCommentButPressed:) forControlEvents:UIControlEventTouchUpInside];

step4.

在新增點下後的樣子

//新增一個bottomview

UIToolbar *bottomView2 = [[UIToolbar alloc] initWithFrame:CGRectMake(0, [UIScreen mainScreen].bounds.size.height-20-44-49, 320, 49)];
    bottomView2.backgroundColor = [UIColor blackColor];
    bottomView2.tintColor = [UIColor grayColor];


//新增一個輸入textview   

    realCommentTextView = [[UITextView alloc] initWithFrame:CGRectMake(8, 10, 250, 30)];
    realCommentTextView.delegate = self;
    realCommentTextView.backgroundColor = [UIColor whiteColor];
    realCommentTextView.clipsToBounds = YES;
    [realCommentTextView.layer setCornerRadius:5];
    [bottomView2 addSubview:realCommentTextView];
    [realCommentTextView.layer setBorderWidth: 1.0];
    [realCommentTextView.layer setBorderColor: [[UIColor grayColor] CGColor]];
    realCommentTextView.font = [UIFont systemFontOfSize:16];
    
//新增一個輸入button

    UIButton *commentButton2 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    commentButton2.frame = CGRectMake(265104530);
    [commentButton2 setTitle:NSLocalizedString(@"Send"nilforState:UIControlStateNormal];
    [bottomView2 addSubview: commentButton2];
    [commentButton2 addTarget:self action:@selector(addCommentButPressed:) forControlEvents:UIControlEventTouchUpInside];



step5.

讓點下後出現bottomView2

    commentTextView.inputAccessoryView = bottomView2;

step6.

加上UITextViewDelegate當輸入很多的時候高會改變並且開起scrolls

#pragma mark - UITextViewDelegate

- (void)textViewDidChange:(UITextView *)textView
{
    if(textView.contentSize.height > 50)
    {
        textView.superview.frame = CGRectMake(0, 0, 320, 98);
        textView.frame = CGRectMake(5, 14.5, 250, 60);
        [textView scrollsToTop];
    }
}


2013年7月19日 星期五

Html5 Canvas 基本練習 劃線 畫圓


什麼是Canvas

HTML5的Canvas元素使用的Javascript在網頁上繪製圖像。

Canvas是一個矩形區域,您可以控制其每一像素。

Canvas上擁有多種繪製路徑,矩形,圓形,字符以及添加圖片的方法


Create a Canvas

<canvas id="myCanvas" width="200" height="100"></canvas>

Draw Onto The Canvas With JavaScript

<script>

var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.fillStyle="#FF0000";
ctx.fillRect(10,10,150,75);

</script>

Canvas劃線

<script>

var c=document.getElementById("myCanvas");
var cxt=c.getContext("2d");
cxt.moveTo(10,10);
cxt.lineTo(150,50);
cxt.lineTo(10,50);
cxt.stroke();

</script>





Canvas劃圓

<script type="text/javascript">

var c=document.getElementById("myCanvas");
var cxt=c.getContext("2d");
cxt.fillStyle="#FF0000";
cxt.beginPath();
cxt.arc(70,18,15,0,Math.PI*2,true);
cxt.closePath();
cxt.fill();

</script>





Canvas劃漸層背景

<script type="text/javascript">

var c=document.getElementById("myCanvas");
var cxt=c.getContext("2d");
var grd=cxt.createLinearGradient(0,0,175,50);
grd.addColorStop(0,"#FF0000");
grd.addColorStop(1,"#00FF00");
cxt.fillStyle=grd;
cxt.fillRect(0,0,175,50);

</script>



Canvas貼上圖片


<script type="text/javascript">

var c=document.getElementById("myCanvas");
var cxt=c.getContext("2d");
var img=new Image()
img.src="flower.png"
cxt.drawImage(img,0,0);

</script>








參考文獻:http://www.w3school.com.cn/html5/html_5_canvas.asp


AngularJS 練習 ngBind

step1.

進入  http://plnkr.co/edit/?p=preview

step2.

左邊選擇index.html

將以下的code全部覆蓋

<!doctype html>
<html ng-app>
  <head>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.min.js"></script>
    <script src="script.js"></script>

  </head>
  <body>

<div ng-controller="Ctrl">
  Enter name: <input type="text" ng-model="name"><br>
  Hello <span ng-bind="name"></span>!
</div>


  </body>
</html>


step3.

左邊選擇script.js

貼上以下的code

function Ctrl($scope) {
  $scope.name = 'Whirled';
}

step4. 觀看結果


在上面有一個button run的請您按下會看到以下的結果

Enter name: 
Hello Whirled!


請您再輸入的框框中 輸入值 會直接Bind 顯示到<span ng-bind="name"></span>

讓您寫起程式更加方便清楚明白



iOS 擊點背景讓textField鍵盤縮下去

step1.
新增一個UITextField出來

UITextField *myTextField=[[UITextField alloc]initWithFrame:CGRectMake(
121, 30, 159, 30) ];


 self.nameTextField.placeholder = @"請輸入xxxx";

self.myTextField.delegate = self ;//要設定代理人


step2.
設定按背景

if(&UIViewNoIntrinsicMetric)
{
        UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap:)];
        [self.view addGestureRecognizer:tapGesture];
        
}

step3. 按下後執行的副程式

-(void)tap:(id)sender
{
    [self.view endEditing:YES];
    //[ScrollView setContentOffset:CGPointMake(0, 0) animated:YES]; //會幫你移動道你要顯示的行數
}

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    [textField resignFirstResponder];

    return YES;
}

=================================================

顯示keyboard:
[myTextField becomeFirstResponder];

隱藏keyboard:
[myTextField resignFirstResponder];

endEditing:的方法
下面介紹一下endEditing:的方法,該方法為UIView中的一個方法,定義為

- (BOOL)endEditing:(BOOL)force

官方原文

Causes the view (or one of its embedded text fields) to resign the first responder status.
This method looks at the current view and its subview hierarchy for the text field that is currently the first responder. If it finds one, it asks that text field to resign as first responder. If the force parameter is set to YES, the text field is never even asked; it is forced to resign.
翻譯為
註銷當前view(或它下屬嵌入的test fidlds)的first responder狀態
該方法在view中找到處於first responder狀態的test fiedld,如果找到會註銷其狀態,如果指定force參數為YES,則不再詢問test field,而直接強制註銷其他first responder狀態






2013年7月18日 星期四

iOS 取得裝置平台類型或版本名稱的方法

step1.
有關的標頭檔
#import <sys/types.h>
#import <sys/sysctl.h>

step2.
取使用的機台副程式

- (NSString *) deviceModel {
    size_t size;
    sysctlbyname("hw.machine", NULL, &size, NULL, 0);
    char *model = malloc(size);
    sysctlbyname("hw.machine", model, &size, NULL, 0);
    NSString *deviceModel = [NSString stringWithCString:model encoding:NSUTF8StringEncoding];
    free(model);
    
    return deviceModel;
}

step3.
使用

NSString *platform = [self deviceModel];

NSString *iosVersion = [[UIDevice currentDevice] systemVersion];
NSString *appVersion = [[[NSBundle mainBundle] infoDictionary]objectForKey:@"CFBundleShortVersionString"];


NSString *content = [NSString stringWithFormat:@"\n\nApp版本: %@, iOS版本: %@, 硬體版本: %@",appVersion, iosVersion, platform];



app版本可以到這裡來修改 如下圖






機器版本      市售的商品名稱
 
i386         iOS 模擬器(i386)
x86_64       iOS 模擬器(x86_64)
 
iPhone1,1    iPhone 1G
iPhone1,2    iPhone 3G
iPhone2,1    iPhone 3Gs
iPhone3,1    iPhone 4
iPhone4,1    iPhone 4s
iPhone5,1    iPhone 5
 
iPod1,1      iPod touch 1
iPod2,1      iPod touch 2
iPod3,1      iPod touch 3
iPod4,1      iPod touch 4
 
iPad1,1      iPad
iPad2,1      iPad 2
=====================================================

辨別是否為iphne or ipad

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
    //判斷為 iPhone 介面裝置
}
 
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
    //判斷為 iPad 介面裝置
}

=====================================================

辨別是否為模擬器 或是實體機器

#if TARGET_IPHONE_SIMULATOR
 
    NSLog(@"使用為模擬器執行");
 
#endif


若要判斷實體裝置請使用「!TARGET_IPHONE_SIMULATOR」或是「#else」敘述,切勿使用 TARGET_OS_IPHONE(用來判斷是否是 iOS 應用程式)。
最後,在 UIDevice 方面,則可以透過 modle 所回傳的字串來判斷是實體裝置或是模擬器。

[[UIDevice currentDevice] model]



參考文獻:http://furnacedigital.blogspot.tw/2011/02/blog-post_14.html





iOS NSDate 要增加月份 或 往前推月份

現在NSDate


NSDate *newdate = [NSDate date];


1.增加月份


NSDateComponents* dateComponents = [[NSDateComponents alloc]init];
[dateComponents setMonth:1];
NSCalendar* calendar = [NSCalendar currentCalendar];
NSDate* newDate = [calendar dateByAddingComponents:dateComponents toDate:“這邊填寫目前的NSDate” options:0];

1.減少月份
NSDateComponents* dateComponents = [[NSDateComponents alloc]init];
[dateComponents setMonth:-1];
NSCalendar* calendar = [NSCalendar currentCalendar];
NSDate* newDate = [calendar dateByAddingComponents:dateComponents toDate:“這邊填寫目前的NSDate” options:0];

iOS NSdate 的格式轉換 與 轉成字串


step1.
//建立空字串
NSString *str =[[NSString alloc] init];


step2.
//建立轉換參數
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"輸入正規化參數 ex:YYYY-MM-d"];

step3.
//轉換成字串
NSString *correctDate = [formatter stringFromDate:date]; 


PS:如果要字串轉回NSDate
NSDate *date = [dateFormatter dateFromString:@"2010-08-04 16:01:03"];


與時間相關
參數      代表意義
 
a        AM/PM (上午/下午)
K        0~11 0時的12小時制
h        1~12 12小時制
H        0~23 0時的24小时制
k        1~24 24小時制
m        0~59 分鐘
s        0~59 秒數
s        秒數的個位數
A        0~86399999 一天當中的第幾微秒
 
v~vvv    一般的GMT時區縮寫
vvvv     一般的GMT時區名稱
z~zzz    具體的GMT時區縮寫
zzzz     具體的GMT時區名稱


======================================================================

與日期相關
參數      代表意義
 
d        1~31 日期
D        1~366 一年的第幾天
e        1~7 一週的第幾天
c/cc     1~7 一週的第幾天,星期日為第一天
 
ccc      星期幾縮寫
E~EEE    星期幾縮寫
cccc     星期幾全名
EEEE     星期幾全名
 
F        1~5 每月第幾周,一周的第一天為周一
w        1~5 每月第幾周,一周的第一天為周日
w        1~53 一年的第幾周,從去年的最後一個周日算起,一周的第一天為周日
 
L/LL     1~12 第幾個月
M/MM     1~12 第幾個月
LLL      月份縮寫
MMM      月份縮寫
LLLL     月份全名
MMMM     月份全名
 
q/qq     1~4 第幾季
Q/QQ     1~4 第幾季
qqq      季度縮寫
QQQ      季度縮寫
qqqq     季度全名
QQQQ     季度全名
 
u        完整年份
y/yyyy   完整年份
Y/YYYY   完整年份,從星期天開始的第一周算起
yy/yyy   兩位數的年份
YY/YYY   兩位數的年份,從星期天開始的第一周算起

==========================================================================
特殊用途
參數      代表意義
 
g        Julian Day Number,從4713 BC一月一日算起
G~GGG    BC/AD 西元前後縮寫
GGGG     西元前後全名





參考文獻: http://furnacedigital.blogspot.tw/2011/02/nsdateformatter.html#sthash.EMQ02sbN.dpuf

2013年7月11日 星期四

iOS NSDate 日期比較的用法


1.想要讀取現在時間


NSDate *now = [[NSDate alloc] init];

Nslog[@"now: %@",now];


2.日期比較

相同時間 回傳 bool

bool check = [checkdate isEqualToDate:now];


獲取較早的日期

NSDate * checkdate = [now earlierDate: inputData ];


獲取較晚的日期

NSDate * checkdate = [now laterDate: inputData ];

iOS AFNetworking


1. 先用Pods 把第三方原件 加入進來

platform :ios, '5.0'
pod 'AFNetworking', '~> 1.2'

2.

將AFNetworking 加入參考

#import <AFNetworking.h>

可以到Xcode資料夾底下 Supporting Files
的 .pch 檔案的裡面

#import <Availability.h>

#ifndef __IPHONE_5_0
#warning "This project uses features only available in iOS SDK 5.0 and later."
#endif

#ifdef __OBJC__
    #import <UIKit/UIKit.h>
    #import <Foundation/Foundation.h>
    #import <AFNetworking.h>

#endif


3.
簡單範例

    static NSString *const BaseURLString = @"http://140.131.95.60/TESTAPI/";
    

    NSString *weatherUrl = [NSString stringWithFormat:@"%@api/product", BaseURLString];
    
    NSURL *url = [NSURL URLWithString:weatherUrl];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    AFJSONRequestOperation *operation =
    [AFJSONRequestOperation JSONRequestOperationWithRequest:request
    success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
//                                                        self.weather  = (NSDictionary *)JSON;
//                                                        self.title = @"JSON Retrieved";
//                                                        [self.tableView reloadData];
        NSLog(@"%@",response);
        NSLog(@"%@",JSON);

                                                    }
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"Error Retrieving Weather"
        message:[NSString stringWithFormat:@"%@",error]delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
            [av show];
    }];
    

    [operation start];



4.接下來要解出json的封包



        NSDictionary *JSONdata = (NSDictionary *)JSON;
        
        for (NSDictionary *carDict in JSONdata) {
            
            NSString * email = [carDict valueForKey:@"email"];
                    NSLog(@"%@",email);
             }


傳回

2013-07-11 17:43:54.981 testcocoapods[15122:a0b] john6812711@gmail.com
2013-07-11 17:43:54.983 testcocoapods[15122:a0b] john6812711@gmail.com
2013-07-11 17:43:54.984 testcocoapods[15122:a0b] john6812711@gmail.com
2013-07-11 17:43:54.984 testcocoapods[15122:a0b] john6812711@gmail.com
2013-07-11 17:43:54.984 testcocoapods[15122:a0b] john@yahoo
2013-07-11 17:43:54.984 testcocoapods[15122:a0b] iLoveJohn@gmail.com
2013-07-11 17:43:54.985 testcocoapods[15122:a0b] john6812711@gmail.com
2013-07-11 17:43:54.985 testcocoapods[15122:a0b] john6812711@yahoo.com.tw
2013-07-11 17:43:54.986 testcocoapods[15122:a0b] john6812711@gmail.com




2013年7月8日 星期一

ASP.net 2012 api 要跨網域方法

假設我們今天開發了一個 ASP.NET Web API 的 Web Services ,這個 Service 的主機名稱為 www.web1.com (稱A),同時我們也開發另外一個網站主機名稱為 www.web2.com (稱B),然而假設 B 網站存取 A 網站的 Web API ,所以我們使用 XMLRequest 或 jQuery 的 $.ajax 來呼叫我們的 Web API ,不幸的是這樣的溝通是會出錯的,因為瀏覽器不允許使用 AJAX 來呼叫外部的資源。

不過雖然瀏覽器為了安全起見阻止此類的呼叫,不過假設我們今天的請求是合法的呢?




從錯誤訊息中我們可以清楚看到 XMLHttpRequest 調用失敗,並且明確寫著來源不允許請求 "Access-Control-Allow-Origin",而什麼是  "Access-Control-Allow-Origin":當每次網頁伺服器在回應瀏覽器請求時,而當 HTTP Header 中有時會帶有  "Access-Control-Allow-Origin" 時,就可以做到跨網域的請求。


解決方法

 web.config 這個設定的作法比較簡單,但還是存在著風險,因為這樣的設定可以讓全世界的網站都可以來存取你這個網站的所有 Web API,就算是 Google 或 Facebook 也不可能公開所有的 API 來讓一般使用者存取

<system.webServer>
//裡面加入

 <httpProtocol>

    <customHeaders>
              <add name="Access-Control-Request-Origin" value="*"></add>
              <add name="Access-Control-Request-Headers" value="Origin,X-Requested-With,Content-Type,Accept" ></add>
             <add name="Access-Control-Request-Method" value="POST,GET,PUT,DELETE,OPTIONS" ></add>
    </customHeaders>
    </httpProtocol>