app版本 ios swift
2018-03-26 16:49:00 weixin_34253539 阅读数 27

因为提交给测试的测试包太多 出问题的包可能会混 

所以加了个打包时间 和其他的一些app 和手机信息  方便测试在提BUG的时候带上

1. 在 Xcode 工程对应 Target 的 build Phases 中新增 run Scrpit Phase


2 创建 buildTime.pilst


3 创建shell脚本


set -e

# plist 文件地址



BUILD_TIME_VALUE="$(date +%Y年%m月%d日%H时%M分%S秒)"

if [ -r "${PLIST_PATH}" ]; then

/usr/libexec/PlistBuddy -c "Set ${BUILD_TIME_KEY} ${BUILD_TIME_VALUE}" "${PLIST_PATH}"


/usr/libexec/PlistBuddy -c "Add ${BUILD_TIME_KEY} string ${BUILD_TIME_VALUE}" "${PLIST_PATH}" 


4 取时间

单取个时间 挺麻烦 我就都贴上了

struct AppInfo {

 static let AppName = ""

 static let SystemType = "ios"

 static let ChannelSource = "App store"

 static let VersionName = String(describing: Bundle.main.infoDictionary!["CFBundleShortVersionString"]!)

 static let VersionCode = String(describing: Bundle.main.infoDictionary!["CFBundleVersion"]!)

 static let BundleIdentifier = Bundle.main.bundleIdentifier!

