我們習慣在開發中把資料和介面分開實現,這種方式比較好,只需要在資料和介面中同時依賴乙個資料結構即可,這種做法對於解藕是乙個不錯的方式。
但是有一些細節的地方可能會導致我們遇到一些很難查詢的bug,比如我們之前遇到的乙個問題,現在分享給大家。
先來描述一下問題:我們在uitableview中加入了乙個向下拖動重新整理資料的控制項,控制項是egorefreshtableheaderview。拖動後,我們就使用asihttprequest重新整理資料,但是在拖動幅度大一些時,asihttprequest請求發出後就直接崩潰了,而且看棧也看不出崩在哪。
資料請求**如下:
- (void)startgetnewslistdata
nsstring *strurl = @"*****";//此處需要填入url的位址字串
//設定委託,委託自己實現非同步請求方法
[request setdelegate : self ];
// 開始非同步請求
[requeststartasynchronous ];//執行完這句後,就直接崩潰了
......//其他邏輯
[[nsnotificationcenterdefaultcenter]postnotificationname:@"getnewslistdatadone"object:newsdataarray];
}
猜測除錯過程如下:
1)開始猜測問題是egorefreshtableheaderview大幅拖動導致的,於是把asihttprequest請求資料注釋掉,再次大幅拖動,程式沒崩。
2)那問題一定出在
asihttprequest請求部分,猜測會不會是請求在子執行緒中做的,導致的問題,除錯一下,發現請求還是在主線程中,所以也排除了這種情況。
3)一開始一直以為是
asihttprequest出的問題,所以精力一直放在他上面。但是後來調了1個小時,查了asihttprequest的使用說明,也沒查到什麼疑點。
4)實在是沒辦法了,祭出屠龍寶刀:開始**分段注釋,執行看結果。問題出在
- (void)startgetnewslistdata函式,所以從這邊開始:注釋
if (nil != newsdataarray && newsdataarray.count > 0)
這段,執行,結果正常了,http請求也能收到返回的結果了,天哪,要是早點採用這種方法,也就不用之前嘗試的1個小時了。開始分析為什麼,
newsdataarray
前面說了,這個資料是會通過
[[nsnotificationcenter defaultcenter] postnotificationname:@"getnewslistdatadone" object:newsdataarray]; 傳送,給uitableview中使用,看接收稱處的**:
......
[[nsnotificationcenterdefaultcenter]addobserver:selfselector:@selector(ongetnewslistdatasuccess:)name:@"getnewslistdatadone"object:nil];
......
- (void)ongetnewslistdatasuccess:(nsnotification*)notify
[m_tableview reloaddata];
......
}- (uitableviewcell *)tableview:(uitableview *)tableview cellforrowatindexpath:(nsindexpath *)indexpath
nsinteger row = indexpath.row;
if (m_arrnews)
......
return cell;
}
看完這些,我也知道問題出在什麼地方了,我們知道,在uitableview中,在使用者拖動cell,有cell 的indexpath發生變化時,就會觸發這個函式:
- (uitableviewcell *)tableview:(uitableview *)tableview cellforrowatindexpath:(nsindexpath *)這個函式中我們用到了m_arrnews,而m_arrnews又是通過
nsmutablearray *receivearray = [notify object];
......
m_arrnews = receivearray;
這麼來的,這裡面全是使用的指標拷貝,原來問題就是這個:淺拷貝,
先來解釋一下深拷貝和淺拷貝:
(1)深拷貝,就是新拷貝一塊記憶體交給物件使用。會拷貝整個資料到新的位址,老的拷貝源改變和目標位址的資料就無關了。
(2)淺拷貝,就是覺得拷貝記憶體太浪費,直接給你我的位址吧。當然這個位址和拷貝源相同,只要拷貝源發生改變,這個目標位址中的資料也會變化。
問題就明顯了
[newsdataarray
removeallobjects
];導致了uitableview中的資料來源發生變化,而大幅度拉動,導致了uitableview中資料重新整理,進入
- (uitableviewcell *)tableview:(uitableview *)tableview cellforrowatindexpath:(nsindexpath *),資料失效,導致崩潰,那解決問題也很簡單,使用深拷貝就可以了。
- (void)ongetnewslistdatasuccess:(nsnotification*)notify
[m_tableviewreloaddata];
......
}
問題解決,收工。
問乙個系統設計的問題
當使用hibernate開源框架去做乙個大中型系統的持久層時,我們一開始做的究竟應該是先設計資料庫,然後按照資料庫,使用工具將資料庫對映成物件 還是完全撇開傳統的關聯式資料庫思想,先建立實體之間關係圖 或建立域模型 然後根據該模型在設計資料庫。不知道大家在平時的設計時一般按哪樣的流程去做,能否介紹下...
MFC寫的乙個介面遇到的問題
1 變數值從一父視窗類傳遞到子視窗類中。方法 cmplayer wnew wnew.buf1 buffer wnew.domodal 2 vs2012中工程預設為unicode字符集,所以使用的實際上是cstringw類。a cstring轉換為char陣列要想使用getbuffer和strcpy轉...
如何設計乙個良好的介面
在設計介面時,有很多因素要考慮,如介面的業務定位,介面的安全性,介面的可擴充套件性 介面的穩定性 介面的跨域性 介面的協議規則 介面的路徑規則 介面單一原則 介面過濾和介面組合等諸多因素,本篇文章將簡要分析這些因素。一 規範性建議 1.職責原則 在設計介面時,必須明確介面的職責,即介面型別,介面應解...