个月前,完成了个人App的2.0版本,也在普天同庆的六一儿童节这天上架了。因为是个人开发,很多实现都是边探索边做。现在完成之后再回顾,发现自己走了些弯路。所以写了这篇总结,概览了从想法、设计、开发到最终发布的过程。希望读者参考本文,可以少走一些弯路;另外,本文也给列出了开发中具体思路和资源列表。

知识从何而来?

Apple的知识又是从何而来?是哪些人在创造这些机制,又是哪些人在传播这些机制?为什么要这样设计呢?为什么要这样编码呢?

iOS开发是在询问什么问题?技术的实现,究竟是在问什么?为什么要这样做?那样做?评价的标准为何?

资源

我在开发过程中常使用的资源:

  • 相关书籍寻找大致实现方向,我有庞大的电子书库,在此感谢学校提供的优质资源。很多书,都会先检视阅读一遍,这样心中有地图,开发时就可快速定位。书本是理论的简单系统化表示。

  • Apple 官方文档 视频 示例代码系统化的概览,具体可使用内容的查找。

  • StackOverflow主要是查找一些细节问题。

  • Github上的相关项目看具体的代码实现,分析不同实现的优缺点,取其精华去其糟粕。

  • Raywenderlich可以很快上手入门新知识点。

  • 博客

  • 论文

  • 对于想深入理解的知识,会参考相关论文。

搜索时使用google或者bing,绝对可以节约你的时间。时间即是生命。

我选择的简单是易用SS,我的推介链接。

想法

  • 目标:简洁优雅易用节拍器

  • 用户:学习乐器演奏的群体

  • 使用场景:乐器演奏

  • 做什么:小而美。好看,好用,占内存小。

  • 不做什么:不做专业程度极高,功能十分完备的节拍器。

设计

我一般使用Sketch进行快速原型设计。

同时思考,是否可实现?

开发

我使用的是coding的仓库,git进行版本管理。

主要介绍2.0版本中的一些开发过程。

你可以免费下载,看看有哪些基本功能。

多主题设计

配色

参考网站:

  • https://coolors.co/browser

  • http://uigradients.com/#Jonquil

  • http://www.rocket-design.fr/color-template/

  • http://www.shejidaren.com/examples/tools/color-scheme/

  • http://www.shejidaren.com/mbe-style.html

  • http://www.peise.net/

扁平化颜色库:

Chameleon is a lightweight, yet powerful, color framework for iOS (Objective-C & Swift). It is built on the idea that software applications should function effortlessly while simultaneously maintaining their beautiful interfaces.

https://github.com/ViccAlexander/Chameleon

多主题实现

OC版:

https://github.com/Draveness/DKNightVersion

Swift版:

http://www.jianshu.com/p/a5cd0176bcf5

https://github.com/zhangbozhb/ChameleonSwift

  1. theme

  2. view

部分配色表:

Name defaultColor SeaColor GreenColor CoffeeColor  
backgroundColor          
BlockColor rgba(184, 184, 184, 1) #D5EBE9 #F4ADA2 #D4C38F  
BlockColorFill rgba(251, 251, 251, 1) #F5FAF9 #F07973 #EFDFAF  
BlockBdrColor rgba(57, 57, 57, 1) #38465F #38465F #272727  
shadowColor rgba(41, 44, 48, 1) #38465F #A0785C #5D4531  
Sliderstart rgba(184, 184, 184, 1) #F5FAF9 #F2F2F2 #88DEF2  
Sliderend rgba(185, 200, 245, 1) #B0D5C2 #F4ADA2 #FAD199  
SliderBackground Black #364960 #3A4C39 #2B2B2B  
nameIncDecTextColor Black White Black Black  
labelColor Black white Black Black  

根据图片配色举例:

代码实现:

1.Struct方式

public protocol YXYTheme {

// MetreView

var blockColor              : UIColor { get set }

var blockFillColor          : UIColor { get set }

var blockBdrColor           : UIColor { get set }

var blockShadowColor        : UIColor { get set }

// View

var backgroundColor         : UIColor { get set }

var nameIncDecTextColor     : UIColor { get set }

var labelColor              : UIColor { get set }

var incAndDecLabelTextColor : UIColor { get set }

// Slider

var sliderBackgroundColor   : UIColor { get set }

var sliderStartColor        : UIColor { get set }

var sliderEndColor          : UIColor { get set }

var sliderHandleColor       : UIColor { get set }

}

