// curring 另类调用方式 let funcWithA = addCur(1) print("funcWithA type : \(funcWithA.dynamicType)") let funcWithAB = funcWithA(b: 2) print("funcWithAB type : \(funcWithAB.dynamicType)") let resultCurring = funcWithAB(c: 3) print("resultCurring type : \(resultCurring.dynamicType)") ```
此时你还是会觉得这只是把一个函数拆开来调用了 那么我们打印一下 每个调用步骤中变量的类型
let funcWithA = addCur(1) print(“funcWithA type : (funcWithA.dynamicType)”) // let funcWithAB = funcWithA(b: 2) print(“funcWithAB type : (funcWithAB.dynamicType)”) let resultCurring = funcWithAB(c: 3) print(“resultCurring type : (resultCurring.dynamicType)”)
1 2
打印结果为
1 + 2 + 3 = 6 funcWithA type : Int -> Int -> Int funcWithAB type : Int -> Int 1 + 2 + 3 = 6 resultCurring type : Int
1 2 3 4 5 6 7 8 9 10 11 12 13
可以看到 变量funcWithA 为 Int -> Int -> Int 类型 funcWithAB 为Int -> Int
// 拼接字符 func concat(chars: Array) { var resultString = “” for char in chars { resultString += char } print(resultString) }
concat([“1”,”2”,”3”]) print(“**“)
// 每个字符代表的数字 + 1 后再拼接 func concatAdd(chars: Array, addNum: Int) { var resultString = “” for char in chars { var num = Int(char)! num = num + addNum let newChar = String(num) resultString += newChar } print(resultString) }
print(“**“) // 每个字符代表的数字 10 后再拼接 func concatMultiply(chars: Array, multiplyNum: Int) { var resultString = “” for char in chars { var num = Int(char)! num = num multiplyNum let newChar = String(num) resultString += newChar } print(resultString) }
print(“**“) / 让我们使用柯里化吧 */ func add(a: Int)(b: Int) -> Int{ return a + b }
func multiply(a: Int)(b: Int) -> Int{ return a * b }
func concatByCurring(chars: Array)(caculateFunc: (Int)->Int) { var resultString = “” for char in chars { var num = Int(char)! var newNum = caculateFunc(num) let newChar = String(newNum) resultString += newChar } print(resultString) }
People().printSpeak() // 打印结果为 People func speak : People -> () -> () // 可见实例的方法就是一个Curring结构
1 2
下面是[Instance Methods are Curried Functions in Swift](http://oleb.net/blog/2014/07/swift-instance-methods-curried-functions/?utm_campaign=iOS_Dev_Weekly_Issue_157&utm_medium=email&utm_source=iOS%2BDev%2BWeekly)中的例子 很开脑洞
Markdown is a plain text format for writing structured documents, based on conventions used for indicating formatting in email and usenet posts. It was developed in 2004 by John Gruber, who wrote the first markdown-to-html converter in Perl, and it soon became widely used in websites. By 2014 there were dozens of implementations in many languages.
// 键盘响应布局 @objc func keyboardFrameChanged(notification: NSNotification) { let dict = NSDictionary(dictionary: notification.userInfo!) let keyboardValue = dict.objectForKey(UIKeyboardFrameEndUserInfoKey) as! NSValue let bottomDistance = mainScreenSize().height - keyboardValue.CGRectValue().origin.y let duration = Double(dict.objectForKey(UIKeyboardAnimationDurationUserInfoKey) as! NSNumber) UIView.animateWithDuration(duration, animations: { self.inputViewConstraint!.constant = -bottomDistance self.view.layoutIfNeeded() }, completion: { (value: Bool) in self.chatTableView.scrollToBottom(animation: true) }) }
ScrollView下拉动态修改keyboard(InputView)的frame
常见隐藏keyboard的一些方式
TouchBeigin
DidDrag
EndDrag
Interactive
iOS7 开始,ScrollView提供
1 2 3 4 5 6
@available(iOS 7.0, *) publicenum UIScrollViewKeyboardDismissMode : Int { case None case OnDrag // dismisses the keyboard when a drag begins case Interactive // the keyboard follows the dragging touch off screen, and may be pulled upward again to cancel the dismiss }
// in objective-c, but in swift, #define can't be used any more // use let keyword to define a macro, look up original document: /* Simple Macros Where you typically used the #define directive to define a primitive constant in C and Objective-C, in Swift you use a global constant instead. For example, the constant definition #define FADE_ANIMATION_DURATION 0.35 can be better expressed in Swift withlet FADE_ANIMATION_DURATION = 0.35. Because simple constant-like macros map directly to Swift global variables, the compiler automatically imports simple macros defined in C and Objective-C source files. */ // in objective-c // #define kCommonAPI @"http://xxxxxxx" // but in swift, no #define, just use let to define let kCommonAPI = "http://xxxxxxx"
let dog = "a gog"// 可以不添加分号 let cat = "a cat"; print(cat)// 除了最后一条语句可以不添加分号外,其它都需要添加分号来隔开 let catTwo = "two cats"; let name = "Jobs"; print("\(name) has \(catTwos)")
类型转换
Swift不会像C、OC那样自动隐式转换类型,所以我们需要手动进行类型转换
1 2 3 4 5 6 7 8
let twoThousand: UInt16 = 2000 // one是UInt8类型 let one: UInt8 = 1 // twoThousand是UInt16类型,one是UInt8类型,如果要执行相加,那么就需要进行类型转换 // 否则会报错的。 let twoThousandAndOne = twoThousand + UInt16(one)
For all styles, line height is 0.1em larger than the English-like languages. English and English-like languages mostly use a portion of the em box, often the lower portion below the x-height. Chinese, Japanese, and Korean (CJK) ideographic characters use the entire em box. Characters in tall languages often have long descenders and/or ascenders. To achieve the same design intention as English for CJK and to avoid potential text clipping between two lines next to each other for tall languages, the line height needs to be larger than in English for tall and dense languages.
classA { var name = "namevalue" var age = 123 var some:(String, Int) = ("ming", 2) }
let a1 = A()
a1.age = 456
a1.age
let r = Mirror(reflecting: a1) forcin r.children { print(c.label.dynamicType) print(c.label) print(c.value.dynamicType) print(c.value) print("===") }
KVO for NSObject 略, 注意监听者与被监听者都要是 NSObject 子类
JSONModel for swift?
> NB: Swift works in a different way under the hood than Objective-C. Therefore I can’t find a way to re-create JSONModel in Swift. JSONModel in Objective-C works in Swift apps through CocoaPods or as an imported Objective-C library.
// Delegate to proper methods based on the viewType ranges. if (viewType >= HEADER_VIEW_TYPE_OFFSET && viewType < HEADER_VIEW_TYPE_OFFSET + VIEW_TYPE_MAX_COUNT) { returnonCreateHeaderItemViewHolder(parent, viewType - HEADER_VIEW_TYPE_OFFSET); } elseif(viewType >= FOOTER_VIEW_TYPE_OFFSET && viewType < FOOTER_VIEW_TYPE_OFFSET + VIEW_TYPE_MAX_COUNT){ returnonCreateFooterItemViewHolder(parent, viewType - FOOTER_VIEW_TYPE_OFFSET); } elseif(viewType >= CONTENT_VIEW_TYPE_OFFSET && viewType < CONTENT_VIEW_TYPE_OFFSET + VIEW_TYPE_MAX_COUNT){ returnonCreateContentItemViewHolder(parent, viewType - CONTENT_VIEW_TYPE_OFFSET); } else { // This shouldn't happen as we check that the viewType provided by the client is valid. thrownew IllegalStateException(); } }
/** * {@inheritDoc} */ @Override publicfinalvoidonBindViewHolder(RecyclerView.ViewHolder viewHolder, int position){ // Delegate to proper methods based on the viewType ranges. if (headerItemCount > 0 && position < headerItemCount) { onBindHeaderItemViewHolder(viewHolder, position); } elseif(contentItemCount > 0 && position - headerItemCount < contentItemCount){ onBindContentItemViewHolder(viewHolder, position - headerItemCount); } else { onBindFooterItemViewHolder(viewHolder, position - headerItemCount - contentItemCount); } }
/** * {@inheritDoc} */ @Override publicfinalintgetItemCount(){ // Cache the counts and return the sum of them. headerItemCount = getHeaderItemCount(); contentItemCount = getContentItemCount(); footerItemCount = getFooterItemCount(); return headerItemCount + contentItemCount + footerItemCount; }
/** * {@inheritDoc} */ @Override publicfinalintgetItemViewType(int position){ // Delegate to proper methods based on the position, but validate first. if (headerItemCount > 0 && position < headerItemCount) { return validateViewType(getHeaderItemViewType(position)) + HEADER_VIEW_TYPE_OFFSET; } elseif(contentItemCount > 0 && position - headerItemCount < contentItemCount){ return validateViewType(getContentItemViewType(position - headerItemCount)) + CONTENT_VIEW_TYPE_OFFSET; } else { return validateViewType(getFooterItemViewType(position - headerItemCount - contentItemCount)) + FOOTER_VIEW_TYPE_OFFSET; } }
/** * Validates that the view type is within the valid range. * * @param viewType the view type. * @return the given view type. */ privateintvalidateViewType(int viewType){ if (viewType < 0 || viewType >= VIEW_TYPE_MAX_COUNT) { thrownew IllegalStateException("viewType must be between 0 and " + VIEW_TYPE_MAX_COUNT); } return viewType; }
/** * Notifies that a header item is inserted. * * @param position the position of the header item. */ publicfinalvoidnotifyHeaderItemInserted(int position){ int newHeaderItemCount = getHeaderItemCount(); if (position < 0 || position >= newHeaderItemCount) { thrownew IndexOutOfBoundsException("The given position " + position + " is not within the position bounds for header items [0 - " + (newHeaderItemCount - 1) + "]."); } notifyItemInserted(position); }
/** * Notifies that multiple header items are inserted. * * @param positionStart the position. * @param itemCount the item count. */ publicfinalvoidnotifyHeaderItemRangeInserted(int positionStart, int itemCount){ int newHeaderItemCount = getHeaderItemCount(); if (positionStart < 0 || itemCount < 0 || positionStart + itemCount > newHeaderItemCount) { thrownew IndexOutOfBoundsException("The given range [" + positionStart + " - " + (positionStart + itemCount - 1) + "] is not within the position bounds for header items [0 - " + (newHeaderItemCount - 1) + "]."); } notifyItemRangeInserted(positionStart, itemCount); }
/** * Notifies that a header item is changed. * * @param position the position. */ publicfinalvoidnotifyHeaderItemChanged(int position){ if (position < 0 || position >= headerItemCount) { thrownew IndexOutOfBoundsException("The given position " + position + " is not within the position bounds for header items [0 - " + (headerItemCount - 1) + "]."); } notifyItemChanged(position); }
/** * Notifies that multiple header items are changed. * * @param positionStart the position. * @param itemCount the item count. */ publicfinalvoidnotifyHeaderItemRangeChanged(int positionStart, int itemCount){ if (positionStart < 0 || itemCount < 0 || positionStart + itemCount >= headerItemCount) { thrownew IndexOutOfBoundsException("The given range [" + positionStart + " - " + (positionStart + itemCount - 1) + "] is not within the position bounds for header items [0 - " + (headerItemCount - 1) + "]."); } notifyItemRangeChanged(positionStart, itemCount); }
/** * Notifies that an existing header item is moved to another position. * * @param fromPosition the original position. * @param toPosition the new position. */ publicvoidnotifyHeaderItemMoved(int fromPosition, int toPosition){ if (fromPosition < 0 || toPosition < 0 || fromPosition >= headerItemCount || toPosition >= headerItemCount) { thrownew IndexOutOfBoundsException("The given fromPosition " + fromPosition + " or toPosition " + toPosition + " is not within the position bounds for header items [0 - " + (headerItemCount - 1) + "]."); } notifyItemMoved(fromPosition, toPosition); }
/** * Notifies that a header item is removed. * * @param position the position. */ publicvoidnotifyHeaderItemRemoved(int position){ if (position < 0 || position >= headerItemCount) { thrownew IndexOutOfBoundsException("The given position " + position + " is not within the position bounds for header items [0 - " + (headerItemCount - 1) + "]."); } notifyItemRemoved(position); }
/** * Notifies that multiple header items are removed. * * @param positionStart the position. * @param itemCount the item count. */ publicvoidnotifyHeaderItemRangeRemoved(int positionStart, int itemCount){ if (positionStart < 0 || itemCount < 0 || positionStart + itemCount > headerItemCount) { thrownew IndexOutOfBoundsException("The given range [" + positionStart + " - " + (positionStart + itemCount - 1) + "] is not within the position bounds for header items [0 - " + (headerItemCount - 1) + "]."); } notifyItemRangeRemoved(positionStart, itemCount); }
/** * Notifies that a content item is inserted. * * @param position the position of the content item. */ publicfinalvoidnotifyContentItemInserted(int position){ int newHeaderItemCount = getHeaderItemCount(); int newContentItemCount = getContentItemCount(); if (position < 0 || position >= newContentItemCount) { thrownew IndexOutOfBoundsException("The given position " + position + " is not within the position bounds for content items [0 - " + (newContentItemCount - 1) + "]."); } notifyItemInserted(position + newHeaderItemCount); }
/** * Notifies that multiple content items are inserted. * * @param positionStart the position. * @param itemCount the item count. */ publicfinalvoidnotifyContentItemRangeInserted(int positionStart, int itemCount){ int newHeaderItemCount = getHeaderItemCount(); int newContentItemCount = getContentItemCount(); if (positionStart < 0 || itemCount < 0 || positionStart + itemCount > newContentItemCount) { thrownew IndexOutOfBoundsException("The given range [" + positionStart + " - " + (positionStart + itemCount - 1) + "] is not within the position bounds for content items [0 - " + (newContentItemCount - 1) + "]."); } notifyItemRangeInserted(positionStart + newHeaderItemCount, itemCount); }
/** * Notifies that a content item is changed. * * @param position the position. */ publicfinalvoidnotifyContentItemChanged(int position){ if (position < 0 || position >= contentItemCount) { thrownew IndexOutOfBoundsException("The given position " + position + " is not within the position bounds for content items [0 - " + (contentItemCount - 1) + "]."); } notifyItemChanged(position + headerItemCount); }
/** * Notifies that multiple content items are changed. * * @param positionStart the position. * @param itemCount the item count. */ publicfinalvoidnotifyContentItemRangeChanged(int positionStart, int itemCount){ if (positionStart < 0 || itemCount < 0 || positionStart + itemCount > contentItemCount) { thrownew IndexOutOfBoundsException("The given range [" + positionStart + " - " + (positionStart + itemCount - 1) + "] is not within the position bounds for content items [0 - " + (contentItemCount - 1) + "]."); } notifyItemRangeChanged(positionStart + headerItemCount, itemCount); }
/** * Notifies that an existing content item is moved to another position. * * @param fromPosition the original position. * @param toPosition the new position. */ publicfinalvoidnotifyContentItemMoved(int fromPosition, int toPosition){ if (fromPosition < 0 || toPosition < 0 || fromPosition >= contentItemCount || toPosition >= contentItemCount) { thrownew IndexOutOfBoundsException("The given fromPosition " + fromPosition + " or toPosition " + toPosition + " is not within the position bounds for content items [0 - " + (contentItemCount - 1) + "]."); } notifyItemMoved(fromPosition + headerItemCount, toPosition + headerItemCount); }
/** * Notifies that a content item is removed. * * @param position the position. */ publicfinalvoidnotifyContentItemRemoved(int position){ if (position < 0 || position >= contentItemCount) { thrownew IndexOutOfBoundsException("The given position " + position + " is not within the position bounds for content items [0 - " + (contentItemCount - 1) + "]."); } notifyItemRemoved(position + headerItemCount); }
/** * Notifies that multiple content items are removed. * * @param positionStart the position. * @param itemCount the item count. */ publicfinalvoidnotifyContentItemRangeRemoved(int positionStart, int itemCount){ if (positionStart < 0 || itemCount < 0 || positionStart + itemCount > contentItemCount) { thrownew IndexOutOfBoundsException("The given range [" + positionStart + " - " + (positionStart + itemCount - 1) + "] is not within the position bounds for content items [0 - " + (contentItemCount - 1) + "]."); } notifyItemRangeRemoved(positionStart + headerItemCount, itemCount); }
/** * Notifies that a footer item is inserted. * * @param position the position of the content item. */ publicfinalvoidnotifyFooterItemInserted(int position){ int newHeaderItemCount = getHeaderItemCount(); int newContentItemCount = getContentItemCount(); int newFooterItemCount = getFooterItemCount(); if (position < 0 || position >= newFooterItemCount) { thrownew IndexOutOfBoundsException("The given position " + position + " is not within the position bounds for footer items [0 - " + (newFooterItemCount - 1) + "]."); } notifyItemInserted(position + newHeaderItemCount + newContentItemCount); }
/** * Notifies that multiple footer items are inserted. * * @param positionStart the position. * @param itemCount the item count. */ publicfinalvoidnotifyFooterItemRangeInserted(int positionStart, int itemCount){ int newHeaderItemCount = getHeaderItemCount(); int newContentItemCount = getContentItemCount(); int newFooterItemCount = getFooterItemCount(); if (positionStart < 0 || itemCount < 0 || positionStart + itemCount > newFooterItemCount) { thrownew IndexOutOfBoundsException("The given range [" + positionStart + " - " + (positionStart + itemCount - 1) + "] is not within the position bounds for footer items [0 - " + (newFooterItemCount - 1) + "]."); } notifyItemRangeInserted(positionStart + newHeaderItemCount + newContentItemCount, itemCount); }
/** * Notifies that a footer item is changed. * * @param position the position. */ publicfinalvoidnotifyFooterItemChanged(int position){ if (position < 0 || position >= footerItemCount) { thrownew IndexOutOfBoundsException("The given position " + position + " is not within the position bounds for footer items [0 - " + (footerItemCount - 1) + "]."); } notifyItemChanged(position + headerItemCount + contentItemCount); }
/** * Notifies that multiple footer items are changed. * * @param positionStart the position. * @param itemCount the item count. */ publicfinalvoidnotifyFooterItemRangeChanged(int positionStart, int itemCount){ if (positionStart < 0 || itemCount < 0 || positionStart + itemCount > footerItemCount) { thrownew IndexOutOfBoundsException("The given range [" + positionStart + " - " + (positionStart + itemCount - 1) + "] is not within the position bounds for footer items [0 - " + (footerItemCount - 1) + "]."); } notifyItemRangeChanged(positionStart + headerItemCount + contentItemCount, itemCount); }
/** * Notifies that an existing footer item is moved to another position. * * @param fromPosition the original position. * @param toPosition the new position. */ publicfinalvoidnotifyFooterItemMoved(int fromPosition, int toPosition){ if (fromPosition < 0 || toPosition < 0 || fromPosition >= footerItemCount || toPosition >= footerItemCount) { thrownew IndexOutOfBoundsException("The given fromPosition " + fromPosition + " or toPosition " + toPosition + " is not within the position bounds for footer items [0 - " + (footerItemCount - 1) + "]."); } notifyItemMoved(fromPosition + headerItemCount + contentItemCount, toPosition + headerItemCount + contentItemCount); }
/** * Notifies that a footer item is removed. * * @param position the position. */ publicfinalvoidnotifyFooterItemRemoved(int position){ if (position < 0 || position >= footerItemCount) { thrownew IndexOutOfBoundsException("The given position " + position + " is not within the position bounds for footer items [0 - " + (footerItemCount - 1) + "]."); } notifyItemRemoved(position + headerItemCount + contentItemCount); }
/** * Notifies that multiple footer items are removed. * * @param positionStart the position. * @param itemCount the item count. */ publicfinalvoidnotifyFooterItemRangeRemoved(int positionStart, int itemCount){ if (positionStart < 0 || itemCount < 0 || positionStart + itemCount > footerItemCount) { thrownew IndexOutOfBoundsException("The given range [" + positionStart + " - " + (positionStart + itemCount - 1) + "] is not within the position bounds for footer items [0 - " + (footerItemCount - 1) + "]."); } notifyItemRangeRemoved(positionStart + headerItemCount + contentItemCount, itemCount); }
/** * Gets the header item view type. By default, this method returns 0. * * @param position the position. * @return the header item view type (within the range [0 - VIEW_TYPE_MAX_COUNT-1]). */ protectedintgetHeaderItemViewType(int position){ return0; }
/** * Gets the footer item view type. By default, this method returns 0. * * @param position the position. * @return the footer item view type (within the range [0 - VIEW_TYPE_MAX_COUNT-1]). */ protectedintgetFooterItemViewType(int position){ return0; }
/** * Gets the content item view type. By default, this method returns 0. * * @param position the position. * @return the content item view type (within the range [0 - VIEW_TYPE_MAX_COUNT-1]). */ protectedintgetContentItemViewType(int position){ return0; }
/** * Gets the header item count. This method can be called several times, so it should not calculate the count every time. * * @return the header item count. */ protectedabstractintgetHeaderItemCount();
/** * Gets the footer item count. This method can be called several times, so it should not calculate the count every time. * * @return the footer item count. */ protectedabstractintgetFooterItemCount();
/** * Gets the content item count. This method can be called several times, so it should not calculate the count every time. * * @return the content item count. */ protectedabstractintgetContentItemCount();
/** * This method works exactly the same as {@link #onCreateViewHolder(android.view.ViewGroup, int)}, but for header items. * * @param parent the parent view. * @param headerViewType the view type for the header. * @return the view holder. */ protectedabstract RecyclerView.ViewHolder onCreateHeaderItemViewHolder(ViewGroup parent, int headerViewType);
/** * This method works exactly the same as {@link #onCreateViewHolder(android.view.ViewGroup, int)}, but for footer items. * * @param parent the parent view. * @param footerViewType the view type for the footer. * @return the view holder. */ protectedabstract RecyclerView.ViewHolder onCreateFooterItemViewHolder(ViewGroup parent, int footerViewType);
/** * This method works exactly the same as {@link #onCreateViewHolder(android.view.ViewGroup, int)}, but for content items. * * @param parent the parent view. * @param contentViewType the view type for the content. * @return the view holder. */ protectedabstract RecyclerView.ViewHolder onCreateContentItemViewHolder(ViewGroup parent, int contentViewType);
/** * This method works exactly the same as {@link #onBindViewHolder(android.support.v7.widget.RecyclerView.ViewHolder, int)}, but for header items. * * @param headerViewHolder the view holder for the header item. * @param position the position. */ protectedabstractvoidonBindHeaderItemViewHolder(RecyclerView.ViewHolder headerViewHolder, int position);
/** * This method works exactly the same as {@link #onBindViewHolder(android.support.v7.widget.RecyclerView.ViewHolder, int)}, but for footer items. * * @param footerViewHolder the view holder for the footer item. * @param position the position. */ protectedabstractvoidonBindFooterItemViewHolder(RecyclerView.ViewHolder footerViewHolder, int position);
/** * This method works exactly the same as {@link #onBindViewHolder(android.support.v7.widget.RecyclerView.ViewHolder, int)}, but for content items. * * @param contentViewHolder the view holder for the content item. * @param position the position. */ protectedabstractvoidonBindContentItemViewHolder(RecyclerView.ViewHolder contentViewHolder, int position);