環境資訊中心特約記者 陳文姿報導
本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能
※評比前十大台北網頁設計、台北網站設計公司知名案例作品心得分享
※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選
※台灣海運大陸貨務運送流程
※兩岸物流進出口一站式服務
居家、公司行號垃圾清運、廢棄物處理、大型家具回收,服務快速,包月及計重或計桶供客戶選擇,合法登記的清潔公司、廢棄物清除許可,專業技術人員及專業廢棄物清運車輛
摘錄自2018年9月21日蘋果日報美國洛杉磯報導
洛杉磯市議會周二(18日)通過議案,將立法禁止銷售皮草衣飾。議會全體投下贊成票,立場堅定;洛杉磯將成為美國禁售皮草的最大城市,可望為其他時尚重鎮帶來示範作用。
洛杉磯市議會以12比0的票數,一致贊成禁止商業皮草。立法機構負責草擬法規,由市議會審核,正式法規將在通過審議的兩年後生效。預計這類法規會為宗教目的、合法漁獵執照持有者另闢途徑,允許合法使用或生產動物皮草。
加州舊金山、西好萊塢、柏克萊都已限制皮草,但像洛杉磯這麼大規模的城市還是首例。提出此議案的議員科瑞茲(Paul Koretz)表示,洛杉磯是世界時尚之都,期許此舉能成為世界典範,紐約、芝加哥和邁阿密等大城可以跟進。
本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計
※不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務
※Google地圖已可更新顯示潭子電動車充電站設置地點!!
※小三通物流營運型態?
※快速運回,大陸空運推薦?
今天我們緊接着上一篇繼續分享Appium自動化測試框架綜合實踐 – 代碼實現。到今天為止,大功即將告成;框架所需要的代碼實現都基本完成。
在實際項目過程中,我們的數據可能是存儲在一個數據文件中,如txt,excel、csv文件類型。我們可以封裝一些方法來讀取文件中的數據來實現數據驅動。
將測試賬號存儲在account.csv文件,內容如下:
|
hg2018 |
hg2018 |
|
hg2019 |
zxw2019 |
|
666 |
222 |
enumerate()是python的內置函數
如果對一個列表,既要遍歷索引又要遍曆元素時,首先可以這樣寫:
list = ["這", "是", "一個", "測試","數據"] for i in range(len(list)): print(i,list[i])
上述方法有些累贅,利用enumerate()會更加直接和優美:
list1 = ["這", "是", "一個", "測試","數據"] for index, item in enumerate(list1): print(index,item)
數據讀取方法也屬於公共方法,這裏我們首先實現一下,然後將其封裝到裡邊即可。
import csv def get_csv_data(csv_file,line): with open(csv_file, 'r', encoding='utf-8-sig') as file: reader=csv.reader(file) for index, row in enumerate(reader,1): if index == line: return row csv_file='../data/account.csv' data=get_csv_data(csv_file,3) print(data)
將其封裝在公共方法中,在其他地方用到的時候,直接導入調用即可。
UTF-8以字節為編碼單元,它的字節順序在所有系統中都是一樣的,沒有字節序的問題,也因此它實際上並不需要BOM(“ByteOrder Mark”)。但是UTF-8 with BOM即utf-8-sig需要提供BOM。
各種配置文件都放在這個目錄下。
主要是一些日誌信息的配置。
[loggers] keys=root,infoLogger [logger_root] level=DEBUG handlers=consoleHandler,fileHandler [logger_infoLogger] handlers=consoleHandler,fileHandler qualname=infoLogger propagate=0 [handlers] keys=consoleHandler,fileHandler [handler_consoleHandler] class=StreamHandler level=INFO formatter=form02 args=(sys.stdout,) [handler_fileHandler] class=FileHandler level=INFO formatter=form01 args=('../logs/runlog.log', 'a') [formatters] keys=form01,form02 [formatter_form01] format=%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s [formatter_form02] format=%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s
這裏宏哥舉例給小夥伴們演示:封裝註冊和登錄兩個測試用例。
測試用例執行開始和結束的封裝,其他模塊用到直接導入,調用即可。
# coding=utf-8 # 1.先設置編碼,utf-8可支持中英文,如上,一般放在第一行 # 2.註釋:包括記錄創建時間,創建人,項目名稱。 ''' Created on 2019-11-20 @author: 北京-宏哥 QQ交流群:707699217 Project:Appium自動化測試框架綜合實踐 - 代碼實現 ''' # 3.導入模塊 import unittest from kyb_testProject.common.desired_caps import appium_desired import logging from time import sleep class StartEnd(unittest.TestCase): def setUp(self): logging.info('=====setUp====') self.driver=appium_desired() def tearDown(self): logging.info('====tearDown====') sleep(5) self.driver.close_app()
開始註冊用例代碼邏輯的實現。
# coding=utf-8 # 1.先設置編碼,utf-8可支持中英文,如上,一般放在第一行 # 2.註釋:包括記錄創建時間,創建人,項目名稱。 ''' Created on 2019-11-20 @author: 北京-宏哥 QQ交流群:707699217 Project:Appium自動化測試框架綜合實踐 - 代碼實現 ''' # 3.導入模塊 from kyb_testProject.common.myunit import StartEnd from kyb_testProject.businessView.registerView import RegisterView import logging,random,unittest class RegisterTest(StartEnd): def test_user_register(self): logging.info('======test_user_register======') r=RegisterView(self.driver) username = 'bjhg2019' + 'fly' + str(random.randint(1000, 9000)) password = 'bjhg2020' + str(random.randint(1000, 9000)) email = 'bjhg' + str(random.randint(1000, 9000)) + '@163.com' self.assertTrue(r.register_action(username,password,email)) if __name__ == '__main__': unittest.main()
開始登錄用例代碼邏輯的實現。
# coding=utf-8 # 1.先設置編碼,utf-8可支持中英文,如上,一般放在第一行 # 2.註釋:包括記錄創建時間,創建人,項目名稱。 ''' Created on 2019-11-13 @author: 北京-宏哥 QQ交流群:707699217 Project:Appium自動化測試框架綜合實踐 - 代碼實現 ''' # 3.導入模塊 from kyb_testProject.common.myunit import StartEnd from kyb_testProject.businessView.loginView import LoginView import unittest import logging class TestLogin(StartEnd): csv_file='../data/account.csv' @unittest.skip('test_login_zxw2018') def test_login_zxw2018(self): logging.info('======test_login_zxw2018=====') l=LoginView(self.driver) data=l.get_csv_data(self.csv_file,2) l.login_action(data[0],data[1]) self.assertTrue(l.check_loginStatus()) # @unittest.skip('skip test_login_zxw2017') def test_login_zxw2017(self): logging.info('======test_login_zxw2017=====') l=LoginView(self.driver) data = l.get_csv_data(self.csv_file, 1) l.login_action(data[0], data[1]) self.assertTrue(l.check_loginStatus()) @unittest.skip('test_login_error') def test_login_error(self): logging.info('======test_login_error=====') l = LoginView(self.driver) data = l.get_csv_data(self.csv_file, 3) l.login_action(data[0], data[1]) self.assertTrue(l.check_loginStatus(),msg='login fail!') if __name__ == '__main__': unittest.main()
到此,Appium自動化測試框架就差下一篇就全部完成了,聰明的你都懂了嗎???嘿嘿!慢慢地來吧。
下一篇,講解執行測試用例,生成測試報告,以及自動化平台,請關注宏哥,敬請期待!!!
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能
※評比前十大台北網頁設計、台北網站設計公司知名案例作品心得分享
※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選
※台灣海運大陸貨務運送流程
※兩岸物流進出口一站式服務
摘錄自2018年9月25日中央社報導
美國聯邦法官今天(25日)下令將棲息在黃石國家公園內部及周遭的灰熊,重新列入瀕臨滅絕物種保護法(ESA)保護名單,阻擋40年多來首度開放在這個地區獵捕灰熊的計畫。
美國蒙大拿州密蘇拉(Missoula)聯邦地區法官克里斯坦森(Dana Christensen)與環保人士及美國原住民站在同一陣線,駁回美國魚類暨野生動物管理局(U.S. Fish and Wildlife Service)將灰熊從瀕危物種名單除名的決定。
環保人士主張,根據瀕臨滅絕物種保護法,對這些灰熊與蒙大拿州和下48州(Lower 48)的其他灰熊族群採取差別待遇,是生物學上靠不住且非法行為,法官也同意這類說法。
環保人士說,儘管灰熊數量有所回升,倘若沒有受到聯邦持續保護,牠們的復育情況就會受到影響。此外,氣候變遷導致灰熊食物供給出現變化和人為死亡率高,也對灰熊生存構成威脅。
本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能
※評比前十大台北網頁設計、台北網站設計公司知名案例作品心得分享
※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選
※台灣海運大陸貨務運送流程
※兩岸物流進出口一站式服務
4月25日,騰勢在北京車展發佈全新的騰勢新動生活解決方案,宣佈在2016年年底前在全國建設650個騰勢專屬公共充電樁。針對有長途出行的車主,騰勢還將提供50%的折扣價格租用梅賽德斯-賓士C級轎車的福利。
為解決車主充電難的問題,騰勢將進一步在北上廣深等城市的大型商場、酒店、寫字樓和機場等交通樞紐建設騰勢專屬公共充電樁,預計2016年年底前在全國建設650個騰勢專屬公共充電樁。與此同時,騰勢服務網路在2015年擴大到了9個城市13家銷售服務網點,未來將在重點城市開設更多服務網點。
在質保方面,騰勢將為動力電池及關鍵零部件提供8年或15萬公里的保修期,為消費者提供無憂的售後保障服務。另外,騰勢還將開放新技術升級服務,騰勢車主可以進行軟體升級或部件升級。在移動應用方面,騰勢專屬App將提供更為智慧貼心的遠端操控功能,可實現智慧充電控制、車內設備控制、車輛狀態查詢以及一鍵尋車等功能。
本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能
※評比前十大台北網頁設計、台北網站設計公司知名案例作品心得分享
※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選
※台灣海運大陸貨務運送流程
※兩岸物流進出口一站式服務
日前,中能工業智慧技術研究院發佈了EVOP電動汽車運營平臺,打造中國最強電動汽車網聯大腦。
從傳統意義上來說,電動汽車只是“行駛+充電”的物理組合,滿足人們最基本的代步需求;而EVOP在此基礎上,通過互聯網和智慧化平臺,將電動汽車和充電設備打造成為能源互聯網產業鏈的重要一環。
和其他智慧化汽車應用相比,EVOP平臺基於中國最強工業大腦DPEN而打造,將資料、資訊和互聯網相結合,讓電動汽車產業鏈變得更智慧。DPEN支持數千萬個採集節點。在DPEN的引領之下,源源不斷的資料進入EVOP平臺,分門別類進行存儲和分析,並通過互聯網傳遞到每一輛電動汽車或者充電設備上,指導設備智慧化、高效率運行,並實現充電網、互聯網、車聯網“三網融合”。
在充電端,EVOP可以輕鬆實現智慧充電功能,它可以即時檢測並調整充電狀態,加強電池的健康管理,引導智慧有序充電、計量計費,並讓車主通過手機隨時瞭解充電情況;而商業地產、物業管理公司、電動汽車廠商等運營商和服務商可以通過雲平臺實現充電樁和車載電池的智慧管理,提供良好的增值服務。
在行駛端,由EVOP平臺海量採集的資料經過精確梳理和分析,通過雲平臺提供給每一位車主,在EVOP營造的車聯網中智慧、高效、安全出行。人們不僅可以隨時瞭解車輛和電池的資訊,快速查詢身邊的充電設備、預約充電;也可以在EVOP的指導下獲得最佳行車路線和最佳能效使用方案;亦可以在EVOP的社交平臺中交流經驗、分享資訊、找到志同道合的朋友,享受 “大資料+互聯網”的時尚車生活。
本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計
※不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務
※Google地圖已可更新顯示潭子電動車充電站設置地點!!
※小三通物流營運型態?
※快速運回,大陸空運推薦?
一、簡介
iOS應用程序擴展是蘋果在iOS8推出的一個新特性,可以將自定義的功能和內容擴展到應用程序之外,在之後又經過不斷地優化和更新,已經成為開發中不可或缺的功能之一。擴展也是一個Target項目,它運行在主機應用程序上,可以與主機應用程序實現資源共享,和宿主應用程序的Target項目是彼此獨立的。系統提供的擴展有很多,Toady擴展就是其中之一,也被成為應用程序插件,它的作用是將今日發生的簡單消息展示在系統的插件界面上。Toady擴展模板名稱為Today Extension。圖1是創建Today擴展,圖2是擴展显示在插件界面上(可以通過點擊Edit來添加或者移除擴展)。
二、創建
按照上圖1的方式創建一個Today Extension的Target后,系統會默認幫我們生成一個TodayViewController控制器類、MainInterface.storyBoard故事板、plist序列化文件,文件結構圖如下:
上圖中紅色圈內和箭頭指向的配置就是系統通過MainInterface.storyBoard幫我們實現了一個基本的Toady插件UI布局,運行后可以直接显示在插件界面上。可是,有的時候開發者並不想使用系統的故事板來構建UI,系統支持自定義的,我們只需要修改plist配置即可。具體的配置是這樣的:
[1] 將NSExtensionMainStoryboard字段刪除;
[2] 添加NSExtensionPrincipalClass字段,修改value為控制器的類名。
[3] 在TodayViewController中的ViewDidLoad中設置preferredContentSize屬性大小,用來調整widget界面UI的尺寸。
配置如下圖所示:
//設置尺寸 self.preferredContentSize = CGSizeMake([UIScreen mainScreen].bounds.size.width, 300);
三、分析
TodayViewController類比較簡單,就是一個VC類,它實現了系統提供的一個擴展協議<NCWidgetProviding>,可以在協議方法中實現對擴展的更新和狀態監控。
協議如下,都是可選的,開發者根據需要進行重寫。
//協議 @protocol NCWidgetProviding <NSObject> @optional //當數據更新時調用的方法,系統會定期更新擴展 - (void)widgetPerformUpdateWithCompletionHandler:(void (^)(NCUpdateResult result))completionHandler; //監聽显示模式(寬鬆型、緊奏型)和尺寸的改變,其中寬鬆和緊湊表示的是展開和摺疊狀態, iOS10開始才能使用 - (void)widgetActiveDisplayModeDidChange:(NCWidgetDisplayMode)activeDisplayMode withMaximumSize:(CGSize)maxSize __API_AVAILABLE(ios(10.0)); //設置擴展UI邊距,注意:使用StoryBoard時,若要所見即所得,則這個方法中需要返回UIEdgeInsetsZero; (iOS10 and later 不會再被調用,棄用了) - (UIEdgeInsets)widgetMarginInsetsForProposedMarginInsets:(UIEdgeInsets)defaultMarginInsets __API_DEPRECATED("This method will not be called on widgets linked against iOS versions 10.0 and later.", ios(8.0, 10.0)); @end
//擴展,都是iOS10開始才能使用 @interface NSExtensionContext (NCWidgetAdditions) //設置widget摺疊或展開狀態 @property (nonatomic, assign) NCWidgetDisplayMode widgetLargestAvailableDisplayMode __API_AVAILABLE(ios(10.0)); //只讀,widget狀態 @property (nonatomic, assign, readonly) NCWidgetDisplayMode widgetActiveDisplayMode __API_AVAILABLE(ios(10.0)); //獲取widget不同狀態的尺寸 - (CGSize)widgetMaximumSizeForDisplayMode:(NCWidgetDisplayMode)displayMode __API_AVAILABLE(ios(10.0)); @end
四、交互
Today擴展是寄宿於主機應用程序上的, TodayViewController又是一個UIViewController類,系統支持Today擴展對UIViewController進行切換。也就是說,蘋果在考慮提供給開發者在對UIViewController中添加各種展示控件這種便利的同時,也相應的提供給開發者通過Today擴展的widget從主機應用程序激活並打開宿主應用程序的機會。不過這個操作必須通過設置並調起scheme來實現。步驟如下:
[1] 配置宿主應用程序的scheme;
[2] 使用擴展的openURL打開宿主應用程序。
交互如下:
//擴展通過scheme打開主宿主應用程序 [self.extensionContext openURL:[NSURL URLWithString:@"MainApp://"] completionHandler:nil];
五、數據
既然Today擴展能與宿主應用程序進行交互,那麼肯定就存在數據通信的問題了。擴展與宿主目錄應用程序位於不同的目錄結構中,默認情況下,擴展與宿主應用程序的數據並不共享,代碼也不能復用。例如在宿主目錄應用程序中可能有網絡請求、數據持久化存儲等結構框架,在擴展中不可以直接使用,擴展需要提供自己的網絡請求框架、數據持久化框架等。這些問題蘋果都提供了解決方法,可以通過創建靜態庫的方式實現代碼共享,通過APP Group和Scheme跳轉實現數據共享。這裏主要講一下數據共享。注意:擴展和宿主應用程序的素材文件也是互相獨立的,必須將擴展中的素材添加到擴展Target。
方式一:通過配置scheme跳轉來實現數據共享。可以將傳遞的數據配置到URL中,然後宿主應用程序通過AppDeleagte的代理方法application:openURL:options:獲取數據,不過這個數據傳遞只能是單方向的。
//打開主應用程序 -(void)openMainApp { //共享數據 NSString *schemeFormat = @"MainApp://action=openCarema?name=xiayuanquan"; [self.extensionContext openURL:[NSURL URLWithString:schemeFormat] completionHandler:nil]; }
-(BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options { //從URL獲取共享數據,截取數據 NSLog(@"---------url = %@---------",url); return YES; }
方式二:給擴展的Target和宿主應用程序的Target項目都開啟APP Group,兩者配置相同的appgroupIndentifier標識,分別生成後綴名為.entitlements文件。然後對於小數據推薦使用偏好進行雙向傳遞共享數據,如圖所示。
//共享數據 //使用偏好設置 NSUserDefaults *defalut = [[NSUserDefaults alloc] initWithSuiteName:@"group.xiayuanquan"]; [defalut setObject:@"xiayuanquan" forKey:@"name"];
//從偏好設置獲取共享數據 NSUserDefaults *defalut = [[NSUserDefaults alloc] initWithSuiteName:@"group.xiayuanquan"]; NSString *name1 = [defalut objectForKey:@"name"]; NSLog(@"1------------name1=%@",name1);
方式三:配置跟方式二一樣,不過雙向傳遞共享數據使用文件目錄來實現。
//共享數據 //方式二:使用共享目錄 NSFileManager *fileManager = [NSFileManager defaultManager]; NSURL *baseURL = [fileManager containerURLForSecurityApplicationGroupIdentifier:@"group.xiayuanquan"]; NSURL *filePath = [baseURL URLByAppendingPathComponent:@"file"]; NSData *data = [NSKeyedArchiver archivedDataWithRootObject:@"xiayuanquan" requiringSecureCoding:NO error:nil]; [data writeToURL:filePath atomically:YES];
//從共享目錄獲取共享數據 NSFileManager *fileManager = [NSFileManager defaultManager]; NSURL *baseURL = [fileManager containerURLForSecurityApplicationGroupIdentifier:@"group.xiayuanquan"]; NSURL *filePath = [baseURL URLByAppendingPathComponent:@"file"]; NSData *data = [NSData dataWithContentsOfURL:filePath]; NSLog(@"2------------data=%@",data);
六、適配
從iOS10開始,蘋果提供了NCWidgetDisplayMode展示模式,通過設置該模式來支持對widget進行摺疊和展開。在這裏,preferredContentSize就用到了。這個是用來設置widget的尺寸的。蘋果對widget的尺寸有自己的標準,width為maxSize.width,height取值範圍[110, maxSize.height]。這個maxSize可以在擴展協議<NCWidgetProviding>的協議方法也即widgetActiveDisplayModeDidChange:withMaximumSize中獲取:,可以發現每一種機型maxSize不一樣。
// 6s模擬器下: // NCWidgetDisplayModeCompact模式下:{359.000000, 110.000000} // NCWidgetDisplayModeExpanded模式下:{359.000000, 528.000000} // 8 plus模擬器下: // NCWidgetDisplayModeCompact模式下:{304.000000, 110.000000} // NCWidgetDisplayModeExpanded模式下:{304.000000, 616.000000}
摺疊狀態:widget的高為110,此時設置preferredContentSize無效;
展開狀態:widget的高為開發者設置的preferredContentSize.height,但是如果preferredContentSize.height>maxSize.height,此時取值為maxSize.height。
適配iOS10,默認支持展開,設置如下:
//設置widget默認為可以展開,此時處於摺疊狀態 #ifdef __IPHONE_10_0 //適配iOS10 self.extensionContext.widgetLargestAvailableDisplayMode = NCWidgetDisplayModeExpanded; #endif
七、範例
【去掉MainInterface.storyBoard,採用純代碼實現】
1、宿主應用程序AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. //存儲共享數據 //方式二:使用偏好設置 NSUserDefaults *defalut = [[NSUserDefaults alloc] initWithSuiteName:@"group.xiayuanquan"]; [defalut setObject:@"xiayuanquan" forKey:@"name"]; //存儲共享數據 //方式三:使用共享目錄 NSFileManager *fileManager = [NSFileManager defaultManager]; NSURL *baseURL = [fileManager containerURLForSecurityApplicationGroupIdentifier:@"group.xiayuanquan"]; NSURL *filePath = [baseURL URLByAppendingPathComponent:@"file"]; NSData *data = [NSKeyedArchiver archivedDataWithRootObject:@"xiayuanquan" requiringSecureCoding:NO error:nil]; [data writeToURL:filePath atomically:YES]; return YES; } -(BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options { //方式一:從URL獲取共享數據,例如參數 NSLog(@"---------url = %@---------",url); return YES; }
2、Widget擴展TodayViewController
// // TodayViewController.m // TodayExtension // Created by 夏遠全 on 2019/11/19. // #import "TodayViewController.h" #import <NotificationCenter/NotificationCenter.h> @interface TodayViewController () <NCWidgetProviding> @end @implementation TodayViewController - (void)viewDidLoad { [super viewDidLoad]; [self config]; [self createUI]; [self fecthData]; } //配置 -(void)config { self.view.backgroundColor = [UIColor lightGrayColor]; //widget背景色為灰色 self.preferredContentSize = CGSizeMake([UIScreen mainScreen].bounds.size.width, 300); //widget尺寸大小, 寬度實際取maxSize,width,高度[110, maxSize.height] //設置widget默認為可以展開,此時處於摺疊狀態 #ifdef __IPHONE_10_0 //適配iOS10 self.extensionContext.widgetLargestAvailableDisplayMode = NCWidgetDisplayModeExpanded; #endif } //創建UI -(void)createUI { CGFloat width = self.view.frame.size.width; CGFloat btnWidth = 100; UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake((width-btnWidth)/2, 0, btnWidth, 40)]; button.backgroundColor = [UIColor greenColor]; [button setTitle:@"OpenAPP" forState:UIControlStateNormal]; [button setTitleColor:[UIColor redColor] forState:UIControlStateNormal]; [button addTarget:self action:@selector(openMainApp) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:button]; } //打開主應用程序 -(void)openMainApp { //傳遞共享數據 //方式一:參數傳遞 NSString *schemeFormat = @"MainApp://action=openCarema?name=xiayuanquan"; [self.extensionContext openURL:[NSURL URLWithString:schemeFormat] completionHandler:nil]; } //獲取共享數據 -(void)fecthData { //方式二:從偏好設置獲取共享數據 NSUserDefaults *defalut = [[NSUserDefaults alloc] initWithSuiteName:@"group.xiayuanquan"]; NSString *name1 = [defalut objectForKey:@"name"]; NSLog(@"1------------name1=%@",name1); //方式三:從共享目錄獲取共享數據 NSFileManager *fileManager = [NSFileManager defaultManager]; NSURL *baseURL = [fileManager containerURLForSecurityApplicationGroupIdentifier:@"group.xiayuanquan"]; NSURL *filePath = [baseURL URLByAppendingPathComponent:@"file"]; NSData *data = [NSData dataWithContentsOfURL:filePath]; NSLog(@"2------------data=%@",data); } //當數據更新時調用的方法,系統會定期更新擴展 - (void)widgetPerformUpdateWithCompletionHandler:(void (^)(NCUpdateResult))completionHandler { //獲取共享的數據,根據判斷回調對應的block //NCUpdateResultNewData, //NCUpdateResultNoData, //NCUpdateResultFailed completionHandler(NCUpdateResultNoData); } //監聽显示模式(寬鬆型、緊奏型)和尺寸的改變 //NCWidgetDisplayModeCompact : 摺疊 //NCWidgetDisplayModeExpanded : 展開 - (void)widgetActiveDisplayModeDidChange:(NCWidgetDisplayMode)activeDisplayMode withMaximumSize:(CGSize)maxSize { //maxSize: //雖說是最大的Size,但蘋果還是把Widget的高度範圍限制在了[110 ~ maxSize]之間 //如果設置高度小於110,那麼default = 110; //如果設置高度大於開發者設置的preferredContentSize.Heiget,那麼default = maxSize; //摺疊狀態下,蘋果將高度固定為110,這個時候設置preferredContentSize屬性無效。 NSLog(@"width = %lf-------height = %lf",maxSize.width,maxSize.height); //可以更改狀態 if (activeDisplayMode == NCWidgetDisplayModeExpanded) { self.preferredContentSize = CGSizeMake([UIScreen mainScreen].bounds.size.width, 300); } else{ self.preferredContentSize = CGSizeMake([UIScreen mainScreen].bounds.size.width, 100); } } //設置擴展UI邊距,注意:使用StoryBoard時,若要所見即所得,則這個方法中需要返回UIEdgeInsetsZero; (iOS10 and later 不會再被調用) //- (UIEdgeInsets)widgetMarginInsetsForProposedMarginInsets:(UIEdgeInsets)defaultMarginInsets { // return UIEdgeInsetsZero; //} @end
3、打印和gif
2019-11-20 16:22:31.074596+0800 TodayExtension[29668:1132736] 1------------name1=xiayuanquan 2019-11-20 16:22:31.234435+0800 TodayExtension[29668:1132736] 2------------data={length = 149, bytes = 0x62706c69 73743030 d4010203 04050607 ... 00000000 00000068 } 2019-11-20 16:22:31.234970+0800 TodayExtension[29668:1132736] maxSize.width = 359.000000-------maxSize.height = 110.000000 //摺疊 2019-11-20 16:22:38.117764+0800 TodayExtension[29668:1132736] maxSize.width = 359.000000-------maxSize.height = 528.000000 //展開
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能
※評比前十大台北網頁設計、台北網站設計公司知名案例作品心得分享
※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選
※台灣海運大陸貨務運送流程
※兩岸物流進出口一站式服務
定義:在golang裡頭select的功能與epoll(nginx)/poll/select的功能類似,都是堅挺IO操作,當IO操作發生的時候,觸發相應的動作。
在Go的語言規範中,select中的case的執行順序是隨機的,當有多個case都可以運行,select會隨機公平地選出一個執行,其他的便不會執行:
1 package main 2 3 import "fmt" 4 5 func main() { 6 ch := make (chan int, 1) 7 8 ch<-1 9 select { 10 case <-ch: 11 fmt.Println("隨機一") 12 case <-ch: 13 fmt.Println("隨機二n") 14 } 15 }
輸出內容為隨機一二里面的任意一個。
case後面必須是channel操作,否則報錯;default子句總是可運行的,所以沒有default的select才會阻塞等待事件 ;沒有運行的case,那麼將會阻塞事件發生報錯(死鎖)。
1 package main 2 3 import ( 4 "fmt" 5 "time" 6 ) 7 8 func main() { 9 timeout := make (chan bool, 1) 10 go func() { 11 time.Sleep(1*time.Second) // 休眠1s,如果超過1s還沒I操作則認為超時,通知select已經超時啦~ 12 timeout <- true 13 }() 14 ch := make (chan int) 15 select { 16 case <- ch: 17 case <- timeout: 18 fmt.Println("超時啦!") 19 } 20 }
也可以這麼寫:
1 package main 2 3 import ( 4 "fmt" 5 "time" 6 ) 7 8 func main() { 9 ch := make (chan int) 10 select { 11 case <-ch: 12 case <-time.After(time.Second * 1): // 利用time來實現,After代表多少時間后執行輸出東西 13 fmt.Println("超時啦!") 14 } 15 }
判斷channel是否阻塞(或者說channel是否已經滿了)
1 package main 2 3 import ( 4 "fmt" 5 ) 6 7 func main() { 8 ch := make (chan int, 1) // 注意這裏給的容量是1 9 ch <- 1 10 select { 11 case ch <- 2: 12 default: 13 fmt.Println("通道channel已經滿啦,塞不下東西了!") 14 } 15 }
退出機制
1 package main 2 3 import ( 4 "fmt" 5 "time" 6 ) 7 8 func main() { 9 i := 0 10 ch := make(chan string, 0) 11 defer func() { 12 close(ch) 13 }() 14 15 go func() { 16 DONE: 17 for { 18 time.Sleep(1*time.Second) 19 fmt.Println(time.Now().Unix()) 20 i++ 21 22 select { 23 case m := <-ch: 24 println(m) 25 break DONE // 跳出 select 和 for 循環 26 default: 27 } 28 } 29 }() 30 31 time.Sleep(time.Second * 4) 32 ch<-"stop" 33 }
select-case中的chan操作編譯成了if-else。如:
1 select { 2 case v = <-c: 3 ...foo 4 default: 5 ...bar 6 }
會被編譯為:
1 if selectnbrecv(&v, c) { 2 ...foo 3 } else { 4 ...bar 5 }
類似地
1 select { 2 case v, ok = <-c: 3 ... foo 4 default: 5 ... bar 6 }
會被編譯為:
1 if c != nil && selectnbrecv2(&v, &ok, c) { 2 ... foo 3 } else { 4 ... bar 5 }
selectnbrecv函數只是簡單地調用runtime.chanrecv函數,不過是設置了一個參數,告訴當runtime.chanrecv函數,當不能完成操作時不要阻塞,而是返回失敗。也就是說,所有的select操作其實都僅僅是被換成了if-else判斷,底層調用的不阻塞的通道操作函數。
在Go的語言規範中,select中的case的執行順序是隨機的,那麼,如何實現隨機呢?
select和case關鍵字使用了下面的結構體:
1 struct Scase 2 { 3 SudoG sg; // must be first member (cast to Scase) 4 Hchan* chan; // chan 5 byte* pc; // return pc 6 uint16 kind; 7 uint16 so; // vararg of selected bool 8 bool* receivedp; // pointer to received bool (recv2) 9 };
1 struct Select 2 { 3 uint16 tcase; // 總的scase[]數量 4 uint16 ncase; // 當前填充了的scase[]數量 5 uint16* pollorder; // case的poll次序 6 Hchan** lockorder; // channel的鎖住的次序 7 Scase scase[1]; // 每個case會在結構體里有一個Scase,順序是按出現的次序 8 };
每個select都對應一個Select結構體。在Select數據結構中有個Scase數組,記錄下了每一個case,而Scase中包含了Hchan。然後pollorder數組將元素隨機排列,這樣就可以將Scase亂序了。
select不注意也會發生死鎖,分兩種情況:
如果沒有數據需要發送,select中又存在接收通道數據的語句,那麼將發送死鎖
1 package main 2 func main() { 3 ch := make(chan string) 4 select { 5 case <-ch: 6 } 7 }
預防的話加default。
空select,也會引起死鎖。
1 package main 2 3 func main() { 4 select {} 5 }
select只能應用於channel的操作,既可以用於channel的數據接收,也可以用於channel的數據發送。如果select的多個分支都滿足條件,則會隨機的選取其中一個滿足條件的分支, 如規範中所述:
If multiple cases can proceed, a uniform pseudo-random choice is made to decide which single communication will execute.
`case`語句的表達式可以為一個變量或者兩個變量賦值。有default語句。
31 package main 32 import "time" 33 import "fmt" 35 func main() { 36 c1 := make(chan string) 37 c2 := make(chan string) 38 go func() { 39 time.Sleep(time.Second * 1) 40 c1 <- "one" 41 }() 42 go func() { 43 time.Sleep(time.Second * 2) 44 c2 <- "two" 45 }() 46 for i := 0; i < 2; i++ { 47 select { 48 case msg1 := <-c1: 49 fmt.Println("received", msg1)
50 case msg2 := <-c2: 51 fmt.Println("received", msg2)
52 } 53 }
switch可以為各種類型進行分支操作, 設置可以為接口類型進行分支判斷(通過i.(type))。switch 分支是順序執行的,這和select不同。
1 package main 2 import "fmt" 3 import "time" 4 5 func main() { 6 i := 2 7 fmt.Print("Write ", i, " as ") 8 switch i { 9 case 1: 10 fmt.Println("one") 11 case 2: 12 fmt.Println("two") 13 case 3: 14 fmt.Println("three") 15 } 16 switch time.Now().Weekday() { 17 case time.Saturday, time.Sunday: 18 fmt.Println("It's the weekend") 19 default: 20 fmt.Println("It's a weekday") 21 } 22 t := time.Now() 23 switch { 24 case t.Hour() < 12: 25 fmt.Println("It's before noon") 26 default: 27 fmt.Println("It's after noon") 28 } 29 whatAmI := func(i interface{}) { 30 switch t := i.(type) { 31 case bool: 32 fmt.Println("I'm a bool") 33 case int: 34 fmt.Println("I'm an int") 35 default: 36 fmt.Printf("Don't know type %T\n", t) 37 } 38 } 39 whatAmI(true) 40 whatAmI(1) 41 whatAmI("hey") 42 }
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計
※不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務
※Google地圖已可更新顯示潭子電動車充電站設置地點!!
※小三通物流營運型態?
※快速運回,大陸空運推薦?
摘錄自2018年10月2日公視報導
全球第一列標榜零排放的氫動力火車,日前在德國正式上路。它所使用的燃料電池,把氫氣和氧氣結合產生電力,目前時速可達140公里。這是德國逐步淘汰柴油動力火車的重要里程碑,歐洲其他國家也紛紛表達高度興趣。
披著亮藍色外衣,造型簡單大方的火車,緩緩駛進德國北部的布雷默沃德車站,它就是全球第一列氫動力列車,由法國鐵路製造商阿爾斯通負責打造。
阿爾斯通經理施朗克說:「這部列車是(全球)第一列完全零碳排,而且車頂沒有電纜線的火車,它是電動車。」
催生氫動力火車的阿爾斯通計畫在2021年之前,在德國下薩克森邦再推出14列同款列車,德國其他城市和地區也可能起而仿效。此外包括英國荷蘭丹麥等國都對零污染,低噪音的氫動力火車表示濃厚興趣。
本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計
※不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務
※Google地圖已可更新顯示潭子電動車充電站設置地點!!
※小三通物流營運型態?
※快速運回,大陸空運推薦?