struct DarkTheme : YXYTheme, AnyObjectConvertible {

var blockColor              = UIColor(red:0.72, green:0.72, blue:0.72, alpha:1)

var blockFillColor          = UIColor(red:0.95, green:0.95, blue:0.95, alpha:1)

var blockBdrColor           = UIColor(red:0.21, green:0.21, blue:0.21, alpha:1)

var blockShadowColor        = UIColor(red:0.16, green:0.17, blue:0.19, alpha:1)

var backgroundColor         = UIColor(red:0.34, green:0.34, blue:0.34, alpha:1)

var nameIncDecTextColor     = UIColor(red:0.95, green:0.95, blue:0.95, alpha:1)

var labelColor              = UIColor.whiteColor()

var incAndDecLabelTextColor = UIColor.whiteColor()

var sliderBackgroundColor   = UIColor.lightGrayColor()

var sliderStartColor        = UIColor.grayColor()

var sliderEndColor          = UIColor.greenColor()

var sliderHandleColor       = UIColor.greenColor()

}

2.class 方式

//

//  LightTheme.swift

//  GuitarFere

//

//  Created by youxinyu on 16/3/10.

//  Copyright © 2016年 yogayu.github.io. All rights reserved.

//

import UIKit

class LightTheme : NSObject, YXYTheme, AnyObjectConvertible

{

var blockColor              = UIColor(red:0.72, green:0.72, blue:0.72, alpha:1)

var blockFillColor          = UIColor(red:0.95, green:0.95, blue:0.95, alpha:1)

var blockBdrColor           = UIColor(red:0.21, green:0.21, blue:0.21, alpha:1)

var blockShadowColor        = UIColor(red:0.16, green:0.17, blue:0.19, alpha:1)

var backgroundColor         = UIColor.whiteColor()

var nameIncDecTextColor     = UIColor(red:0.95, green:0.95, blue:0.95, alpha:1)

var labelColor              = UIColor.whiteColor()

var incAndDecLabelTextColor = UIColor.whiteColor()

var sliderBackgroundColor   = UIColor.lightGrayColor()

var sliderStartColor        = UIColor.grayColor()

var sliderEndColor          = UIColor.redColor()

var sliderHandleColor       = UIColor.greenColor()

init( blockColor:UIColor, blockFillColor:UIColor, blockBdrColor:UIColor, blockShadowColor:UIColor,

backgroundColor:UIColor, nameIncDecTextColor:UIColor, labelColor:UIColor, incAndDecLabelTextColor:UIColor,

sliderBackgroundColor:UIColor, sliderStartColor:UIColor, sliderEndColor:UIColor, sliderHandleColor:UIColor){

self.blockColor = blockColor

self.blockFillColor = blockFillColor

self.blockBdrColor = blockBdrColor

self.blockShadowColor = blockShadowColor

self.backgroundColor = backgroundColor

self.nameIncDecTextColor = nameIncDecTextColor

self.labelColor = labelColor

self.incAndDecLabelTextColor = incAndDecLabelTextColor

self.sliderBackgroundColor = sliderBackgroundColor

self.sliderStartColor = sliderStartColor

self.sliderEndColor = sliderEndColor

self.sliderHandleColor = sliderHandleColor

}

}

本地化

参见我之前博文:

http://www.jianshu.com/p/782aaf3bf7da

http://azureyu.com/2016-05-14-iOS-Localizable.html

保持用户设置

let userDefaultsLastTempoKey = "DefaultsTempoKey"

let defaults = NSUserDefaults.standardUserDefaults()

func saveTempo(tempo:Int){

defaults.setInteger(tempo, forKey: userDefaultsLastTempoKey)

defaults.synchronize()

}

读取:

