Coding Style:
2015年2月12日 星期四
2015年1月21日 星期三
偵測 back button 被按下時(還沒整理完@@)
整理了一些我在網路上找到關於偵測返回鍵被按下的方法,以及每個方法的盲點,的 Bug。
這兩個方法語法上最直覺,但不知道為什麼當 push 進入這個 view 的時候,這兩個方法也會被呼叫,所以裡面還要再加一個判別式 if (!parent)。但是這個方法沒辦法辨別是按下返回鍵還是使用 unwind segue。
這兩個方法語法上最直覺,但不知道為什麼當 push 進入這個 view 的時候,這兩個方法也會被呼叫,所以裡面還要再加一個判別式 if (!parent)。但是這個方法沒辦法辨別是按下返回鍵還是使用 unwind segue。
2014年12月21日 星期日
Protocol 協定
介紹
在 Objective-C 裡,每一個類別是單繼承的,一個類別只會有一個父類別,而這個父類別也只會有一個父類別,這樣一直往上追朔直到根類別 NSObject,但如果你需要呼叫一個不在這整個繼承鏈裡的方法,protocol 協定就是一個可以幫你解決這個問題的方法(註一)。製作 protocol
解說:
- protocol 本身不會實作,只會宣告 method,實作的部分由使用這個 protocol 的 class 來實作。
- 在Objective-C 2.0 之後,加了 @required 跟 @optional 的語法,你可以設定某些method是optional,也就是這些 method 沒有一定要實作出來。預設是 @required,要注意的是@required跟 @optional 這兩個語法的影響範圍,是從它以下所有的 method 都會被影響,直到另一個 directive 或是 @end 為止。
- 就像 class 可以繼承另一個 class 裏所有的 method 一樣,protocol 也可以繼承自另一個 protocol,大多數的 protocol 都是繼承自 <NSObject> 這個根 protocol(註二),但我們並不需要實作 <NSObject> 裡的 method,因為不管是我們自定或是系統提供的 class 都會繼承自 NSObject 這個 class,自然也就有 <NSObject> 的實作了(註三)。
使用 protocol
方法如下,如果要一次使用多個 protocol 用逗號分開就可以了:定義變數
protocol 也可以當作一種型別來定義變數。這段程式的意思是:delegate 這個變數,它可以是任意資料型態,但一定要遵循 protocolName 這個 protocol,也就是說,delegate 的實體必需要實作 protocolName 裡@required所有的 method。
這種用 @protocol 來定義方法的稱做 formal protocol,從名字看大概猜得出來一定也有叫做 informal protocol 的東西,不過這個會在介紹 category 的時候再做說明。
註一:另一種對於 protocol 使用的說法:對於繼承自不同父 class 的 class 來說,如果需要有共同的方法名稱,就需要使用 Protocol。我還沒完全搞清楚@@
註二:每次要建立新的 protocol 時,Xcode都會自訂幫我們繼承 <NSObject>,但我發現這個可有可無,我把 <NSObject> 刪掉也沒有出現編譯錯誤,我現在還不知道什麼時候要繼承 <NSObject> 什麼時候不用。
註三:這句其實我沒有完全看懂,因為我沒有看到哪裡有繼承 NSObject class 我也不懂為什麼他說繼承了 NSObject class,
資料整理自:
Objective-C: Protocols
http://shenfive.pixnet.net/blog/post/49325290-protocol-語法
Protocol 協定的使用方式 Furnace iOS 程式設計中文學習網站
http://iosdevelopersnote.blogspot.tw/2010/11/protocol-delegate.html
蘋果官方文件:Programming with Objective-C:Working with Protocols
2014年12月13日 星期六
NSDate 相關的 method
下面這些是關於NSDate所有的整理自蘋果官方的文件,推薦看網頁版,網頁版的現在設計得互動性非常高,一開始會把每個method列出來,如果想要細看哪個method的話,再點下去所有的細節就會通通展開來,包括:
1定義(Declaration)
2參數(Parameters)
3回傳值(Return Value)
4Import Statement
5可使用版本(Availability)
6探討(Discussion)
7相關(See Also)
另外也可以選擇要顯示的語言,Objective-C還是Switf或是兩個都顯示。
關於NSDate背後的架構(是這樣說嗎!?找不到一個適當的詞@@)可以去看官方文件,因為我自己也還沒有完全看懂,所以就不在這裡做翻譯了Orz
大部份的method都可以望文生義,如果有不懂得再去看官方文件就可以了,我這裡只是整理了所有的mehtod,讓我們可以看得更一目了然。前半段是我目前最常用的method。
確實照著文件的說明實現了,可是我的問題是這可以幹嘛??我現在還不知道這個函數存在的意義,如果我以後知道了,我會在這裡更新。2014/12/14
後面這幾個是我比較不常用的
蘋果官方文件:NSDate Class Reference
NSDate Manipulation Made Easy in iOS 8
1定義(Declaration)
2參數(Parameters)
3回傳值(Return Value)
4Import Statement
5可使用版本(Availability)
6探討(Discussion)
7相關(See Also)
另外也可以選擇要顯示的語言,Objective-C還是Switf或是兩個都顯示。
關於NSDate背後的架構(是這樣說嗎!?找不到一個適當的詞@@)可以去看官方文件,因為我自己也還沒有完全看懂,所以就不在這裡做翻譯了Orz
大部份的method都可以望文生義,如果有不懂得再去看官方文件就可以了,我這裡只是整理了所有的mehtod,讓我們可以看得更一目了然。前半段是我目前最常用的method。
Creating and Initializing Date Objects
Comparing Dates
Getting Time Intervals
Adding a Time Interval
Getting Temporal Boundaries
+ dateWithTimeIntervalSinceReferenceDate:
+ dateWithTimeIntervalSince1970:
- initWithTimeIntervalSinceReferenceDate:
- initWithTimeIntervalSince1970:
+ timeIntervalSinceReferenceDate
timeIntervalSinceReferenceDate
timeIntervalSince1970
其中這幾個函數我還不是很搞得清楚到底是做什麼用途的,以initWithTimeIntervalSinceReferenceDate:為例,官方文件是這樣說明的:Returns an NSDate object initialized relative the first instant of 1 January 2001, GMT by a given number of seconds.,翻成中文就是:會得到一個以西元兩千年一月一號零分零秒為開始,(由使用者輸入)往後推幾秒的時間點,我實際使用了一下,如果輸入下列這行程式NSDate *date = [[NSDate alloc] initWithTimeIntervalSinceReferenceDate:10];
顯示結果如下:後面這幾個是我比較不常用的
Representing Dates as Strings
Constants
Notification
蘋果官方文件:NSDate Class Reference
NSDate Manipulation Made Easy in iOS 8
2014年12月6日 星期六
NSDate, NSTimeInterval, NSCalendar, NSDateComponents, NSDateFormatter基本教學
下面是一些跟時間相關的class,以及其簡單的使用方法,而每個class背後的原理,我會另外分幾篇網誌來寫。
下面這段程式是讀取現在時間的程式碼。
下面是NSDateFormatter的使用方式。
設定NSDateFormatter也可以使用Xcode提供的幾種制式化格式
註一:我現在還不完全清楚它的原理,不知道是「會」根據當地時區作轉換,還是「需要」知道當地的時區來作轉換。2014/12/7
註二:我不知道是不是全部,一時沒時間去查,但我要用的話幾乎都在那篇裡找得到。2014/12/7
註三:我還搞不清楚差在哪,我查到後這裡會更新。2014/12/7
NSDate
NSDate儲存的是世界標準時間(UTC),是絕對時間,當要輸出時間的時候會(註一)根據當地時區轉換成當地的時間。下面這段程式是讀取現在時間的程式碼。
NSDateFormatter
說到NSDateFormatter,就不得不提關於NSDateFormatter 的二三事這篇網誌,這篇網誌把很多(註二)參數都整理出來了。下面是NSDateFormatter的使用方式。
設定NSDateFormatter也可以使用Xcode提供的幾種制式化格式
NSTimeInterval
特別要注意NSTimeInterval的資料型態是double。
NSCalendar, NSDateComponents
下面三種方法得出來的結果都一樣,只是取用的方式不同。(註三)註一:我現在還不完全清楚它的原理,不知道是「會」根據當地時區作轉換,還是「需要」知道當地的時區來作轉換。2014/12/7
註二:我不知道是不是全部,一時沒時間去查,但我要用的話幾乎都在那篇裡找得到。2014/12/7
註三:我還搞不清楚差在哪,我查到後這裡會更新。2014/12/7
2014年10月30日 星期四
int vs. NSInteger vs. NSNumber
NSInteger vs. int
NSInteger is typedef'ed based on the target architecture. In other word, it's an architecture-safe (64 vs 32 bit) type to support different platforms and implementations of C. Targeting a 32-bit CPU and OS it's 32-bits wide, on a 64-bit OS it's 64-bits wide.What follows is how NSInteger is defined in NSObjCRuntime.h file :
And this is what Apple say in Foundation Data Types Reference :
When building 32-bit applications, NSInteger is a 32-bit integer. A 64-bit application treats NSInteger as a 64-bit integer.
Simply, the NSInteger typedef does a step for you: if the architecture is 32-bit, it uses int, if it is 64-bit, it uses long. Using NSInteger, you don't need to worry about the architecture that the program is running on.
Apple recommends that you use NSInteger over normal types anyway, I would assume for portability!
結論:除非你有特定要int或是long,要不然就建議用NSInteger,這樣就不必去煩惱使用者用的是32-bit還是64-bit的iDevice。
更深入探討
Why use
int at all?
Apple uses
int because for a loop control variable (which is only used to control the loop iterations) int datatype is fine, both in datatype size and in the values it can hold for your loop. No need for platform dependent datatype here. For a loop control variable even a 16-bit int will do most of the time.
Apple uses
NSInteger for a function return value or for a function argument because in this case datatype [size] matters, because what you are doing with a function is communicating/passing data with other programs or with other pieces of code; see the answer to When should I be using NSInteger vs int?in your question itself...Apple use NSInteger (or NSUInteger) when passing a value as an argument to a function or returning a value from a function.
延伸閱讀:64-Bit Transition Guide for Cocoa Touch
NSNumber
NSNumber is an Objective-C class, a subclass of NSValue to be specific. Where a NSInteger or int will fit in a register, a NSNumber is an object that can hold/encapsulate any scalar type (IIRC - I don't use NSNumber if I can help it. Way too slow.), It can be used when you need an NSObject that holds a scalar value.You can create an NSNumber object from a signed or unsigned char, short int, int, long int, long long int, float, double or BOOL.
One of the primary distinctions is that you can use NSNumber in collections, such as NSArray or NSSet, where an object is required. For example, if you need to add a float into an NSArray, you would first need to create an NSNumber object from the float:
1 2 3 4 | float percentage = 40.5; ... // Create NSNumber object, which can now be inserted into an NSArray NSNumber *percentageObject = [NSNumber numberWithFloat:percentage]; |
Cocoa提供了NSNumber類來包裝(即以物件object形式實現)基本數據類型。
例如以下創建方法:
+ (NSNumber*)numberWithChar: (char)value; + (NSNumber*)numberWithInt: (int)value; + (NSNumber*)numberWithFloat: (float)value; + (NSNumber*)numberWithBool: (BOOL) value;例:NSNumber *n = [NSNumber numberWithInt:5];
將基本類型數據封裝到NSNumber中後,就可以通過下面的實例方法重新獲取它:
- (char)charValue; - (int)intValue; - (float)floatValue; - (BOOL)boolValue; - (NSString*)stringValue;例:int i = [n intValue];
資料來源:
http://www.quora.com/What-is-the-difference-between-NSInteger-NSNumber-int-and-all-the-different-ways-to-represent-an-integer
http://iosdevelopertips.com/cocoa/nsnumber-and-nsinteger.html
http://stackoverflow.com/a/5870916/3295047
http://stackoverflow.com/a/4445224/3295047
http://www.wuleilei.com/blog/335
2014年10月26日 星期日
Local Notification介紹
基本設定
請求使用者運允許發送通知
從iOS 8開始,如果打完上面的程式就執行會出現類似下面這樣的錯誤碼
要把下面這段程式加上去,請求使用者允許App發送通知,我們的Local Notification才能正常運作,在iOS 8之前當然也要使用者的同意,不過可能以前是系統自動幫我們問吧,不過就像我常講的,其實我們不太需要知道以前是怎麼樣,反正現在這段程式是一定要寫就對了!
自訂特定的時間
一般fireDate的設定我們都是使用我們既有的資料或是稍微經過dateByAddingTimeInterval之類的處理,如果要完全自訂一個特定的時間的話,可以參考下面的程式碼。你會注意要我只設定了小時跟分鐘,如果想要設定通知是每天固定發出,只要設定小時跟分鐘就可以了。
alertAction
這段程式有個小問題,它可以執行,但我必須要自己去「設定」那裏把alert sytle從Banners改成Alerts,notification才會顯示成alert的形式,我目前還不知道問題出在哪裡,知道的人拜託告訴我~
icon Badge
注意第三行程式,我們也可以讀取目前的IconBadgeNumber做累加的動作
重複
使用自訂的聲音
我沒想到要使用自訂的聲音竟然這麼簡單,只要將想要播放的音檔匯入project中,再如下面的程式碼打就可以了,不過有兩點需要注意:
1音檔的長度不可以超過三十秒,要不然聲音會播不出來,我在Documentation裡沒看到這項規定,是在stackoverflow裡看到這篇回答才知道的,但我確定有這項限制,因為我之前就是卡關在這裡Orz
2音檔只有一些特定的格式可以
在通知中另外夾帶參數(一般是供其它地方的程式辨識用)
取消Local Notification
取消指定的通知
其實沒有一定要用下面的方式來尋找指定的Local Notification,也可以用其他屬性像是fireDate、alertBody...等,只要你能找到你要的特定通知就可以了。另外,雖然可以抓到自己想要的特定通知,但我試過並不能再修改其屬性。
取消全部
按下發送出來的通知後怎麼處理
當App已經沒有在運作
當App已經還在運作(可能在背景或是或是正在使用)
更深入的探討
用Local Notification實現Alarm
要實作一個Alarm需要做到下面這幾點:
1播放音樂
2在背景執行
3定時
其實上面三點是一句話拆開來講:「在一段時間後在背景播放音樂」
我查了很多資料,發現目前Local Notification是唯一可以完全達到上面要求的方法,但那只是從技術面來看,實際使用的話會遇到兩個問題:
1.1Local Notification的聲音最長只能到三十秒,如果要做的一個鬧鐘的程式,我們絕對不可能讓他只響三十秒,當然我們可以一連排程好幾的Local Notification,可是這樣使用者打開他的iPhone的時候就是看到四五個Notification,這樣的使用者體驗非常差。
1.2我目前想到比較好的方法是:設一連串的Local Notification,只有第一個有設alertBody,後面幾個都設nil,因為我發現如果alertBody設nil,iDevice不會顯示任何東西,但音樂還是會播放。
1.3不過後來經過測試,這樣的UX爛炸了,因為一般我要用自訂的聲音,音檔一般都會像是一首歌之類的,用上面的方法,這首歌每次只會播三十秒就重新播放,越聽只讓我越煩燥而已。
2沒辦法像內建的鬧鐘可以有按鈕讓鬧鐘稍後再播放
我去網路上問,不過看起來應該是無解了Orz
請求使用者運允許發送通知
從iOS 8開始,如果打完上面的程式就執行會出現類似下面這樣的錯誤碼
要把下面這段程式加上去,請求使用者允許App發送通知,我們的Local Notification才能正常運作,在iOS 8之前當然也要使用者的同意,不過可能以前是系統自動幫我們問吧,不過就像我常講的,其實我們不太需要知道以前是怎麼樣,反正現在這段程式是一定要寫就對了!
自訂特定的時間
一般fireDate的設定我們都是使用我們既有的資料或是稍微經過dateByAddingTimeInterval之類的處理,如果要完全自訂一個特定的時間的話,可以參考下面的程式碼。你會注意要我只設定了小時跟分鐘,如果想要設定通知是每天固定發出,只要設定小時跟分鐘就可以了。
alertAction
這段程式有個小問題,它可以執行,但我必須要自己去「設定」那裏把alert sytle從Banners改成Alerts,notification才會顯示成alert的形式,我目前還不知道問題出在哪裡,知道的人拜託告訴我~
icon Badge
注意第三行程式,我們也可以讀取目前的IconBadgeNumber做累加的動作
重複
使用自訂的聲音
我沒想到要使用自訂的聲音竟然這麼簡單,只要將想要播放的音檔匯入project中,再如下面的程式碼打就可以了,不過有兩點需要注意:
1音檔的長度不可以超過三十秒,要不然聲音會播不出來,我在Documentation裡沒看到這項規定,是在stackoverflow裡看到這篇回答才知道的,但我確定有這項限制,因為我之前就是卡關在這裡Orz
2音檔只有一些特定的格式可以
在通知中另外夾帶參數(一般是供其它地方的程式辨識用)
取消Local Notification
取消指定的通知
其實沒有一定要用下面的方式來尋找指定的Local Notification,也可以用其他屬性像是fireDate、alertBody...等,只要你能找到你要的特定通知就可以了。另外,雖然可以抓到自己想要的特定通知,但我試過並不能再修改其屬性。
取消全部
按下發送出來的通知後怎麼處理
當App已經沒有在運作
當App已經還在運作(可能在背景或是或是正在使用)
更深入的探討
https://www.facebook.com/groups/iostw/permalink/906779296016087/
https://www.facebook.com/groups/iostw/permalink/934380229922660/
https://www.facebook.com/photo.php?fbid=10202759629864986&set=gm.967383696622313&type=1
用Local Notification實現Alarm
要實作一個Alarm需要做到下面這幾點:
1播放音樂
2在背景執行
3定時
其實上面三點是一句話拆開來講:「在一段時間後在背景播放音樂」
我查了很多資料,發現目前Local Notification是唯一可以完全達到上面要求的方法,但那只是從技術面來看,實際使用的話會遇到兩個問題:
1.1Local Notification的聲音最長只能到三十秒,如果要做的一個鬧鐘的程式,我們絕對不可能讓他只響三十秒,當然我們可以一連排程好幾的Local Notification,可是這樣使用者打開他的iPhone的時候就是看到四五個Notification,這樣的使用者體驗非常差。
1.2我目前想到比較好的方法是:設一連串的Local Notification,只有第一個有設alertBody,後面幾個都設nil,因為我發現如果alertBody設nil,iDevice不會顯示任何東西,但音樂還是會播放。
1.3不過後來經過測試,這樣的UX爛炸了,因為一般我要用自訂的聲音,音檔一般都會像是一首歌之類的,用上面的方法,這首歌每次只會播三十秒就重新播放,越聽只讓我越煩燥而已。
2沒辦法像內建的鬧鐘可以有按鈕讓鬧鐘稍後再播放
我去網路上問,不過看起來應該是無解了Orz
2014年10月16日 星期四
atomic vs. nonatomic
nonatomic :
atomic(default) : 我目前有找到幾種解釋,因為還沒整理完,所以先都貼上來。
整理來源:
http://stackoverflow.com/a/10753201/3295047
http://stackoverflow.com/questions/9162926/ios-property-declaration-clarification
http://rypress.com/tutorials/objective-c/properties.html
- does not enforce thread safety on the property, mainly for use when only one thread shall be used throughout a program.
atomic(default) : 我目前有找到幾種解釋,因為還沒整理完,所以先都貼上來。
- enforces thread safety on the property, mainly for use when multiple threads shall be used throughout a program
- More precisely, tomic properties do not ensure thread-safety; rather it ensures atomicity. If thread A and thread B are both writing, atomic ensures that the outcome will be a whole value, meaning either one or the other. Which one is undefined. Writing thread-safe code is not as simple as using atomic properties. See the "Synchronization" section of the Threading Programming Guide
- atomic是Objc使用的一種線程保護技術,基本上來講,是防止在寫未完成的時候被另外一個線程讀取,造成數據錯誤。而這種機制是耗費系統資源的,所以在iPhone這種小型設備上,如果沒有使用多線程間的通訊編程,那麼 nonatomic 是一個非常好的選擇。
- Atomicity has to do with how properties behave in a threaded environment. When you have more than one thread, it’s possible for the setter and the getter to be called at the same time. This means that the getter/setter can be interrupted by another operation, possibly resulting in corrupted data. Atomic properties lock the underlying object to prevent this from happening, guaranteeing that the get or set operation is working with a complete value. However, it’s important to understand that this is only one aspect of thread-safety—using atomic properties does not necessarily mean that your code is thread-safe.
整理來源:
http://stackoverflow.com/a/10753201/3295047
http://stackoverflow.com/questions/9162926/ios-property-declaration-clarification
http://rypress.com/tutorials/objective-c/properties.html
2014年10月9日 星期四
@property 介紹
@property是在Objective-C 2.0(2006年)新加入的功能,目的是要簡化一個實體變數(instance variable, 簡稱ivar)設定的過程。
在沒有@property功能之前,要自己宣告setter跟getter。
記憶體管理相關:
多執行緒相關:對初學者來說,這部分比較難懂,我後面打的解釋是結果論,如果想要知道兩個屬性背後實際上是怎麼回事可以看這篇atomic vs. nonatomic
setter/getter相關(accessors):
原本是在@interface的程式
在@implementation的程式從
2012年Objective-C加入了不少新功能,@synthesize變成預設值,現在有沒有寫@synthesize的差別只在於你取用變數的方式:
有寫@synthesize
例如我們自訂setter:
不過在高見龍的部落格裡有提到點語法的一個小細節,有可能造成無窮回圈:
整理來源:
http://stackoverflow.com/questions/9162926/ios-property-declaration-clarification
http://pydoing.blogspot.tw/2012/08/objc-property-and-synthesize.html
http://shenfive.pixnet.net/blog/post/48054812-@property-
http://blog.eddie.com.tw/2010/12/08/property-and-synthesize/
在沒有@property功能之前,要自己宣告setter跟getter。
各種屬性介紹
讀寫相關:- readwrite(default)
- readonly
記憶體管理相關:
- Automatic Reference Counting(ARC):這部分對初學者來說比較難懂,簡單講,絕大部分時我們會用的是strong,weak是一些比較進階的功能才會用到,所以初學者每次在設定的時候用strong就可以了。如果想要知道背後詳細的原理及解釋可以看我另外寫的這篇Automatic Reference Counting(ARC)。
- strong:
- weak:
- Manual Reference Counting(MRC):這是上一代的記憶體管理方式,現在已經不用了,因為ARC遠遠比MRC好用太多了,只需要知道有這些屬性的存在就可以了,因為在網路上還是很容易找到比較舊的文章是用MRC。
- assign(default) : 直接指派,不進行 retain
- retain : 先 release 再 retain 新值
- copy : 先 release 再 copy 新值
多執行緒相關:對初學者來說,這部分比較難懂,我後面打的解釋是結果論,如果想要知道兩個屬性背後實際上是怎麼回事可以看這篇atomic vs. nonatomic
- nonatomic : 沒有要用多執行序就選這個,但不知道為什麼Apple並沒有把這個屬性設為預設,所以幾乎是每次都要加上這個屬性。
- atomic(default) : 如果要使用多執行序就選這個。
setter/getter相關(accessors):
- setter = setterName:重新命名setter名稱
- getter = getterName:重新命名getter名稱,最常改的方式是在原本的名稱加「is」ex:@property (nonatomic, getter = isChosen) BOOL chosen;
@synthesize
@property DECLARES the accessors for your property, @synthesize will IMPLEMENT them.原本是在@interface的程式
-(int) price;
-(void) setPrice: (int) p;
可以只要寫@property int price;
在@implementation的程式從
-(int) price
{
return price;
}
-(void) setPrice: (int) p
{
price = p;
}
變成只要寫@synthesize price;
Xcode 4.3 之前,每一個 @property 都要在 @implementation 加上 @synthesize 變數名稱 或 @synthesize 變數名稱 =_ 變數名稱 但 4.4 之後就自動化了,如果沒寫,就等於寫了 @synthesize 變數名稱 =_ 變數名稱,而 @synthesize 的設定,也可以改變變數的名稱,如 【@synthesize 變數名稱;】 時,變數名稱前面就不再有 underline, 有興趣的讀可以查一下 @synthesize 的功能。2012年Objective-C加入了不少新功能,@synthesize變成預設值,現在有沒有寫@synthesize的差別只在於你取用變數的方式:
有寫@synthesize
price
沒有寫@synthesizeself.price
自訂setter/getter
但如果你要自訂自己的setter/getter的話,你就要自己寫setter/getter 函數,系統會以你自己寫的函數為主。例如我們自訂setter:
-(void)setPrice:(int)p
{
price = p * 2;
}
這樣的話當我們在給price值的時候,就會自動變成兩倍,也就是當我們打的程式碼是:price = 3;
price的值實際上是6而不是3,因為3傳入時還會被乘以二。Attribute 屬性
在2006年發佈了Objective-C 2.0後,Objective-C也可以使用「.」來存取物件的屬性
原本要設值是這樣
[b setPrice:300];
就可以寫成b.price = 300;
不過在高見龍的部落格裡有提到點語法的一個小細節,有可能造成無窮回圈:
-(void) setPrice: (int) p
{
self.price = p;
}
如果在自訂的setter裡使用了點語法,那就會不斷的呼叫自己(setter函數),變成無窮迴圈。整理來源:
http://stackoverflow.com/questions/9162926/ios-property-declaration-clarification
http://pydoing.blogspot.tw/2012/08/objc-property-and-synthesize.html
http://shenfive.pixnet.net/blog/post/48054812-@property-
http://blog.eddie.com.tw/2010/12/08/property-and-synthesize/
2014年9月4日 星期四
BOOL vs. Boolean vs. bool
Boolean is an old Carbon keyword (historic Mac type), defined as an unsigned char.
BOOL is an Objective-C type defined as signed char.
bool is a defined version of the _Bool standard C type.
You should use BOOL for common use and Boolean in CF.
BOOL is an Objective-C type defined as signed char.
bool is a defined version of the _Bool standard C type.
You should use BOOL for common use and Boolean in CF.
資料來源:http://stackoverflow.com/a/3016912/3295047
2014年8月29日 星期五
取消UITableView選擇後會highlight的動畫
我總共找到幾種方法,這之間有一些差異
第一種 放在tableView:cellForRowAtIndexPath:
可以用這個方法避免觸發到不希望有highlight效果的row
第二種 放在viewDidLoad裡
另外這是我找到的評論:Instead of userInteraction, use tableView.allowsSelection. That stops the cell's interaction methods but doesn't block the regular UIView responder stuff.
第五種
直接在Storyboard上設定,點選tableView的Selection選項,選擇No Selection
用這個方法的話,不會觸動tableView:didSelectRowAtIndexPath:。
資料來源:http://stackoverflow.com/questions/190908/how-can-i-disable-the-uitableview-selection-highlighting
第一種 放在tableView:cellForRowAtIndexPath:
cell.selectionStyle = UITableViewCellSelectionStyleNone;
但仍然會觸發tableView:didSelectRowAtIndexPath:,只是不會有highlight的動畫。可以用這個方法避免觸發到不希望有highlight效果的row
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// A case was selected, so push into the CaseDetailViewController
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (![cell selectionStyle] == UITableViewCellSelectionStyleNone) {
// Handle tap code here
}
}
[self.tableView setAllowsSelection:NO];
一次取消整個tableView的highlight功能,不會觸動tableView:didSelectRowAtIndexPath:。另外這是我找到的評論:Instead of userInteraction, use tableView.allowsSelection. That stops the cell's interaction methods but doesn't block the regular UIView responder stuff.
第三種 放在tableView:cellForRowAtIndexPath
第四種
放在viewDidLoad裡
cell.userInteractionEnabled = NO;
指定特定的row停止所有與使用者互動的功能,包括向右滑動刪除的功能。第四種
放在viewDidLoad裡
[self.tableView setUserInteractionEnabled:NO];
一次設定所有的tableView的userInteraction功能都取消。但這個方法會使得tableView連scroll的動作都沒辦法做,要注意!第五種
直接在Storyboard上設定,點選tableView的Selection選項,選擇No Selection
用這個方法的話,不會觸動tableView:didSelectRowAtIndexPath:。
資料來源:http://stackoverflow.com/questions/190908/how-can-i-disable-the-uitableview-selection-highlighting
2014年7月28日 星期一
頁面轉換
UIViewController *page2 = [self.storyboard instantiateViewControllerWithIdentifier:@"page2"];
Modal
[self presentViewController:page2 animated:YES completion:NULL];
The completion block is used for doing any tasks after presenting the view controller , the code written inside the completion block will execute only after the view is presented.資料來源:http://stackoverflow.com/a/13025138
Push
[self.navigationController pushViewController:page2 animated:YES];
UIButton
設定按鈕上的文字
[self.button setTitle:@"Wake Up" forState:UIControlStateNormal];
不能用self.button.titleLabel.text = @"Wake Up";
2014年7月17日 星期四
Core Data 基本操作
查詢
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"GoToBedTime" inManagedObjectContext:self.managedObjectContext];
NSSortDescriptor *sortByDate = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:NO];
NSArray *sortArray = [[NSArray alloc] initWithObjects:sortByDate, nil];
fetchRequest.sortDescriptors = sortArray;
fetchRequest.entity = entity;
NSArray *array = [self.managedObjectContext executeFetchRequest:fetchRequest error:nil];
GoToBedTime *goToBedTime = [array objectAtIndex:0];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"HH:mm:ss"];
cell.detailTextLabel.text = [formatter stringFromDate:goToBedTime.date];
原本
WakeUpTime *wakeUpTime = [array objectAtIndex:0];
wakeUpTime.timing
優化[[array objectAtIndex:0] timing]
handle the error
NSError *error = nil;
NSArray *array = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error]; //沒有資料會取得零筆資料但不會有error
if (error) {
//handle the error
}
相關範例
https://www.facebook.com/groups/iostw/permalink/969502549743761/
將NSDate轉成NSString
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"HH:mm:ss"];
cell.detailTextLabel.text = [formatter stringFromDate:[NSDate date]];
2014年7月10日 星期四
tableView
重新載入資料
全部[self.tableView reloadData];
更新特定row[self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:0 inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
別人的文章:UITableViewController 之 dataSource 更新顯示不知道什麼時候要加@@
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"Cell"];
設定接下來要顯示的viewController的title,有兩種方式:
prepareForSegue:- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
UIViewController *page2 = segue.destinationViewController;
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
(indexPath.row == 0) ? [page2 setTitle:@"Go To Bed Time"] : [page2 setTitle:@"Wake Up Time"];
}
didSelectRowAtIndexPath,需要另外設定目標viewController的Storyboard ID。但如果需要隔空轉換畫面,也就是不用segue轉換畫面的話,比如:同一個button一不同的情況要轉換到不同的view:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UIViewController *page2 = [self.storyboard instantiateViewControllerWithIdentifier:@"page3"];
(indexPath.row == 0) ? [page2 setTitle:@"Go To Bed Time"] : [page2 setTitle:@"Wake Up Time"];
[self.navigationController pushViewController:page2 animated:YES];
}
如果轉換模式要用modal
[self presentViewController:page2 animated:YES completion:nil];
completion那裡可以放轉換過去後要執行的程式indexPath
The NSIndexPath class represents the path to a specific node in a tree of nested array collections.
A table has sections and rows, to know where a row is you need to know the index of which section it is in and the index position it is at within that section.
UIKit adds a category to make it easier to work with UITableView's.@interface NSIndexPath (UITableView)
+ (NSIndexPath *)indexPathForRow:(NSInteger)row inSection:(NSInteger)section;
@property(nonatomic,readonly) NSInteger section;
@property(nonatomic,readonly) NSInteger row;
@end
資料來源:http://stackoverflow.com/a/10807882/3295047
2014年7月9日 星期三
按下backButton所觸動的method
我總共查到四種方法:
方法一:viewWillDisappear
方法二:viewDidDisappear
方法三:willMoveToParentViewController:parent
方法四:重新寫一個UINavigationBar,把舊的覆蓋掉
Add this custom Button on UINavigationBar , just override this button on BackButton and you can perform any action with click event.
不過只不過為了取得觸發按backButton的method有點太大費周章了,原出處是想要自訂UINavigationBar
方法五:下面這幾種方法也是網路上找到的,但不知道為什麼都不能觸發,原因可能是因為在tab下無法啟動,但不知道為什麼我另外開了個project還是不行,以後再來找原因吧,如果有誰知道拜託告訴我~~
延伸:如何直接回到 RootViewController(跳過中間的ViewController)
方法一:viewWillDisappear
-(void) viewWillDisappear:(BOOL)animated {
if ([self.navigationController.viewControllers indexOfObject:self]==NSNotFound) {
// back button was pressed. We know this is true because self is no longer
// in the navigation stack.
}
}
方法二:viewDidDisappear
- (void)viewDidDisappear:(BOOL)animated
{
if (self.navigationController == nil) {
NSLog(@"self.navigationController == nil");
}
if (self.navigationController.view == nil) {
NSLog(@"self.navigationController.view == nil");
}
if (self.navigationController.viewControllers == nil) {
NSLog(@"self.navigationController.viewControllers = nil");
}
}
方法三:willMoveToParentViewController:parent
-(void)willMoveToParentViewController:(UIViewController *)parent {
NSLog(@"This VC has has been pushed popped OR covered");
if (!parent)
NSLog(@"This happens ONLY when it's popped");
}
使用這個方法有個問題,就是不知道為什麼進入這個viewController也會觸動這個method方法四:重新寫一個UINavigationBar,把舊的覆蓋掉
Add this custom Button on UINavigationBar , just override this button on BackButton and you can perform any action with click event.
- (void)viewDidLoad
{
UIImage *backButtonImage = [UIImage imageNamed:@"backbutton.png"];
UIButton *backbutton = [UIButton buttonWithType:UIButtonTypeCustom];
//[backbutton setImage:backButtonImage forState:UIControlStateNormal];//this line for set only image on button
[backbutton setBackgroundImage:backButtonImage forState:UIControlStateNormal];
[backbutton setTitle:@"Back" forState:UIControlStateNormal];
backbutton.frame = CGRectMake(0, 0, backButtonImage.size.width, backButtonImage.size.height);
UIBarButtonItem * back = [[UIBarButtonItem alloc] initWithCustomView:backbutton];
[backbutton addTarget:self action:@selector(back_Clicked) forControlEvents:UIControlEventTouchUpInside];
self.navigationItem.leftBarButtonItem = back;
}
when back button clicked bellow method call and you will go to previous viewcontroller.-(void)back_Clicked{
[self.navigationController popViewControllerAnimated:YES];
}
出處:http://stackoverflow.com/a/13856441/3295047不過只不過為了取得觸發按backButton的method有點太大費周章了,原出處是想要自訂UINavigationBar
方法五:下面這幾種方法也是網路上找到的,但不知道為什麼都不能觸發,原因可能是因為在tab下無法啟動,但不知道為什麼我另外開了個project還是不行,以後再來找原因吧,如果有誰知道拜託告訴我~~
- (void)navigationController:(UINavigationController *)navigationController
willShowViewController:(UIViewController *)viewController
animated:(BOOL)animated
{
NSLog(@"navigationController:willShowViewController:animated");
}
- (void)navigationBar:(UINavigationBar *)navigationBar
didPopItem:(UINavigationItem *)item
{
NSLog(@"navigationBar:didPopItem");
}
- (UIViewController *)popNavigationItemAnimated:(BOOL)animated
{
NSLog(@"popNavigationItemAnimated");
return self.parentViewController;
}
- (id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
animationControllerForOperation:(UINavigationControllerOperation)operation
fromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC
{
NSLog(@"from VC class %@", [SLWakeUpTwoViewController class]);
if ([fromVC isKindOfClass:[SLWakeUpTwoViewController class]])
{
NSLog(@"Returning from popped controller");
}
return nil;
}
延伸:如何直接回到 RootViewController(跳過中間的ViewController)
訂閱:
文章 (Atom)