 static let KmilesBuildTime: String? = {

 if let path = Bundle.main.path(forResource: "BuildTime", ofType: "plist"),

 let dic = NSDictionary(contentsOfFile: path) as? [String: AnyObject],

 let result = dic["BuildTime"] as? String {

 return result


 return nil


 static let IPhoneOS: String = {

 return UIDevice.current.systemVersion


 static let IPhoneType: String = {

 var systemInfo = utsname()


 let machineMirror = Mirror(reflecting: systemInfo.machine)

 let identifier = machineMirror.children.reduce("") { identifier, element in

 guard let value = element.value as? Int8, value != 0 else { return identifier }

 return identifier + String(UnicodeScalar(UInt8(value)))


 switch identifier {

 case "iPod5,1": return "iPod Touch 5"

 case "iPod7,1": return "iPod Touch 6"

 case "iPhone3,1", "iPhone3,2", "iPhone3,3": return "iPhone 4"

 case "iPhone4,1": return "iPhone 4s"

 case "iPhone5,1", "iPhone5,2": return "iPhone 5"

 case "iPhone5,3", "iPhone5,4": return "iPhone 5c"

 case "iPhone6,1", "iPhone6,2": return "iPhone 5s"

 case "iPhone7,2": return "iPhone 6"

 case "iPhone7,1": return "iPhone 6 Plus"

 case "iPhone8,1": return "iPhone 6s"

 case "iPhone8,2": return "iPhone 6s Plus"

 case "iPhone9,1": return "iPhone 7"

 case "iPhone9,2": return "iPhone 7 Plus"

 case "iPhone10,1","iPhone10,4": return "iPhone 8"

 case "iPhone10,2","iPhone10,5": return "iPhone 8 Plus"

 case "iPhone10,3","iPhone10,6": return "iPhone X"

 case "iPad2,1", "iPad2,2", "iPad2,3", "iPad2,4":return "iPad 2"

 case "iPad3,1", "iPad3,2", "iPad3,3": return "iPad 3"

 case "iPad3,4", "iPad3,5", "iPad3,6": return "iPad 4"

 case "iPad4,1", "iPad4,2", "iPad4,3": return "iPad Air"

 case "iPad5,3", "iPad5,4": return "iPad Air 2"

 case "iPad2,5", "iPad2,6", "iPad2,7": return "iPad Mini"

 case "iPad4,4", "iPad4,5", "iPad4,6": return "iPad Mini 2"

 case "iPad4,7", "iPad4,8", "iPad4,9": return "iPad Mini 3"

 case "iPad5,1", "iPad5,2": return "iPad Mini 4"

 case "iPad6,7", "iPad6,8": return "iPad Pro"

 case "AppleTV5,3": return "Apple TV"

 case "i386", "x86_64": return "Simulator"

 default: return "Unknown"




遮住的只是我的app名字 没有影响

2016-09-28 14:30:00 weixin_34402090 阅读数 2

1. Launch Xcode

2. Choose the Single View Application template 

3. Make sure that only Portrait is selected.

4. Remove the View Controller Scene from the storyboard, change UIViewController to UITableViewController

5. Drag a Table View Controller into the canvas

6. Set Class type to ChecklistViewController

7. Set the Initial View Controller.

8. Adding the label to the prototype cell, also add a checkmark to the cell’s design

9. Giving the table view cell a reuse identifier

10. Use tableView(numberOfRowsInSection) protocol and tableView(cellForRowAt) protocol

11. Gets a copy of the prototype cell, Call tableView.dequeueReusableCell(withIdentifier).

12. Set the label's Tag field to 1000

13. Ask the table view cell for the view with tag 1000.

14. Looks at the value of indexPath.row, which contains the row number, and changes the label’s text accordingly

15. Add the the tableView(didSelectRowAt) method

16. Find the UITableViewCell object for the tapped row

17. Add the toggle of checkmark

18. Add the tableView.deselectRow method.

19. Added an instance variable with the text for every row

20. Added initial check type for every cell 

Bug: Cell VS Row

21. For every row you have added an instance variable with the text for that row.

22. Add another five new instance variables to keep track of the “checked” state of each of the rows.

23. Merge the 5 check prototype track variable to 1 (change 22)

Bug: the data model (the “row checked” variables) and the views (the checkmarks inside the cells) are out-of-sync.

24. Set the cell’s accessoryType property to the right value in tableView(cellForRowAt)---call configure checkmark method in tableview ( cell for row at) method, just before return cell.

25. Simplify “didSelectRowAt” by letting configureCheckmark(for:at:) do some of the work.

26. Combine the text and checkmark state into a new object: make a class named checklistItem

27. Remove the old instance variables and replace them with ChecklistItem objects

28. In tableView(cellForRowAt), replace the if-statements, In tableView(didSelectRowAt), change the following lines, in configureCheckmark(for:at:), make these changes.

29. Give it a value inside a so-called initializer method:

required init?(coder aDecoder: NSCoder) {


super.init(coder: aDecoder) }

30. In ChecklistViewController.swift, throw away all the instance variables and replace them with a single array variable named items.

31. Simplify the table view data source and delegate methods once again.

32. Replace the configureCheckmark(for:at:) method with (for: with: checklistItem)

33. Add a new method: Configure text

34. Update tableView(cellForRowAt) and tableView(didSelectRowAt) so that it calls these new methods 

35. Add the toggle checked method

36. Embed a navigation controller in the view controller 

36. Add Bar Button Item into the rightside slot of the navigation bar

37. Add a new addItem method to ChecklistViewController.swift and connect it with the button. Creates the new ChecklistItem object and adds it to the end of the array

38. Tell the table view about this new row so it can add a new cell for that row.

39. Add the Swipe-to-delete method to ChecklistViewController.swift.

40. Add a new Table View Controller as the addItem screen and connect it with the add button.

41. Remove the button’s connection with the addItem action. (change 37)

42. In the segue's Attributes inspector, choose Kind: Present Modally.

43. Embed In a Navigation Controller for the new table view controller and add the cancel button and done button.

44. Make a new view controller source code file specifically for the Add Item screen and connect it to the scene

45. Add the new cancel() and done() action methods in AddItemViewController.swift

46. In the addItem view's Attributes inspector, change the Content setting from Dynamic Prototypes to Static Cells.

47. Drag a Text Field object into the cell and set the Border Style to no border.

48. Add the willselectRow at method In AddItemViewController.swift* and return nil.

49. In the storyboard, select the table view cell and go to the Attributes inspector. Set the Selection attribute to None. (may be not necessary)

50. Connect the text field with the swift file.

51. Modify the done() action to write the contents of this text field

52. Add viewWillAppear (becomefirstResponder) method to AddItemViewController.swift

53. Set the attributes for the text field.

54. Open the Connections inspector of the text field. Drag from the Did End on Exit event to the view controller and pick the done action.

55. Disable the Done button when no text has been typed yet..

56. Make the view controller a delegate for the text field:

      Include UITextFieldDelegate in the class line for the view controller.

     Tell the text field that it has a delegate

     Implement the delegate methods

57. Add the textField(shouldChangeCharactersIn methon to AddItemViewController.swift

58. Uncheck the Enabled box of the done button attributes inspector.

Delegates in five easy steps:

59. Defines the AddItemViewControllerDelegate protocol.

60. Inside AddItemViewController, write the variable delegate to refer back to the ChecklistViewController

61. Replace the cancel() and done() actions with delegate method.

Bug: the Cancel and Done buttons. They no longer work

62. Make the ChecklistViewController suitable to play the delegate role and add the methods that are listed in AddItemViewControllerDelegate to the checklistViewController.

63. Add prepare-for-segue method to ChecklistViewController.swift, and naming the segue between the Checklists scene and the navigation controller

64. Change the implementation of the “didFinishAdding” delegate method in ChecklistViewController.swift.( copied the contents of addItem() )

65. Remove addItem() from ChecklistViewController.swift as you no longer need this method.

66. Go to the table view cell in the storyboard and in the Attributes inspector set its Accessory to Detail Disclosure.

67. Drag a new Label into the cell and place it on the left of the text label.

68. In ChecklistViewController.swift, change configureCheckmark(for:with:) (change 32)

69. Connect the accessory action of the table view cell with the navigation controller and set it present modally.

70. Add a new property for a ChecklistItem object below the other instance variables in AddItemViewController.swift

71. Add the viewDidLoad() method to AddItemViewController.swift

72. Change prepare(for:sender:) in ChecklistViewController.swift. (add edit item condition) (change 63)

73. Change viewDidLoad() in AddItemViewController.swift to fix the Done button

74. Add a new addItemViewController method (didFinishEditing) to the delegate protocol

75. In AddItemViewController.swift, change the done() method

Bug: “Method … has different argument names from those required by protocol …”.

76. Add the didFinishEditing to ChecklistViewController.swift

Bug: “Cannot invoke index with an argument list of type blah blah blah”.

77. Add the NSObject to the checklistItem class.

78. Replace the name of the addItemView controller with ItemDetailViewController

79. Add documentDirectory methods to ChecklistViewController

80. Add the saveChecklistItems method to ChecklistViewController

func saveChecklistItems() {  

 let data = NSMutableData()  

 let archiver = NSKeyedArchiver(forWritingWith: data)  

 archiver.encode(items, forKey: "ChecklistItems")  


 data.write(to: dataFilePath(), atomically: true) 


81. Add a call to saveChecklistItems() to the end of ItemDetailViewControllerDelegate methods inside ChecklistViewController

82. Let’s not forget the swipe-to-delete function and toggling the checkmark on a row on or off

Bug: [Checklists.ChecklistItem encodeWithCoder:]: unrecognized selector sent to instance 0x7f8d6af3aac0

83. Add NSCoding to the class line in ChecklistItem, telling the compiler that ChecklistItem will conform to a new protocol, NSCoding. (need to add the 2 func in checklistItem)

84. Add the encode(with aCoder: NSCoder) to ChecklistItem

85. Add the init?(coder aDecoder: NSCoder) method to ChecklistItem

86. Add an init() method that takes no parameters to ChecklistItem.

87. Change the empty init?(coder) method in ChecklistItem. (change 83), take objects from the NSCoder’s decoder object and put their values inside your own properties.

88. In ChecklistViewController.swift, replace init?(coder)

89. Also add the loadChecklistItems() method

90. Add a new Cocoa Touch Class template, Class: AllListsViewController, Subclass of: UITableViewController

91. Remove the numberOfSections(in) method

92. Implement the tableView(cellForRowAt) method to put some text into the cells and add a makeCell method.

93. Drag a new Table View Controller onto the canvas

94. Ctrl-drag from the very first navigation controller to this new table view controller, Relationship Segue - root view controller

95. Select the new table view controller and set its Class in the Identity inspector to AllListsViewController

96. Ctrl-drag from the yellow circle icon at the top of All Lists View Controller into the Checklist View Controller and create a Show segue, go to the Attributes inspector and give it the identifier ShowChecklist.

97. In AllListsViewController.swift, add the tableView(didSelectRowAt) method

98. Add a new file to the project based on the Cocoa Touch Class template. Name it Checklist and make it a subclass of NSObject

99. Give Checklist.swift a name property

100. Give AllListsViewController an array that will store these new Checklist objects

101. Go to Checklist.swift and add the new init method

102. Go back to AllListsViewController.swift and add init?(coder), for real this time:

103. Change the tableView(numberOfRowsInSection) method to return the number of objects in the new array

104. Change tableView(cellForRowAt) to fill in the cells for the rows

105. Add a new instance variable to ChecklistViewController.swift

106. Change the viewDidLoad() method in ChecklistViewController.swift

107. In AllListsViewController.swift, update tableView(didSelectRowAt)

108. Add the prepare(for:sender:) method to AllListsViewController.swift

109. Add a new file to the project, ListDetailViewController.swift. You can either use the Cocoa Touch Class template or the Swift File template for this.

110. Replace the contents of ListDetailViewController.swift

111. Add the viewDidLoad() method

112. Also add the viewWillAppear() method to pop up the keyboard

113. Add the action methods for the Cancel and Done buttons

114. Also make sure the user cannot select the table cell with the text field

115. And finally, add the text field delegate method that enables or disables the Done button depending on whether the text field is empty or not.

116. Drag a new Navigation Controller from the Object Library into the canvas and move it below the other view controllers.

117. Select the new Table View Controller, Change its class to ListDetailViewController

118. Change the navigation bar title from “Root View Controller” to Add Checklist.

119. Add Cancel and Done bar button items and hook them up to the action methods in the view controller. Also connect the Done button to the doneBarButton outlet and uncheck its Enabled option.

120. Change the table view to Static Cells, style Grouped. You only need one cell, so remove the bottom two.

121. Drop a new Text Field into the cell.

122. Ctrl-drag from the view controller to the Text Field and connect it to the textField outlet.

123. Ctrl-drag the other way around, from the Text Field back to the view controller, and choose delegate under Outlets.

124. Connect the text field’s Did End on Exit event to the done action on the view controller.

125. Go to the All Lists View Controller (the one titled “Checklists”) and drag a Bar Button Item into its navigation bar. Change it into an Add button.

126. Ctrl-drag from this new bar button to the navigation controller below to add a new Present Modally segue.

127. Click on the new segue and name it AddChecklist

128. Make the AllListsViewController the delegate for the ListDetailViewController

129. Add the tableView(accessoryButtonTappedForRowWith) method to AllListsViewController.swift.

130. Open the storyboard and select the navigation controller that points to List Detail View Controller. Go to the Identity inspector and into the field Storyboard ID type ListDetailNavigationController:

131. Creates a new, empty, array that can hold ChecklistItem objects and assigns it to the items instance variable.

132. Remove the items instance variable from ChecklistViewController.swift.

133. Anywhere it says items you change it to say checklist.items instead.

134. Delete the documentsDirectory(),dataFilePath() , saveChecklistItems(), loadChecklistItems() methods from ChecklistViewController.swift. 

135. Remove the lines that call saveChecklistItems().

136. Also delete init?(coder) from ChecklistViewController.swift.

137. Add some fake data into the various Checklist objects so that you can test whether this new design actually works.

138. Add the documentsDirectory(),dataFilePath() , saveChecklistItems(), loadChecklistItems() methods to AllListsViewController.swift.

139. Gets rid of the test data you put there earlier and makes the loadChecklists() method do all the work.

140. Add the NSCoding protocol in Checklist.swift

141. Add the method which loads and saves the Checklist’s name and items properties.

142. Remove the old Checklists.plist file from the Simulator’s Documents folder.

143. Add saveData() method to AppDelegate.swift

144. Change the applicationDidEnterBackground() and applicationWillTerminate() methods to call saveData()

145. Add a new file to the project using the Swift File template. Save it as DataModel.swift

146. Defines the new DataModel object and gives it a lists property.

147. Cut the documentsDirectory(),dataFilePath() , saveChecklistItems(), loadChecklistItems() methods out of AllListsViewController.swift and paste them into DataModel.swift

148. Add an init() method to DataModel.swift, makes sure that, as soon as the DataModel object is created, it will attempt to load Checklists.plist.

149. Switch to AllListsViewController.swift and make the following changes:

 ➤ Remove the lists instance variable. 

➤ Remove the init?(coder) method. 

➤ Add a new dataModel instance variable

150. Everywhere the code for AllListsViewController says lists, replace this with dataModel.lists. You need to do this in the following methods:

 • tableView(numberOfRowsInSection) 

• tableView(cellForRowAt) 

• tableView(didSelectRowAt)

 • tableView(commit, forRowAt) 

• tableView(accessoryButtonTappedForRowWith) 

• listDetailViewController(didFinishAdding) 

• listDetailViewController(didFinishEditing)

151. In AppDelegate.swift, add a new dataModel property

152. Simplify the saveData() method

153. Share the DataModel instance with AllListsViewController  in the application(didFinishLaunchingWithOptions) method

154. In AllListsViewController.swift, change tableView(didSelectRowAt) to store the index of the selected row into UserDefaults under the key “ChecklistIndex”.

155. Add the delegate protocol to the class line in AllListsViewController.swift

156. Add the delegate method to the bottom of AllListsViewController.swift

157. Add the viewDidAppear() method to AllListsViewController.swift

158. Add the registerDefaults() method inside DataModel.swift

159. Change DataModel.swift’s init() to call loadChecklists()  and registerDefaults()  method

160. Let’s move all of the UserDefaults stuff into DataModel

161. Update the code in AllListsViewController.swift to use this new computed property

162. Change the if-statement in viewDidAppear()

163. Change the registerDefaults() method in DataModel.swift, add a new default setting to the registerDefaults() method. The key for this value is “FirstTime”.

164. Still in DataModel.swift, add a new handleFirstTime() method

165. Call this new method from DataModel’s init()

166. Add the countUncheckedItems() method to Checklist.swift

167. Go to AllListsViewController.swift and in makeCell(for) change style: .default to style: .subtitle.

168. Add the cell.detailTextLabel!.text =  "\(checklist.countUncheckedItems()) Remaining" just before return cell in tableView(cellForRowAt).

169. Go to AllListsViewController.swift and add the viewWillAppear() method

170. Change the relevant code in tableView(cellForRowAt) to change the label to read “All Done!” when there are no more to-do items left to check. Answerc

171. Change method in AllListsViewController’s implementation of “didFinishAdding” and “didFinishEditing

172. Add the sortChecklists() method to DataModel.swift

173. You should also call sortChecklists() when the plist file is loaded

174. Add the images from this folder to the asset catalog.

175. Add the iconName property to Checklist.swift

176. Extend init?(coder) and encode(with) to respectively load and save this icon name in the Checklists.plist file

177. Update init(name) to Give all new checklists the “Appointments” icon 

178. Change tableView(cellForRowAt) in AllListsViewController.swift to put the icon into the table view cell:

179. Remove the Checklists.plist file or reset the Simulator

180. Change Checklist’s init(name) to give each Checklist object an icon named “No Icon” by default

181. Add a new Swift file to the project. Name it IconPickerViewController, defines the IconPickerViewController object

182. Add a constant (inside the class brackets) to hold the array of icons

183. Implement the data source methods: (numberOfRowsInSection, cellForRowAt ) for the table view.

184. Open the storyboard. Drag a new Table View Controller from the Object Library and place it next to the List Detail View Controller

185. In the Identity inspector, change the class of this new table view controller to IconPickerViewController.

186. Select the prototype cell and set its Style to Basic and its (re-use) Identifier to IconCell.

187. Go to the List Detail View Controller and add a new section to the table view. You can do this by changing the Sections field in the Attributes inspector for the table view from 1 to 2.

188. Delete the Text Field from the new cell;

189. Add a Label to this cell and name it Icon.

190. Set the cell’s Accessory to Disclosure Indicator.

191. Add an Image View to the right of the cell. Make it 36 × 36 points big. (Tip: use the Size inspector for this.)

192. Use the Assistant Editor to add an outlet property for this image view to ListDetailViewController.swift and name it iconImageView.

193. Ctrl-drag from the “Icon” table view cell to the Icon Picker View Controller and add a segue of type Selection Segue – Show.

194. Give the segue the identifier PickIcon.

195. Double-click that navigation bar and change its title to Choose Icon.

196. In ListDetailViewController.swift, change the “willSelectRowAt” table view delegate method

197. Add an instance variable in ListDetailViewController.swift to keep track of the chosen icon name

198. Update viewDidLoad()  to copy the Checklist object’s icon name into the iconName instance variable.

199. Implement prepare(for:sender:) to ListDetailViewController.swift in order to tell the IconPickerViewController that this screen is now its delegate

200. Made the view controller conform to the delegate protocol

201. Add the implementation of the method from that delegate protocol somewhere inside the ListDetailViewController class:

202. Change the done() action so that it puts the chosen icon name into the Checklist object when the user closes the screen

203. Change IconPickerViewController to actually call the delegate method when a row is tapped.

204. Add a new init method to Checklist.swift that takes two parameters: name and iconName.

205. Making init(name) call init(name, iconName) with "No Icon" as the value for the iconName parameter.

206. Open the storyboard and go to the File inspector, Click Global Tint to open the color picker and choose Red: 4, Green: 169, Blue: 235.

207. Add the label.textColor = view.tintColor line to configureCheckmark(for:with:) in ChecklistViewController.swift

208. Open the Project Settings screen. In the General tab, scroll down to the App Icons and Launch Images section.

209. In the Launch Screen File box, press the arrow and select Main.storyboard.

210. Delete LaunchScreen.storyboard from the project.

211. From the Product menu choose Clean.

212. Select the Icon Image View. Bring up the Pin menu using the icon at the bottom of the canvas, uncheck Constrain to margins, Activate the bars at the top and the right so they turn red, Put checkmarks in front of Width and Height, For Update Frames choose Items of New Constraints, Finally, click Add 4 Constraints to finish.

213. Select the Text Field and in the Pin menu activate the four bars so they all become red

214. Also do this for the text field on the Add/Edit Item screen.

215. In the storyboard, go to the Checklist screen and select the label inside the prototype cell.

216. First use Editor → Size to Fit Content to give the label its ideal size.

217. Open the Pin menu and uncheck Constrain to margins, Activate the red bar on the right. Give it the value 0 so there is no spacing between the label and the disclosure button, set Update Frames to Items of New Constraints. Click Add 1 Constraint to add the new constraint.

218. With the label still selected, open the Align menu (next to Pin). Check Vertically in Container. Update Frames should be Items of New Constraints.

219. Select the label again. Ctrl-drag from the label to anywhere within the cell, select Leading Space to Container Margin from the popup.

220. Select the blue bar. In the Size inspector, change Constant to 30.

221. Open AppDelegate.swift and add a new UserNotifications import to the top of the file

222. Add the following to the method application(didFinishLaunchingWithOptions), just before the return true line:

 let center = UNUserNotificationCenter.current() 

center.requestAuthorization(options: [.alert, .sound]) {    

     granted, error in 

     if granted {    

          print("We have permission")  } 

     else {    

          print("Permission denied")



223. Stop the app and add the UNMutableNotificationContent code to didFinishLaunchingWithOptions

224. Add the UIResponder, UIApplicationDelegate,  UNUserNotificationCenterDelegate to AppDelegate’s class declaration

225. Also add the userNotificationCenter method to AppDelegate.swift

226. Finally, tell the UNUserNotificationCenter that AppDelegate is now its delegate. You do this in application(didFinishLaunchingWithOptions)

227. Remove the the local notification code from didFinishLaunchingWithOptions, but keep these lines:

let center = UNUserNotificationCenter.current()  

center.delegate = self

228. Extend init?(coder) and encode(with) in order to be able to load and save these new properties along with the ChecklistItem objects

229. Asks the DataModel object for a new item ID whenever the app creates a new ChecklistItem object.

230 Add this new nextChecklistItemID() method to DataModel.

231. Hop on over to DataModel.swift and add nextChecklistItemID() method

232. Add a default value for “ChecklistItemID” to the registerDefaults() method

233. In ChecklistViewController.swift, change the configureText(for:with:)

234. Before you run the app, make sure to reset the Simulator first or throw away Checklists.plist from the app’s Documents directory.

235. Add the shouldRemindSwitch and dueDateLabel outlets to ItemDetailViewController.swift

236. Open the storyboard and select the Table View in the Item Detail View Controller, Add a new section to the table.

237. Remove the Text Field from the new cell. Drag a new Table View Cell from the Object Library and drop it below this one, so that the second section has two rows.

238. Add a Label to the first cell and give it the text Remind Me. Set the font to System, size 17.

239. Also drag a Switch control into the cell. Hook it up to the shouldRemindSwitch outlet on the view controller. In the Attributes inspector, set its Value to Off so it is no longer green.

240. Pin the Switch to the top and right edges of the table view cell.

241. simply set the Style of the cell to Right Detail and rename Title to Due Date.

242. The label on the right should be hooked up to the dueDateLabel outlet.

243. Add a new dueDate instance variable to ItemDetailViewController.swift

244. Change viewDidLoad()

245. The updateDueDateLabel() method is new. Add it to the file

246. The last thing to change in this file is the done() action.

247. Run the app and change the position of the switch control. The app will remember this setting when you terminate it

248. Add a new instance variable to ItemDetailViewController.swift, to keep track of whether the date picker is currently visible And add the showDatePicker() method

249. Open the storyboard and go to the Add Item scene. From the Object Library, pick up a new Table View Cell. Don’t drag it into the view controller itself but into the scene dock at the top

250. Select the Table View Cell and in the Size inspector set the Height to 217. The date picker is 216 points tall, plus one point for the separator line at the bottom of the cell.

251. In the Attributes inspector, set Selection to None so this cell won’t turn gray when you tap on it.

252. From the Object Library, drag a Date Picker into the cell. It should fit exactly

253. Use the Pin menu to glue the Date Picker to the four sides of the cell. Turn off Constrain to margins and then select the four bars to make them red (they all should be 0).

254. Make two new outlets and connect them to the cell and the date picker, respectively.

255. Add the tableView(cellForRowAt) method to ItemDetailViewController.swift

256. Override tableView(numberOfRowsInSection)

257. you also need to provide the tableView(heightForRowAt) method

258. Add didSelectRowAt method calls showDatePicker() when the index-path indicates that the Due Date row was tapped

259. Change tableView(willSelectRowAt)

260. Add the tableView(indentationLevelForRowAt) method

261. Add the dateChanged() method to ItemDetailViewController.swift

262. In the storyboard, Ctrl-drag from the Date Picker to the view controller and select the dateChanged: action method. Now everything is properly hooked up.

263. Add the datePicker.setDate(dueDate, animated: false) line to the bottom of showDatePicker()

264. Change showDatePicker() to sets the textColor of the detailTextLabel to the tint color.

265. Add the new hideDatePicker() method

266. Change tableView(didSelectRowAt) to toggle between the visible and hidden states

267. Add the textFieldDidBeginEditing() method

268. Add the scheduleNotification() method to ChecklistItem.swift

269. In the done() action in ItemDetailViewController.swift, add the item.scheduleNotification() line just before the call to didFinishEditing and also before `didFinishaAdding

270. In ChecklistItem.swift, change scheduleNotification()

271. To tell ChecklistItem about the User Notifications framework, you need to import UserNotifications to the top of the file, below the other import

272. Add the shouldRemindToggled method to ItemDetailViewController.swift

273. Also add an import UserNotifications or the above method won’t compile

274. Open the storyboard and connect the shouldRemindToggled: action to the switch control.

275. Add the removeNotification() method to ChecklistItem.swift

276. Call this new method from to the top of scheduleNotification()

277. Add the removeNotification() to the bottom of ChecklistItem.swift

2018-03-26 16:47:48 weiwandaixu_ 阅读数 270

因为提交给测试的测试包太多 出问题的包可能会混 

所以加了个打包时间 和其他的一些app 和手机信息  方便测试在提BUG的时候带上

1. 在 Xcode 工程对应 Target 的 build Phases 中新增 run Scrpit Phase

2 创建 buildTime.pilst

3 创建shell脚本


set -e

# plist 文件地址



BUILD_TIME_VALUE="$(date +%Y年%m月%d日%H时%M分%S秒)"

if [ -r "${PLIST_PATH}" ]; then

    /usr/libexec/PlistBuddy -c "Set ${BUILD_TIME_KEY} ${BUILD_TIME_VALUE}" "${PLIST_PATH}"


    /usr/libexec/PlistBuddy -c "Add ${BUILD_TIME_KEY} string ${BUILD_TIME_VALUE}" "${PLIST_PATH}"    


4 取时间

单取个时间 挺麻烦 我就都贴上了

struct AppInfo {

    static let AppName = ""

    static let SystemType = "ios"

    static let ChannelSource = "App store"

    static let VersionName = String(describing: Bundle.main.infoDictionary!["CFBundleShortVersionString"]!)

    static let VersionCode = String(describing: Bundle.main.infoDictionary!["CFBundleVersion"]!)

    static let BundleIdentifier = Bundle.main.bundleIdentifier!

    static let KmilesBuildTime: String? = {

        if let path = Bundle.main.path(forResource: "BuildTime", ofType: "plist"),

            let dic = NSDictionary(contentsOfFile: path) as? [String: AnyObject],

            let result = dic["BuildTime"] as? String {

            return result


        return nil


    static let IPhoneOS: String = {

        return UIDevice.current.systemVersion


    static let IPhoneType: String = {

        var systemInfo = utsname()


        let machineMirror = Mirror(reflecting: systemInfo.machine)

        let identifier = machineMirror.children.reduce("") { identifier, element in

            guard let value = element.value as? Int8, value != 0 else { return identifier }

            return identifier + String(UnicodeScalar(UInt8(value)))


        switch identifier {

        case "iPod5,1":                                 return "iPod Touch 5"

        case "iPod7,1":                                 return "iPod Touch 6"

        case "iPhone3,1", "iPhone3,2", "iPhone3,3":     return "iPhone 4"

        case "iPhone4,1":                               return "iPhone 4s"

        case "iPhone5,1", "iPhone5,2":                  return "iPhone 5"

        case "iPhone5,3", "iPhone5,4":                  return "iPhone 5c"

        case "iPhone6,1", "iPhone6,2":                  return "iPhone 5s"

        case "iPhone7,2":                               return "iPhone 6"

        case "iPhone7,1":                               return "iPhone 6 Plus"

        case "iPhone8,1":                               return "iPhone 6s"

        case "iPhone8,2":                               return "iPhone 6s Plus"

        case "iPhone9,1":                               return "iPhone 7"

        case "iPhone9,2":                               return "iPhone 7 Plus"

        case "iPhone10,1","iPhone10,4":                 return "iPhone 8"

        case "iPhone10,2","iPhone10,5":                 return "iPhone 8 Plus"

        case "iPhone10,3","iPhone10,6":                 return "iPhone X"

        case "iPad2,1", "iPad2,2", "iPad2,3", "iPad2,4":return "iPad 2"

        case "iPad3,1", "iPad3,2", "iPad3,3":           return "iPad 3"

        case "iPad3,4", "iPad3,5", "iPad3,6":           return "iPad 4"

        case "iPad4,1", "iPad4,2", "iPad4,3":           return "iPad Air"

        case "iPad5,3", "iPad5,4":                      return "iPad Air 2"

        case "iPad2,5", "iPad2,6", "iPad2,7":           return "iPad Mini"

        case "iPad4,4", "iPad4,5", "iPad4,6":           return "iPad Mini 2"

        case "iPad4,7", "iPad4,8", "iPad4,9":           return "iPad Mini 3"

        case "iPad5,1", "iPad5,2":                      return "iPad Mini 4"

        case "iPad6,7", "iPad6,8":                      return "iPad Pro"

        case "AppleTV5,3":                              return "Apple TV"

        case "i386", "x86_64":                          return "Simulator"

        default:                                        return "Unknown"




遮住的只是我的app名字 没有影响
2017-06-29 16:52:28 taoerit 阅读数 1041


Mac OS: macOS Sierra 10.12.5
XCode版本:Version 8.3.3 (8E3004b)
上传方法:archive - validate - export - application loader

上传app store总结:


【如果发现图片小看不清楚,请用ctrl + 滚轮键 放大或者缩小】



然后去itunsconnect 去提交一下



2016-09-13 16:38:00 weixin_33966365 阅读数 5

let iOSVersion : NSString = UIDevice.currentDevice().systemVersion  //iOS 版本

let identifierNumber = UIDevice.currentDevice().identifierForVendor  //设备 udid

let systemName = UIDevice.currentDevice().systemName  //设备名称

let model = UIDevice.currentDevice().model  //设备型号

let localizedModel = UIDevice.currentDevice().localizedModel  //设备区域化型号 如 A1533