func initialTempo(){

let savedTempo = NSUserDefaults.standardUserDefaults().objectForKey( userDefaultsLastTempoKey) as? Int

if let tempo = savedTempo {

metronome.tempo = tempo

tempoLabel.text = "\(metronome.tempo)"

}else {

tempoLabel.text = "\(metronome.tempo)"

}

Struct如何转为AnyObject?

参考:

https://github.com/tarunon/AnyObjectConvertible

class Box<T> {

let value: T

init(value: T) {

self.value = value

}

}

NSNotificationCenter.defaultCenter().postNotificationName("foo", object: Box(value: YourOwnStruct())) // OK

But Box<T> unwrap is too lazy.

let value = (notification.object as? Box<YourOwnStruct>)?.value

You can cast your struct/enum directory if implement AnyObjectConvertible at that type.

extension YourOwnStruct: AnyObjectConvertible {}

NSNotificationCenter.defaultCenter().postNotificationName("foo", object: YourOwnStruct()) // OK

let value = notification.object as? YourOw

存储用户当前主题设置

初始显示,无法使用函数更改,为什么?

解决:因为存的内容不对,主题是一个Struct或Class。

func initTheme() {

let savedTheme = retrieveTheme()

if let theme = savedTheme {

UIApplication.ch_switchTheme(lightTheme)

}else{

// ...

}

}

GuitarFere[20074:736310] * Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘Attempt to insert non-property list object GuitarFere.Box<GuitarFere.YXYTheme> for key DefaultThemeKey’

The code you posted tries to save an array of custom objects to NSUserDefaults. You can’t do that. Implementing the NSCoding methods doesn’t help. You can only store things like NSArray, NSDictionary, NSString, NSData, NSNumber, and NSDate in NSUserDefaults.
You need to convert the object to NSData (like you have in some of the code) and store that NSData in NSUserDefaults. You can even store an NSArray of NSData if you need to.
When you read back the array you need to unarchive the NSData to get back your BC_Personobjects.
http://stackoverflow.com/questions/19720611/attempt-to-set-a-non-property-list-object-as-an-nsuserdefaults

func saveTheme(theme:LightTheme){

//    let archivedObject = NSKeyedArchiver.archivedDataWithRootObject((theme as? NSObject)!)

let archivedObject = NSKeyedArchiver.archiveRootObject(theme as NSObject, toFile: userDefaultsLastThemeKey)

defaults.setObject(archivedObject, forKey: userDefaultsLastThemeKey)

defaults.synchronize()

}

存:

func saveTheme(theme:LightTheme){

//    let archivedObject = NSKeyedArchiver.archivedDataWithRootObject((theme as? NSObject)!)

let archivedObject = NSKeyedArchiver.archiveRootObject(theme as NSObject, toFile: userDefaultsLastThemeKey)

defaults.setObject(archivedObject, forKey: userDefaultsLastThemeKey)

defaults.synchronize()

}

上面解决方式还是有问题。

突然想到,不用保存主题本身,直接保存是第几个(Int)主题就好。

问题就这样解决了。

摇一摇换肤

override func canBecomeFirstResponder() -> Bool {

return true

}

override func motionBegan(motion: UIEventSubtype, withEvent event: UIEvent?) {

if(event?.subtype == UIEventSubtype.MotionShake) {

randomTheme()

print("shacked")

self.setNeedsStatusBarAppearanceUpdate()

}

}

func randomTheme() {

let max = themes.count - 1

let index = randomIn(min: 0, max: max)

let randomTheme = themes[index]

saveTheme(index)

UIApplication.ch_switchTheme(randomTheme)

}

钟摆绘制

主要使用图像绘制。

例如绘制三角形:

func drawTriangle()  {

//1.获得图形上下文

let context = UIGraphicsGetCurrentContext()

//绘制三角形

let height = self.frame.height

let width = self.frame.width

CGContextMoveToPoint(context, 0, 0)

CGContextAddLineToPoint(context, width, height/2)

CGContextAddLineToPoint(context, 0, height)

//关闭路径,闭环,(连接起点和最后一个点)

powerOffColor.setFill()

CGContextClosePath(context)

//显示在view上

CGContextFillPath(context)

}

iOS 独立开发记录(上)的更多相关文章

  1. iOS 独立开发记录(下)

    侧边菜单栏 查看Github上相关实现,一开始选择的是SlideMenuControllerSwift,后来决定更改为自定义,使用更简洁的方式. 分离 分离之前的SliderMeanControlle ...

  2. iOS 自定义控件开发(上)

    工作需要,最近在进行iOS方面的图表工作.找了很多第三方库都无法实现效果,所以决定自己写一个控件. <iOS 自定义控件开发(上)> <iOS 自定义控件开发(中)> #0 目 ...

  3. iOS-开发记录-UIView属性

    UIView属性 1.alpha 设置视图的透明度.默认为1. // 完全透明 view.alpha = ; // 不透明 view.alpha = ; 2.clipsToBounds // 默认是N ...

  4. IOS APP开发UI上的尺寸注意问题(屏幕、适配、分辨率)

  5. iOS 自定义控件开发(中)

    <iOS 自定义控件开发(上)> <iOS 自定义控件开发(中)> 接上篇iOS自定义控件开发之后,我们尝试另外一种. 在Xcode的右边,会看到如下的图 其中,上面有一个:C ...

  6. IOS开发-图片上传

    目前IOS端开发,图片上传到服务器分为两种,一种是直接上到服务器,一种是借助第三方储存(减少服务器压力). 一.直接上传到服务器 /** * 代码演示 */ //*******UIImagePNGRe ...

  7. iOS 蓝牙开发资料记录

    一.蓝牙基础认识:   1.iOS蓝牙开发:  iOS蓝牙开发:蓝牙连接和数据读写   iOS蓝牙后台运行  iOS关于app连接已配对设备的问题(ancs协议的锅)          iOS蓝牙空中 ...

  8. CozyRSS开发记录19-窗口标题栏交互

    CozyRSS开发记录19-窗口标题栏交互 1.谈谈对mvvm解耦的看法 在使用mvvm时,如何操作窗口,这是一个问题.这个问题的关键点是:mvvm是把view和viewmodel解耦了的,很多写法一 ...

  9. iOS多线程开发

    概览 大家都知道,在开发过程中应该尽可能减少用户等待时间,让程序尽可能快的完成运算.可是无论是哪种语言开发的程序最终往往转换成汇编语言进而解释成机器码来执行.但是机器码是按顺序执行的,一个复杂的多步操 ...

随机推荐

  1. 实例:jQuery实现标签切换

    具体实现效果如图: 原理很简单,就是监听鼠标滑动和点击事件.在第一个标签切换的示例中,当鼠标滑过某个标签时,就把class转移到当前标签.这里用到的jQuery方法主要是each()确定当前是哪一个标 ...

  2. 织梦dedecms后台发布文章不自动更新首页与栏目列表页

    dedecms发文章不自动更新首页也列表页解决办法如下: 登陆dedecms后台,找到“系统”“系统基本参数”“性能选项”,把“arclist标签调用缓存”设置成0,然后把“发布文章后马上更新网站主页 ...

  3. 那些年被我坑过的Python——玄而又玄(第六章 面向对象编程基础)

    面向对象编程: 面向对象顾名思义,就是把组织代码的粒度从函数级别抽象到对象级别,对象是通过类来生成的,类可以想象为模板或进本框架而对象是在原有模板或框架的基础上增加详细信息的实体,类,有分类.聚类的含 ...

  4. Java线程生命模型

    一. 线程状态类型1. 新建状态(New):新创建了一个线程对象.2. 就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法.该状态的线程位于可运行线程池中,变得可运 ...

  5. 转:PHP开发框架流行度排名:Laravel居首

    原文来自于:http://www.sitepoint.com/best-php-frameworks-2014/ Update: If you’d like to take part in the n ...

  6. [BZOJ 3626] [LNOI2014] LCA 【树链剖分 + 离线 + 差分询问】

    题目链接: BZOJ - 3626 题目分析 考虑这样的等价问题,如果我们把一个点 x 到 Root 的路径上每个点的权值赋为 1 ,其余点的权值为 0,那么从 LCA(x, y) 的 Depth 就 ...

  7. 几个国外FMX网站 good

    FireMonkey X –  Amazing overview of FireMonkey FMX Feeds – All your FireMonkey news in one place FMX ...

  8. android-wear开发之定义布局

    Android Wear使用跟手机一样的布局技术,但需要对特定情况进行设计.不要把手机的UI直接照搬过来.更多可查看:Android Wear Design Guidelines 当创建android ...

  9. AlgorithmsI PA2: Randomized Queues and Deques RandomizedQueue

    RandomizedQueue 有几个关键点: 1. 选择合适的数据结构,因为需要任意位置删除元素,Linked list 做不到,必须使用resizing arrays. 2. resizing 的 ...

  10. HDU 5396 Expression(DP+组合数)(详解)

    题目大意: 给你一个n然后是n个数. 然后是n-1个操作符,操作符是插入在两个数字之间的. 由于你不同的运算顺序,会产生不同的结果. 比如: 1 + 1 * 2 有两种  (1+1)*2   或者   ...