diff --git a/AVFoundation/AVFoundation.xcodeproj/project.pbxproj b/AVFoundation/AVFoundation.xcodeproj/project.pbxproj index 4bef6d31..9b86cb55 100644 --- a/AVFoundation/AVFoundation.xcodeproj/project.pbxproj +++ b/AVFoundation/AVFoundation.xcodeproj/project.pbxproj @@ -140,7 +140,7 @@ 0867D690FE84028FC02AAC07 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0460; + LastUpgradeCheck = 0510; }; buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "AVFoundation" */; compatibilityVersion = "Xcode 3.2"; @@ -202,7 +202,6 @@ INSTALL_PATH = "@executable_path/../Frameworks"; PRODUCT_NAME = AVFoundation; SYMROOT = ../build; - VALID_ARCHS = "i386 x86_64"; WRAPPER_EXTENSION = framework; }; name = Debug; @@ -222,7 +221,6 @@ INSTALL_PATH = "@executable_path/../Frameworks"; PRODUCT_NAME = AVFoundation; SYMROOT = ../build; - VALID_ARCHS = "i386 x86_64"; WRAPPER_EXTENSION = framework; }; name = Release; @@ -230,13 +228,12 @@ 1DEB91B208733DA50010E9CD /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_OPTIMIZATION_LEVEL = 0; GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.6; + MACOSX_DEPLOYMENT_TARGET = 10.7; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; }; @@ -245,13 +242,12 @@ 1DEB91B308733DA50010E9CD /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; CODE_SIGN_IDENTITY = "3rd Party Mac Developer Application"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.6; + MACOSX_DEPLOYMENT_TARGET = 10.7; PROVISIONING_PROFILE = ""; SDKROOT = macosx; }; diff --git a/AVFoundation/AVFoundation.xcodeproj/project.xcworkspace/xcshareddata/AVFoundation.xccheckout b/AVFoundation/AVFoundation.xcodeproj/project.xcworkspace/xcshareddata/AVFoundation.xccheckout new file mode 100644 index 00000000..b792d443 --- /dev/null +++ b/AVFoundation/AVFoundation.xcodeproj/project.xcworkspace/xcshareddata/AVFoundation.xccheckout @@ -0,0 +1,50 @@ + + + + + IDESourceControlProjectFavoriteDictionaryKey + + IDESourceControlProjectIdentifier + D07BFBE5-D22F-4E7C-8EC3-D1129799E6A7 + IDESourceControlProjectName + AVFoundation + IDESourceControlProjectOriginsDictionary + + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + svn://dev.iconfactory.net/Projects/Software/UIKit/trunk + + IDESourceControlProjectPath + AVFoundation/AVFoundation.xcodeproj/project.xcworkspace + IDESourceControlProjectRelativeInstallPathDictionary + + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + ../../.. + + IDESourceControlProjectRepositoryRootDictionary + + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + svn://dev.iconfactory.net/Projects/Software + + IDESourceControlProjectURL + svn://dev.iconfactory.net/Projects/Software/UIKit/trunk/AVFoundation/AVFoundation.xcodeproj + IDESourceControlProjectVersion + 110 + IDESourceControlProjectWCCIdentifier + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + IDESourceControlProjectWCConfigurations + + + IDESourceControlRepositoryBranchesRelativeLocationKey + UIKit/branches + IDESourceControlRepositoryExtensionIdentifierKey + public.vcs.subversion + IDESourceControlRepositoryTrunkRelativeLocationKey + UIKit/trunk + IDESourceControlWCCIdentifierKey + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + IDESourceControlWCCName + UIKit + + + + diff --git a/AddressBookUI/AddressBookUI.xcodeproj/project.pbxproj b/AddressBookUI/AddressBookUI.xcodeproj/project.pbxproj index 2c79c466..9f809cfc 100644 --- a/AddressBookUI/AddressBookUI.xcodeproj/project.pbxproj +++ b/AddressBookUI/AddressBookUI.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 45; + objectVersion = 46; objects = { /* Begin PBXBuildFile section */ @@ -166,8 +166,11 @@ /* Begin PBXProject section */ 0867D690FE84028FC02AAC07 /* Project object */ = { isa = PBXProject; + attributes = { + LastUpgradeCheck = 0510; + }; buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "AddressBookUI" */; - compatibilityVersion = "Xcode 3.1"; + compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 1; knownRegions = ( @@ -278,26 +281,24 @@ 1DEB91B208733DA50010E9CD /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_OPTIMIZATION_LEVEL = 0; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; - SDKROOT = macosx10.6; + SDKROOT = macosx; }; name = Debug; }; 1DEB91B308733DA50010E9CD /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; PREBINDING = NO; - SDKROOT = macosx10.6; + SDKROOT = macosx; }; name = Release; }; diff --git a/AddressBookUI/AddressBookUI.xcodeproj/project.xcworkspace/xcshareddata/AddressBookUI.xccheckout b/AddressBookUI/AddressBookUI.xcodeproj/project.xcworkspace/xcshareddata/AddressBookUI.xccheckout new file mode 100644 index 00000000..73a9ff5b --- /dev/null +++ b/AddressBookUI/AddressBookUI.xcodeproj/project.xcworkspace/xcshareddata/AddressBookUI.xccheckout @@ -0,0 +1,50 @@ + + + + + IDESourceControlProjectFavoriteDictionaryKey + + IDESourceControlProjectIdentifier + 9F3968B1-EE4C-4FC9-9142-CB68E7E1F3AC + IDESourceControlProjectName + AddressBookUI + IDESourceControlProjectOriginsDictionary + + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + svn://dev.iconfactory.net/Projects/Software/UIKit/trunk + + IDESourceControlProjectPath + AddressBookUI/AddressBookUI.xcodeproj/project.xcworkspace + IDESourceControlProjectRelativeInstallPathDictionary + + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + ../../.. + + IDESourceControlProjectRepositoryRootDictionary + + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + svn://dev.iconfactory.net/Projects/Software + + IDESourceControlProjectURL + svn://dev.iconfactory.net/Projects/Software/UIKit/trunk/AddressBookUI/AddressBookUI.xcodeproj + IDESourceControlProjectVersion + 110 + IDESourceControlProjectWCCIdentifier + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + IDESourceControlProjectWCConfigurations + + + IDESourceControlRepositoryBranchesRelativeLocationKey + UIKit/branches + IDESourceControlRepositoryExtensionIdentifierKey + public.vcs.subversion + IDESourceControlRepositoryTrunkRelativeLocationKey + UIKit/trunk + IDESourceControlWCCIdentifierKey + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + IDESourceControlWCCName + UIKit + + + + diff --git a/AssetsLibrary/AssetsLibrary.xcodeproj/project.pbxproj b/AssetsLibrary/AssetsLibrary.xcodeproj/project.pbxproj index 250c53bf..daf140b8 100644 --- a/AssetsLibrary/AssetsLibrary.xcodeproj/project.pbxproj +++ b/AssetsLibrary/AssetsLibrary.xcodeproj/project.pbxproj @@ -161,7 +161,7 @@ 0867D690FE84028FC02AAC07 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0460; + LastUpgradeCheck = 0510; }; buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "AssetsLibrary" */; compatibilityVersion = "Xcode 3.2"; @@ -227,7 +227,6 @@ INSTALL_PATH = "@executable_path/../Frameworks"; PRODUCT_NAME = AssetsLibrary; SYMROOT = ../build; - VALID_ARCHS = "i386 x86_64"; WRAPPER_EXTENSION = framework; }; name = Debug; @@ -248,7 +247,6 @@ INSTALL_PATH = "@executable_path/../Frameworks"; PRODUCT_NAME = AssetsLibrary; SYMROOT = ../build; - VALID_ARCHS = "i386 x86_64"; WRAPPER_EXTENSION = framework; }; name = Release; @@ -256,13 +254,12 @@ 1DEB91B208733DA50010E9CD /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_OPTIMIZATION_LEVEL = 0; GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.6; + MACOSX_DEPLOYMENT_TARGET = 10.7; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; }; @@ -271,13 +268,12 @@ 1DEB91B308733DA50010E9CD /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - CODE_SIGN_IDENTITY = "3rd Party Mac Developer Application"; + CODE_SIGN_IDENTITY = "Developer ID Application: The Iconfactory"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.6; + MACOSX_DEPLOYMENT_TARGET = 10.7; PROVISIONING_PROFILE = ""; SDKROOT = macosx; }; diff --git a/AssetsLibrary/AssetsLibrary.xcodeproj/project.xcworkspace/xcshareddata/AssetsLibrary.xccheckout b/AssetsLibrary/AssetsLibrary.xcodeproj/project.xcworkspace/xcshareddata/AssetsLibrary.xccheckout new file mode 100644 index 00000000..0d001db3 --- /dev/null +++ b/AssetsLibrary/AssetsLibrary.xcodeproj/project.xcworkspace/xcshareddata/AssetsLibrary.xccheckout @@ -0,0 +1,50 @@ + + + + + IDESourceControlProjectFavoriteDictionaryKey + + IDESourceControlProjectIdentifier + 325CD246-7DA7-4A70-BA15-8AA78CD07E08 + IDESourceControlProjectName + AssetsLibrary + IDESourceControlProjectOriginsDictionary + + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + svn://dev.iconfactory.net/Projects/Software/UIKit/trunk + + IDESourceControlProjectPath + AssetsLibrary/AssetsLibrary.xcodeproj/project.xcworkspace + IDESourceControlProjectRelativeInstallPathDictionary + + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + ../../.. + + IDESourceControlProjectRepositoryRootDictionary + + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + svn://dev.iconfactory.net/Projects/Software + + IDESourceControlProjectURL + svn://dev.iconfactory.net/Projects/Software/UIKit/trunk/AssetsLibrary/AssetsLibrary.xcodeproj + IDESourceControlProjectVersion + 110 + IDESourceControlProjectWCCIdentifier + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + IDESourceControlProjectWCConfigurations + + + IDESourceControlRepositoryBranchesRelativeLocationKey + UIKit/branches + IDESourceControlRepositoryExtensionIdentifierKey + public.vcs.subversion + IDESourceControlRepositoryTrunkRelativeLocationKey + UIKit/trunk + IDESourceControlWCCIdentifierKey + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + IDESourceControlWCCName + UIKit + + + + diff --git a/Examples/BigApple/BigApple.xcodeproj/project.pbxproj b/Examples/BigApple/BigApple.xcodeproj/project.pbxproj index 89bb9fb9..af480485 100644 --- a/Examples/BigApple/BigApple.xcodeproj/project.pbxproj +++ b/Examples/BigApple/BigApple.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 45; + objectVersion = 46; objects = { /* Begin PBXBuildFile section */ @@ -211,8 +211,11 @@ /* Begin PBXProject section */ 29B97313FDCFA39411CA2CEA /* Project object */ = { isa = PBXProject; + attributes = { + LastUpgradeCheck = 0510; + }; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "BigApple" */; - compatibilityVersion = "Xcode 3.1"; + compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 1; knownRegions = ( @@ -320,6 +323,7 @@ INFOPLIST_FILE = "BigApple-Info.plist"; INSTALL_PATH = "$(HOME)/Applications"; PRODUCT_NAME = BigApple; + SDKROOT = macosx; }; name = Debug; }; @@ -339,32 +343,31 @@ INFOPLIST_FILE = "BigApple-Info.plist"; INSTALL_PATH = "$(HOME)/Applications"; PRODUCT_NAME = BigApple; + SDKROOT = macosx; }; name = Release; }; C01FCF4F08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_OPTIMIZATION_LEVEL = 0; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; - SDKROOT = macosx10.6; + SDKROOT = macosx; }; name = Debug; }; C01FCF5008A954540054247B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; PREBINDING = NO; - SDKROOT = macosx10.6; + SDKROOT = macosx; }; name = Release; }; diff --git a/Examples/BigApple/BigApple.xcodeproj/project.xcworkspace/xcshareddata/BigApple.xccheckout b/Examples/BigApple/BigApple.xcodeproj/project.xcworkspace/xcshareddata/BigApple.xccheckout new file mode 100644 index 00000000..18129e6f --- /dev/null +++ b/Examples/BigApple/BigApple.xcodeproj/project.xcworkspace/xcshareddata/BigApple.xccheckout @@ -0,0 +1,50 @@ + + + + + IDESourceControlProjectFavoriteDictionaryKey + + IDESourceControlProjectIdentifier + 014C1F5D-2A9E-449E-85EA-21CA406C7C86 + IDESourceControlProjectName + BigApple + IDESourceControlProjectOriginsDictionary + + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + svn://dev.iconfactory.net/Projects/Software/UIKit/trunk + + IDESourceControlProjectPath + Examples/BigApple/BigApple.xcodeproj/project.xcworkspace + IDESourceControlProjectRelativeInstallPathDictionary + + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + ../../../.. + + IDESourceControlProjectRepositoryRootDictionary + + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + svn://dev.iconfactory.net/Projects/Software + + IDESourceControlProjectURL + svn://dev.iconfactory.net/Projects/Software/UIKit/trunk/Examples/BigApple/BigApple.xcodeproj + IDESourceControlProjectVersion + 110 + IDESourceControlProjectWCCIdentifier + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + IDESourceControlProjectWCConfigurations + + + IDESourceControlRepositoryBranchesRelativeLocationKey + UIKit/branches + IDESourceControlRepositoryExtensionIdentifierKey + public.vcs.subversion + IDESourceControlRepositoryTrunkRelativeLocationKey + UIKit/trunk + IDESourceControlWCCIdentifierKey + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + IDESourceControlWCCName + UIKit + + + + diff --git a/Examples/MultiApple/MultiApple.xcodeproj/project.pbxproj b/Examples/MultiApple/MultiApple.xcodeproj/project.pbxproj index 248bd6d5..21a61483 100644 --- a/Examples/MultiApple/MultiApple.xcodeproj/project.pbxproj +++ b/Examples/MultiApple/MultiApple.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 45; + objectVersion = 46; objects = { /* Begin PBXBuildFile section */ @@ -298,8 +298,11 @@ /* Begin PBXProject section */ 0867D690FE84028FC02AAC07 /* Project object */ = { isa = PBXProject; + attributes = { + LastUpgradeCheck = 0510; + }; buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "MultiApple" */; - compatibilityVersion = "Xcode 3.1"; + compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 1; knownRegions = ( @@ -499,7 +502,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_UNIVERSAL_IPHONE_OS)"; CODE_SIGN_IDENTITY = "iPhone Developer"; COPY_PHASE_STRIP = NO; DSTROOT = "/tmp/$(PROJECT_NAME).dst"; @@ -537,7 +539,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_UNIVERSAL_IPHONE_OS)"; CODE_SIGN_IDENTITY = "iPhone Developer"; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; @@ -575,26 +576,24 @@ 1DEB91B208733DA50010E9CD /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_OPTIMIZATION_LEVEL = 0; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; - SDKROOT = macosx10.6; + SDKROOT = macosx; }; name = Debug; }; 1DEB91B308733DA50010E9CD /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; PREBINDING = NO; - SDKROOT = macosx10.6; + SDKROOT = macosx; }; name = Release; }; diff --git a/Examples/MultiApple/MultiApple.xcodeproj/project.xcworkspace/xcshareddata/MultiApple.xccheckout b/Examples/MultiApple/MultiApple.xcodeproj/project.xcworkspace/xcshareddata/MultiApple.xccheckout new file mode 100644 index 00000000..03c2d0a0 --- /dev/null +++ b/Examples/MultiApple/MultiApple.xcodeproj/project.xcworkspace/xcshareddata/MultiApple.xccheckout @@ -0,0 +1,50 @@ + + + + + IDESourceControlProjectFavoriteDictionaryKey + + IDESourceControlProjectIdentifier + FBBFB75C-FE54-46A5-ACD2-594A4A0973EE + IDESourceControlProjectName + MultiApple + IDESourceControlProjectOriginsDictionary + + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + svn://dev.iconfactory.net/Projects/Software/UIKit/trunk + + IDESourceControlProjectPath + Examples/MultiApple/MultiApple.xcodeproj/project.xcworkspace + IDESourceControlProjectRelativeInstallPathDictionary + + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + ../../../.. + + IDESourceControlProjectRepositoryRootDictionary + + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + svn://dev.iconfactory.net/Projects/Software + + IDESourceControlProjectURL + svn://dev.iconfactory.net/Projects/Software/UIKit/trunk/Examples/MultiApple/MultiApple.xcodeproj + IDESourceControlProjectVersion + 110 + IDESourceControlProjectWCCIdentifier + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + IDESourceControlProjectWCConfigurations + + + IDESourceControlRepositoryBranchesRelativeLocationKey + UIKit/branches + IDESourceControlRepositoryExtensionIdentifierKey + public.vcs.subversion + IDESourceControlRepositoryTrunkRelativeLocationKey + UIKit/trunk + IDESourceControlWCCIdentifierKey + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + IDESourceControlWCCName + UIKit + + + + diff --git a/Examples/NavBarUpdates/NavBarUpdates.xcodeproj/project.pbxproj b/Examples/NavBarUpdates/NavBarUpdates.xcodeproj/project.pbxproj index 8ae79a00..414453a8 100644 --- a/Examples/NavBarUpdates/NavBarUpdates.xcodeproj/project.pbxproj +++ b/Examples/NavBarUpdates/NavBarUpdates.xcodeproj/project.pbxproj @@ -188,6 +188,7 @@ 38E523B81339731100E041B3 /* Project object */ = { isa = PBXProject; attributes = { + LastUpgradeCheck = 0510; ORGANIZATIONNAME = "XPlatform Inc"; }; buildConfigurationList = 38E523BB1339731100E041B3 /* Build configuration list for PBXProject "NavBarUpdates" */; @@ -289,7 +290,12 @@ 38E523DD1339731100E041B3 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = DEBUG; @@ -297,6 +303,9 @@ GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; @@ -307,11 +316,19 @@ 38E523DE1339731100E041B3 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.6; SDKROOT = macosx; diff --git a/Examples/NavBarUpdates/NavBarUpdates.xcodeproj/project.xcworkspace/xcshareddata/NavBarUpdates.xccheckout b/Examples/NavBarUpdates/NavBarUpdates.xcodeproj/project.xcworkspace/xcshareddata/NavBarUpdates.xccheckout new file mode 100644 index 00000000..7bb718c1 --- /dev/null +++ b/Examples/NavBarUpdates/NavBarUpdates.xcodeproj/project.xcworkspace/xcshareddata/NavBarUpdates.xccheckout @@ -0,0 +1,50 @@ + + + + + IDESourceControlProjectFavoriteDictionaryKey + + IDESourceControlProjectIdentifier + 337C535E-8A84-4C65-B4DE-C440FF9F5D7A + IDESourceControlProjectName + NavBarUpdates + IDESourceControlProjectOriginsDictionary + + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + svn://dev.iconfactory.net/Projects/Software/UIKit/trunk + + IDESourceControlProjectPath + Examples/NavBarUpdates/NavBarUpdates.xcodeproj/project.xcworkspace + IDESourceControlProjectRelativeInstallPathDictionary + + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + ../../../.. + + IDESourceControlProjectRepositoryRootDictionary + + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + svn://dev.iconfactory.net/Projects/Software + + IDESourceControlProjectURL + svn://dev.iconfactory.net/Projects/Software/UIKit/trunk/Examples/NavBarUpdates/NavBarUpdates.xcodeproj + IDESourceControlProjectVersion + 110 + IDESourceControlProjectWCCIdentifier + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + IDESourceControlProjectWCConfigurations + + + IDESourceControlRepositoryBranchesRelativeLocationKey + UIKit/branches + IDESourceControlRepositoryExtensionIdentifierKey + public.vcs.subversion + IDESourceControlRepositoryTrunkRelativeLocationKey + UIKit/trunk + IDESourceControlWCCIdentifierKey + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + IDESourceControlWCCName + UIKit + + + + diff --git a/MediaPlayer/MediaPlayer.xcodeproj/project.pbxproj b/MediaPlayer/MediaPlayer.xcodeproj/project.pbxproj index 2c2a264a..b8a43e35 100644 --- a/MediaPlayer/MediaPlayer.xcodeproj/project.pbxproj +++ b/MediaPlayer/MediaPlayer.xcodeproj/project.pbxproj @@ -13,8 +13,8 @@ 14EFB1BB1211DB5300D19B0C /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 14EFB1BA1211DB5300D19B0C /* Cocoa.framework */; }; 4C1677D913C70F1A00814195 /* MPMoviePlayerController.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C1677D713C70F1900814195 /* MPMoviePlayerController.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4C1677DA13C70F1A00814195 /* MPMoviePlayerController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C1677D813C70F1900814195 /* MPMoviePlayerController.m */; }; - 4C16781613C71E4900814195 /* MPMediaPlayback.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C16781513C71E4900814195 /* MPMediaPlayback.h */; }; - 4C16781A13C71E6200814195 /* UIInternalMovieView.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C16781813C71E6200814195 /* UIInternalMovieView.h */; }; + 4C16781613C71E4900814195 /* MPMediaPlayback.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C16781513C71E4900814195 /* MPMediaPlayback.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4C16781A13C71E6200814195 /* UIInternalMovieView.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C16781813C71E6200814195 /* UIInternalMovieView.h */; settings = {ATTRIBUTES = (Private, ); }; }; 4C16781B13C71E6200814195 /* UIInternalMovieView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C16781913C71E6200814195 /* UIInternalMovieView.m */; }; 4C16787D13C71FB900814195 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C16787C13C71FB900814195 /* UIKit.framework */; }; 4C16789F13C7206500814195 /* QTKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C16789E13C7206500814195 /* QTKit.framework */; }; @@ -191,7 +191,7 @@ 0867D690FE84028FC02AAC07 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0430; + LastUpgradeCheck = 0510; }; buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "MediaPlayer" */; compatibilityVersion = "Xcode 3.2"; @@ -306,7 +306,6 @@ 1DEB91B208733DA50010E9CD /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_OPTIMIZATION_LEVEL = 0; GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; @@ -321,7 +320,6 @@ 1DEB91B308733DA50010E9CD /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; CODE_SIGN_IDENTITY = "3rd Party Mac Developer Application"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; diff --git a/MediaPlayer/MediaPlayer.xcodeproj/project.xcworkspace/xcshareddata/MediaPlayer.xccheckout b/MediaPlayer/MediaPlayer.xcodeproj/project.xcworkspace/xcshareddata/MediaPlayer.xccheckout new file mode 100644 index 00000000..08ea7606 --- /dev/null +++ b/MediaPlayer/MediaPlayer.xcodeproj/project.xcworkspace/xcshareddata/MediaPlayer.xccheckout @@ -0,0 +1,50 @@ + + + + + IDESourceControlProjectFavoriteDictionaryKey + + IDESourceControlProjectIdentifier + 25E1A0F8-8F0F-446A-BECC-FE2996734ECD + IDESourceControlProjectName + MediaPlayer + IDESourceControlProjectOriginsDictionary + + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + svn://dev.iconfactory.net/Projects/Software/UIKit/trunk + + IDESourceControlProjectPath + MediaPlayer/MediaPlayer.xcodeproj/project.xcworkspace + IDESourceControlProjectRelativeInstallPathDictionary + + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + ../../.. + + IDESourceControlProjectRepositoryRootDictionary + + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + svn://dev.iconfactory.net/Projects/Software + + IDESourceControlProjectURL + svn://dev.iconfactory.net/Projects/Software/UIKit/trunk/MediaPlayer/MediaPlayer.xcodeproj + IDESourceControlProjectVersion + 110 + IDESourceControlProjectWCCIdentifier + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + IDESourceControlProjectWCConfigurations + + + IDESourceControlRepositoryBranchesRelativeLocationKey + UIKit/branches + IDESourceControlRepositoryExtensionIdentifierKey + public.vcs.subversion + IDESourceControlRepositoryTrunkRelativeLocationKey + UIKit/trunk + IDESourceControlWCCIdentifierKey + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + IDESourceControlWCCName + UIKit + + + + diff --git a/MessageUI/Classes/MFMailComposeViewController.h b/MessageUI/Classes/MFMailComposeViewController.h index 0fc059f4..8b7bc319 100644 --- a/MessageUI/Classes/MFMailComposeViewController.h +++ b/MessageUI/Classes/MFMailComposeViewController.h @@ -44,11 +44,7 @@ typedef enum MFMailComposeResult MFMailComposeResult; - (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error; @end -@interface MFMailComposeViewController : UINavigationController { -@private - __unsafe_unretained id _mailComposeDelegate; -} - +@interface MFMailComposeViewController : UINavigationController + (BOOL)canSendMail; - (void)setSubject:(NSString*)subject; @@ -58,6 +54,5 @@ typedef enum MFMailComposeResult MFMailComposeResult; - (void)setBccRecipients:(NSArray*)bccRecipients; - (void)addAttachmentData:(NSData*)attachment mimeType:(NSString*)mimeType fileName:(NSString*)filename; -@property (nonatomic,assign) id mailComposeDelegate; - +@property (nonatomic, assign) id mailComposeDelegate; @end diff --git a/MessageUI/Classes/MFMailComposeViewController.m b/MessageUI/Classes/MFMailComposeViewController.m index 985a373c..61308c96 100644 --- a/MessageUI/Classes/MFMailComposeViewController.m +++ b/MessageUI/Classes/MFMailComposeViewController.m @@ -30,7 +30,6 @@ #import "MFMailComposeViewController.h" @implementation MFMailComposeViewController -@synthesize mailComposeDelegate=_mailComposeDelegate; + (BOOL)canSendMail { diff --git a/MessageUI/MFMessageComposeViewController.h b/MessageUI/MFMessageComposeViewController.h index ccd18f42..56f5cd9f 100644 --- a/MessageUI/MFMessageComposeViewController.h +++ b/MessageUI/MFMessageComposeViewController.h @@ -42,18 +42,12 @@ enum MessageComposeResult { }; typedef enum MessageComposeResult MessageComposeResult; -@interface MFMessageComposeViewController : NSObject { - __unsafe_unretained id _messageComposeDelegate; - NSArray *_recipients; - NSString *_body; -} - +@interface MFMessageComposeViewController : NSObject + (BOOL)canSendText; @property (nonatomic, assign) id messageComposeDelegate; -@property(nonatomic,copy) NSArray *recipients; -@property(nonatomic,copy) NSString *body; - +@property(nonatomic, copy) NSArray *recipients; +@property(nonatomic, copy) NSString *body; @end diff --git a/MessageUI/MFMessageComposeViewController.m b/MessageUI/MFMessageComposeViewController.m index 8c23660d..5375dec6 100644 --- a/MessageUI/MFMessageComposeViewController.m +++ b/MessageUI/MFMessageComposeViewController.m @@ -39,10 +39,6 @@ @implementation MFMessageComposeViewController -@synthesize messageComposeDelegate = _messageComposeDelegate; -@synthesize recipients = _recipients; -@synthesize body = _body; - + (BOOL)canSendText { return NO; // most likely we can't send messages on a mac ;) } diff --git a/MessageUI/MessageUI.xcodeproj/project.pbxproj b/MessageUI/MessageUI.xcodeproj/project.pbxproj index 243474ad..c4d0e39e 100644 --- a/MessageUI/MessageUI.xcodeproj/project.pbxproj +++ b/MessageUI/MessageUI.xcodeproj/project.pbxproj @@ -187,7 +187,7 @@ 0867D690FE84028FC02AAC07 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0460; + LastUpgradeCheck = 0510; }; buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "MessageUI" */; compatibilityVersion = "Xcode 3.2"; @@ -286,7 +286,6 @@ INSTALL_PATH = "@executable_path/../Frameworks"; PRODUCT_NAME = MessageUI; SYMROOT = ../build; - VALID_ARCHS = "i386 x86_64"; WRAPPER_EXTENSION = framework; }; name = Debug; @@ -308,7 +307,6 @@ INSTALL_PATH = "@executable_path/../Frameworks"; PRODUCT_NAME = MessageUI; SYMROOT = ../build; - VALID_ARCHS = "i386 x86_64"; WRAPPER_EXTENSION = framework; }; name = Release; @@ -316,13 +314,12 @@ 1DEB91B208733DA50010E9CD /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_OPTIMIZATION_LEVEL = 0; GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.6; + MACOSX_DEPLOYMENT_TARGET = 10.7; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; }; @@ -331,13 +328,12 @@ 1DEB91B308733DA50010E9CD /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - CODE_SIGN_IDENTITY = "3rd Party Mac Developer Application"; + CODE_SIGN_IDENTITY = "Developer ID Application: The Iconfactory"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.6; + MACOSX_DEPLOYMENT_TARGET = 10.7; PROVISIONING_PROFILE = ""; SDKROOT = macosx; }; diff --git a/MessageUI/MessageUI.xcodeproj/project.xcworkspace/xcshareddata/MessageUI.xccheckout b/MessageUI/MessageUI.xcodeproj/project.xcworkspace/xcshareddata/MessageUI.xccheckout new file mode 100644 index 00000000..7ccac3ca --- /dev/null +++ b/MessageUI/MessageUI.xcodeproj/project.xcworkspace/xcshareddata/MessageUI.xccheckout @@ -0,0 +1,50 @@ + + + + + IDESourceControlProjectFavoriteDictionaryKey + + IDESourceControlProjectIdentifier + 0B0E74CD-B913-4D2E-BAD0-73F7E73D7985 + IDESourceControlProjectName + MessageUI + IDESourceControlProjectOriginsDictionary + + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + svn://dev.iconfactory.net/Projects/Software/UIKit/trunk + + IDESourceControlProjectPath + MessageUI/MessageUI.xcodeproj/project.xcworkspace + IDESourceControlProjectRelativeInstallPathDictionary + + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + ../../.. + + IDESourceControlProjectRepositoryRootDictionary + + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + svn://dev.iconfactory.net/Projects/Software + + IDESourceControlProjectURL + svn://dev.iconfactory.net/Projects/Software/UIKit/trunk/MessageUI/MessageUI.xcodeproj + IDESourceControlProjectVersion + 110 + IDESourceControlProjectWCCIdentifier + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + IDESourceControlProjectWCConfigurations + + + IDESourceControlRepositoryBranchesRelativeLocationKey + UIKit/branches + IDESourceControlRepositoryExtensionIdentifierKey + public.vcs.subversion + IDESourceControlRepositoryTrunkRelativeLocationKey + UIKit/trunk + IDESourceControlWCCIdentifierKey + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + IDESourceControlWCCName + UIKit + + + + diff --git a/MessageUI/MessageUI_Prefix.pch b/MessageUI/MessageUI_Prefix.pch index 73ffda54..a9ca302e 100644 --- a/MessageUI/MessageUI_Prefix.pch +++ b/MessageUI/MessageUI_Prefix.pch @@ -30,13 +30,3 @@ #ifdef __OBJC__ #import #endif - -// If ARC is not enabled, declare empty ARC directives to supress compiler errors -#ifndef __has_feature - #define __has_feature(x) 0 // Compatibility with non-clang compilers. -#endif - -#if !__has_feature(objc_arc) - #define __unsafe_unretained - #define __bridge -#endif diff --git a/StoreKit/StoreKit.xcodeproj/project.pbxproj b/StoreKit/StoreKit.xcodeproj/project.pbxproj index 7fb2d99c..91a7ded2 100644 --- a/StoreKit/StoreKit.xcodeproj/project.pbxproj +++ b/StoreKit/StoreKit.xcodeproj/project.pbxproj @@ -175,7 +175,7 @@ 0867D690FE84028FC02AAC07 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0450; + LastUpgradeCheck = 0500; }; buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "StoreKit" */; compatibilityVersion = "Xcode 3.2"; @@ -274,13 +274,12 @@ 1DEB91B208733DA50010E9CD /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_OPTIMIZATION_LEVEL = 0; GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.6; + MACOSX_DEPLOYMENT_TARGET = 10.7; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; }; @@ -289,13 +288,12 @@ 1DEB91B308733DA50010E9CD /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - CODE_SIGN_IDENTITY = "3rd Party Mac Developer Application"; + CODE_SIGN_IDENTITY = "Developer ID Application: The Iconfactory"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.6; + MACOSX_DEPLOYMENT_TARGET = 10.7; PROVISIONING_PROFILE = ""; SDKROOT = macosx; }; diff --git a/StoreKit/StoreKit.xcodeproj/project.xcworkspace/xcshareddata/StoreKit.xccheckout b/StoreKit/StoreKit.xcodeproj/project.xcworkspace/xcshareddata/StoreKit.xccheckout new file mode 100644 index 00000000..5be8e98e --- /dev/null +++ b/StoreKit/StoreKit.xcodeproj/project.xcworkspace/xcshareddata/StoreKit.xccheckout @@ -0,0 +1,50 @@ + + + + + IDESourceControlProjectFavoriteDictionaryKey + + IDESourceControlProjectIdentifier + 7123AA42-C57B-4F08-87C2-5C3ADE24923A + IDESourceControlProjectName + StoreKit + IDESourceControlProjectOriginsDictionary + + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + svn://dev.iconfactory.net/Projects/Software/UIKit/trunk + + IDESourceControlProjectPath + StoreKit/StoreKit.xcodeproj/project.xcworkspace + IDESourceControlProjectRelativeInstallPathDictionary + + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + ../../.. + + IDESourceControlProjectRepositoryRootDictionary + + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + svn://dev.iconfactory.net/Projects/Software + + IDESourceControlProjectURL + svn://dev.iconfactory.net/Projects/Software/UIKit/trunk/StoreKit/StoreKit.xcodeproj + IDESourceControlProjectVersion + 110 + IDESourceControlProjectWCCIdentifier + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + IDESourceControlProjectWCConfigurations + + + IDESourceControlRepositoryBranchesRelativeLocationKey + UIKit/branches + IDESourceControlRepositoryExtensionIdentifierKey + public.vcs.subversion + IDESourceControlRepositoryTrunkRelativeLocationKey + UIKit/trunk + IDESourceControlWCCIdentifierKey + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + IDESourceControlWCCName + UIKit + + + + diff --git a/StoreKit/StoreKit_Prefix.pch b/StoreKit/StoreKit_Prefix.pch index 73ffda54..a9ca302e 100644 --- a/StoreKit/StoreKit_Prefix.pch +++ b/StoreKit/StoreKit_Prefix.pch @@ -30,13 +30,3 @@ #ifdef __OBJC__ #import #endif - -// If ARC is not enabled, declare empty ARC directives to supress compiler errors -#ifndef __has_feature - #define __has_feature(x) 0 // Compatibility with non-clang compilers. -#endif - -#if !__has_feature(objc_arc) - #define __unsafe_unretained - #define __bridge -#endif diff --git a/UIKit/Classes/NSFetchedResultsController.h b/UIKit/Classes/NSFetchedResultsController.h deleted file mode 100644 index c17d8541..00000000 --- a/UIKit/Classes/NSFetchedResultsController.h +++ /dev/null @@ -1,116 +0,0 @@ -// -// NSFetchedResultsController.h -// UIKit -// -// Created by Peter Steinberger on 23.03.11. -// -/* - * Copyright (c) 2011, The Iconfactory. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of The Iconfactory nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE ICONFACTORY BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - - -#import -#import - -//#ifdef NSCoreDataVersionNumber10_5 -@protocol NSFetchedResultsControllerDelegate; - -@class NSFetchRequest; -@class NSManagedObjectContext; - - -@interface NSFetchedResultsController : NSObject { - __unsafe_unretained id _delegate; - NSFetchRequest *_fetchRequest; - NSManagedObjectContext *_managedObjectContext; - NSArray *_fetchedObjects; // we don't yet support sections! - - // stubs - NSString *_sectionNameKeyPath; - NSString *_sectionNameKey; - NSString *_cacheName; -} - -- (id)initWithFetchRequest:(NSFetchRequest *)fetchRequest managedObjectContext: (NSManagedObjectContext *)context sectionNameKeyPath:(NSString *)sectionNameKeyPath cacheName:(NSString *)name; - -- (BOOL)performFetch:(NSError **)error; - -@property (nonatomic, readonly) NSFetchRequest *fetchRequest; -@property (nonatomic, readonly) NSManagedObjectContext *managedObjectContext; -@property (nonatomic, readonly) NSString *sectionNameKeyPath; -@property (nonatomic, readonly) NSString *cacheName; -@property(nonatomic, assign) id delegate; -+ (void)deleteCacheWithName:(NSString *)name; - -// accessing objects -@property (nonatomic, readonly) NSArray *fetchedObjects; -- (id)objectAtIndexPath:(NSIndexPath *)indexPath; -- (NSIndexPath *)indexPathForObject:(id)object; - -- (NSString *)sectionIndexTitleForSectionName:(NSString *)sectionName; -@property (nonatomic, readonly) NSArray *sectionIndexTitles; -@property (nonatomic, readonly) NSArray *sections; -- (NSInteger)sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)sectionIndex; - -@end - - -@protocol NSFetchedResultsSectionInfo - -@property (nonatomic, readonly) NSString *name; -@property (nonatomic, readonly) NSString *indexTitle; -@property (nonatomic, readonly) NSUInteger numberOfObjects; -@property (nonatomic, readonly) NSArray *objects; - -@end - -@protocol NSFetchedResultsControllerDelegate - -enum { - NSFetchedResultsChangeInsert = 1, - NSFetchedResultsChangeDelete = 2, - NSFetchedResultsChangeMove = 3, - NSFetchedResultsChangeUpdate = 4 - -}; -typedef NSUInteger NSFetchedResultsChangeType; - -@optional - -- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath; - -- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id )sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type; - -- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller; -- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller; - -- (NSString *)controller:(NSFetchedResultsController *)controller sectionIndexTitleForSectionName:(NSString *)sectionName; - -@end - -//#endif diff --git a/UIKit/Classes/NSFetchedResultsController.m b/UIKit/Classes/NSFetchedResultsController.m deleted file mode 100644 index 7ceaa3ff..00000000 --- a/UIKit/Classes/NSFetchedResultsController.m +++ /dev/null @@ -1,109 +0,0 @@ -// -// NSFetchedResultsController.m -// UIKit -// -// Created by Peter Steinberger on 23.03.11. -// -/* - * Copyright (c) 2011, The Iconfactory. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of The Iconfactory nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE ICONFACTORY BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import "NSFetchedResultsController.h" - -//#ifdef NSCoreDataVersionNumber10_5 - -#import "NSIndexPath+UITableView.h" - -@implementation NSFetchedResultsController - -@synthesize delegate = _delegate; -@synthesize fetchRequest = _fetchRequest; -@synthesize managedObjectContext = _managedObjectContext; -@synthesize fetchedObjects = _fetchedObjects; -@synthesize cacheName = _cacheName, sectionNameKeyPath = _sectionNameKeyPath; - -- (id)initWithFetchRequest:(NSFetchRequest *)fetchRequest managedObjectContext: (NSManagedObjectContext *)context sectionNameKeyPath:(NSString *)sectionNameKeyPath cacheName:(NSString *)name { - if ((self = [super init])) { - _fetchRequest = [fetchRequest retain]; - _managedObjectContext = [context retain]; - } - return self; -} - -- (void)dealloc { - _delegate = nil; - [_fetchRequest release]; - [_managedObjectContext release]; - [_fetchedObjects release]; - [super dealloc]; -} - -- (BOOL)performFetch:(NSError **)error { - [_fetchedObjects release]; - _fetchedObjects = [[_managedObjectContext executeFetchRequest:_fetchRequest error:error] retain]; - - return YES; -} - -- (id)objectAtIndexPath:(NSIndexPath *)indexPath { - return [_fetchedObjects objectAtIndex:indexPath.row]; -} - -- (NSIndexPath *)indexPathForObject:(id)object { - NSUInteger objectIndex = [_fetchedObjects indexOfObject:object]; - return [NSIndexPath indexPathForRow:objectIndex inSection:0]; -} - -// stubs - -+ (void)deleteCacheWithName:(NSString *)name { - // stub -} - - -- (NSString *)sectionIndexTitleForSectionName:(NSString *)sectionName { - return @"UNIMPLEMENTED"; -} - -- (NSArray *)sectionIndexTitles { - // stub - return [NSArray array]; -} - -- (NSArray *)sections { - // stub - return [NSArray array]; -} - -- (NSInteger)sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)sectionIndex { - return 0; -} - -@end - -//#endif diff --git a/UIKit/Classes/UIAcceleration.h b/UIKit/Classes/UIAcceleration.h index 6d09c1e8..3b806754 100644 --- a/UIKit/Classes/UIAcceleration.h +++ b/UIKit/Classes/UIAcceleration.h @@ -31,16 +31,9 @@ typedef double UIAccelerationValue; -@interface UIAcceleration : NSObject { - UIAccelerationValue _x; - UIAccelerationValue _y; - UIAccelerationValue _z; - NSTimeInterval _timestamp; -} - +@interface UIAcceleration : NSObject @property (nonatomic, readonly) UIAccelerationValue x; @property (nonatomic, readonly) UIAccelerationValue y; @property (nonatomic, readonly) UIAccelerationValue z; @property (nonatomic, readonly) NSTimeInterval timestamp; - @end diff --git a/UIKit/Classes/UIAcceleration.m b/UIKit/Classes/UIAcceleration.m index 5f9571d7..8ae1d8f0 100644 --- a/UIKit/Classes/UIAcceleration.m +++ b/UIKit/Classes/UIAcceleration.m @@ -30,5 +30,4 @@ #import "UIAcceleration.h" @implementation UIAcceleration -@synthesize x=_x, y=_y, z=_z, timestamp=_timestamp; @end diff --git a/UIKit/Classes/UIAccelerometer.h b/UIKit/Classes/UIAccelerometer.h index 9a87ec6e..56e95afd 100644 --- a/UIKit/Classes/UIAccelerometer.h +++ b/UIKit/Classes/UIAccelerometer.h @@ -35,15 +35,9 @@ - (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration; @end -@interface UIAccelerometer : NSObject { -@private - NSTimeInterval _updateInterval; - __unsafe_unretained id _delegate; -} - +@interface UIAccelerometer : NSObject + (UIAccelerometer *)sharedAccelerometer; @property (nonatomic, assign) id delegate; @property (nonatomic) NSTimeInterval updateInterval; - @end diff --git a/UIKit/Classes/UIAccelerometer.m b/UIKit/Classes/UIAccelerometer.m index 102bab98..86439642 100644 --- a/UIKit/Classes/UIAccelerometer.m +++ b/UIKit/Classes/UIAccelerometer.m @@ -30,7 +30,6 @@ #import "UIAccelerometer.h" @implementation UIAccelerometer -@synthesize updateInterval=_updateInterval, delegate=_delegate; + (UIAccelerometer *)sharedAccelerometer { diff --git a/UIKit/Classes/UIAccessibility.h b/UIKit/Classes/UIAccessibility.h index a0aadcbf..704d0efe 100644 --- a/UIKit/Classes/UIAccessibility.h +++ b/UIKit/Classes/UIAccessibility.h @@ -78,3 +78,14 @@ extern UIAccessibilityNotifications UIAccessibilityPageScrolledNotification; extern void UIAccessibilityPostNotification(UIAccessibilityNotifications notification, id argument); extern BOOL UIAccessibilityIsVoiceOverRunning(void); + +extern NSString *const UIAccessibilityVoiceOverStatusChanged; + +typedef NS_ENUM(NSInteger, UIAccessibilityScrollDirection) { + UIAccessibilityScrollDirectionRight = 1, + UIAccessibilityScrollDirectionLeft, + UIAccessibilityScrollDirectionUp, + UIAccessibilityScrollDirectionDown, + UIAccessibilityScrollDirectionNext, + UIAccessibilityScrollDirectionPrevious +}; diff --git a/UIKit/Classes/UIAccessibility.m b/UIKit/Classes/UIAccessibility.m index 4cff6f6f..a09468a8 100644 --- a/UIKit/Classes/UIAccessibility.m +++ b/UIKit/Classes/UIAccessibility.m @@ -48,6 +48,7 @@ UIAccessibilityNotifications UIAccessibilityAnnouncementNotification = 1002; UIAccessibilityNotifications UIAccessibilityPageScrolledNotification = 1003; +NSString *const UIAccessibilityVoiceOverStatusChanged = @"UIAccessibilityVoiceOverStatusChanged"; @implementation NSObject (UIAccessibility) - (BOOL)isAccessibilityElement diff --git a/UIKit/Classes/UIAccessibilityElement.h b/UIKit/Classes/UIAccessibilityElement.h index 333b8024..9994fdbe 100644 --- a/UIKit/Classes/UIAccessibilityElement.h +++ b/UIKit/Classes/UIAccessibilityElement.h @@ -29,20 +29,12 @@ #import "UIAccessibility.h" -@interface UIAccessibilityElement : NSObject { - NSString *_accessibilityLabel; - NSString *_accessibilityHint; - NSString *_accessibilityValue; - CGRect _accessibilityFrame; - UIAccessibilityTraits _accessibilityTraits; -} - +@interface UIAccessibilityElement : NSObject - (id)initWithAccessibilityContainer:(id)container; -@property (nonatomic, retain) NSString *accessibilityLabel; -@property (nonatomic, retain) NSString *accessibilityHint; -@property (nonatomic, retain) NSString *accessibilityValue; +@property (nonatomic, strong) NSString *accessibilityLabel; +@property (nonatomic, strong) NSString *accessibilityHint; +@property (nonatomic, strong) NSString *accessibilityValue; @property (nonatomic, assign) CGRect accessibilityFrame; @property (nonatomic, assign) UIAccessibilityTraits accessibilityTraits; - @end diff --git a/UIKit/Classes/UIAccessibilityElement.m b/UIKit/Classes/UIAccessibilityElement.m index a6cb4664..d33acbde 100644 --- a/UIKit/Classes/UIAccessibilityElement.m +++ b/UIKit/Classes/UIAccessibilityElement.m @@ -30,8 +30,6 @@ #import "UIAccessibilityElement.h" @implementation UIAccessibilityElement -@synthesize accessibilityLabel=_accessibilityLabel, accessibilityHint=_accessibilityHint, accessibilityValue=_accessibilityValue; -@synthesize accessibilityFrame=_accessibilityFrame, accessibilityTraits=_accessibilityTraits; - (id)initWithAccessibilityContainer:(id)container { @@ -40,12 +38,5 @@ - (id)initWithAccessibilityContainer:(id)container return self; } -- (void)dealloc -{ - [_accessibilityLabel release]; - [_accessibilityHint release]; - [_accessibilityValue release]; - [super dealloc]; -} @end diff --git a/UIKit/Classes/UIAction.h b/UIKit/Classes/UIAction.h index b64cc547..b5ef9f16 100644 --- a/UIKit/Classes/UIAction.h +++ b/UIKit/Classes/UIAction.h @@ -29,12 +29,7 @@ #import -@interface UIAction : NSObject { - __unsafe_unretained id _target; - SEL _action; -} - -@property (nonatomic, assign) id target; +@interface UIAction : NSObject +@property (nonatomic, weak) id target; @property (nonatomic, assign) SEL action; - @end diff --git a/UIKit/Classes/UIAction.m b/UIKit/Classes/UIAction.m index 5378ff5d..c05e825d 100644 --- a/UIKit/Classes/UIAction.m +++ b/UIKit/Classes/UIAction.m @@ -30,13 +30,12 @@ #import "UIAction.h" @implementation UIAction -@synthesize target=_target, action=_action; - (BOOL)isEqual:(id)object { if (object == self) { return YES; - } else if ([object isKindOfClass:[isa class]]) { + } else if ([object isKindOfClass:[[self class] class]]) { return ([object target] == self.target && [object action] == self.action); } else { return NO; diff --git a/UIKit/Classes/UIActionSheet.h b/UIKit/Classes/UIActionSheet.h index 1bc1fa8c..3c750aac 100644 --- a/UIKit/Classes/UIActionSheet.h +++ b/UIKit/Classes/UIActionSheet.h @@ -42,35 +42,14 @@ - (void)actionSheetCancel:(UIActionSheet *)actionSheet; @end -typedef enum { +typedef NS_ENUM(NSInteger, UIActionSheetStyle) { UIActionSheetStyleAutomatic = -1, UIActionSheetStyleDefault = UIBarStyleDefault, UIActionSheetStyleBlackTranslucent = UIBarStyleBlackTranslucent, UIActionSheetStyleBlackOpaque = UIBarStyleBlackOpaque, -} UIActionSheetStyle; - -@interface UIActionSheet : UIView { -@private - __unsafe_unretained id _delegate; - NSInteger _destructiveButtonIndex; - NSInteger _cancelButtonIndex; - NSInteger _firstOtherButtonIndex; - NSString *_title; - NSMutableArray *_menuTitles; - NSMutableArray *_separatorIndexes; - UIActionSheetStyle _actionSheetStyle; - id _menu; - - struct { - unsigned clickedButtonAtIndex : 1; - unsigned willPresentActionSheet : 1; - unsigned didPresentActionSheet : 1; - unsigned willDismissWithButtonIndex : 1; - unsigned didDismissWithButtonIndex : 1; - unsigned actionSheetCancel : 1; - } _delegateHas; -} +}; +@interface UIActionSheet : UIView - (id)initWithTitle:(NSString *)title delegate:(id)delegate cancelButtonTitle:(NSString *)cancelButtonTitle destructiveButtonTitle:(NSString *)destructiveButtonTitle otherButtonTitles:(NSString *)otherButtonTitles, ...; - (NSInteger)addButtonWithTitle:(NSString *)title; @@ -91,5 +70,4 @@ typedef enum { @property (nonatomic) NSInteger cancelButtonIndex; @property (nonatomic, readonly) NSInteger firstOtherButtonIndex; @property (nonatomic, readonly) NSInteger numberOfButtons; - @end diff --git a/UIKit/Classes/UIActionSheet.m b/UIKit/Classes/UIActionSheet.m index af3e97a9..d207b235 100644 --- a/UIKit/Classes/UIActionSheet.m +++ b/UIKit/Classes/UIActionSheet.m @@ -31,15 +31,26 @@ #import "UIWindow.h" #import "UIScreenAppKitIntegration.h" #import "UIKitView.h" -#import "UIApplication+UIPrivate.h" +#import "UIApplicationAppKitIntegration.h" #import "UIBarButtonItem.h" #import #import #import -@implementation UIActionSheet -@synthesize delegate=_delegate, destructiveButtonIndex=_destructiveButtonIndex, cancelButtonIndex=_cancelButtonIndex, title=_title; -@synthesize firstOtherButtonIndex=_firstOtherButtonIndex, actionSheetStyle = _actionSheetStyle; +@implementation UIActionSheet { + NSMutableArray *_menuTitles; + NSMutableArray *_separatorIndexes; + NSMenu *_menu; + + struct { + unsigned clickedButtonAtIndex : 1; + unsigned willPresentActionSheet : 1; + unsigned didPresentActionSheet : 1; + unsigned willDismissWithButtonIndex : 1; + unsigned didDismissWithButtonIndex : 1; + unsigned actionSheetCancel : 1; + } _delegateHas; +} - (id)initWithFrame:(CGRect)frame { @@ -67,7 +78,7 @@ - (id)initWithTitle:(NSString *)title delegate:(id < UIActionSheetDelegate >)del va_list argumentList; va_start(argumentList, otherButtonTitles); - while ((buttonTitle=(__bridge NSString *)va_arg(argumentList, void *))) { + while ((buttonTitle=va_arg(argumentList, NSString *))) { [self addButtonWithTitle:buttonTitle]; } @@ -85,14 +96,6 @@ - (id)initWithTitle:(NSString *)title delegate:(id < UIActionSheetDelegate >)del return self; } -- (void)dealloc -{ - [_title release]; - [_menu release]; - [_menuTitles release]; - [_separatorIndexes release]; - [super dealloc]; -} - (void)setDelegate:(id)newDelegate { @@ -180,7 +183,6 @@ - (void)_showFromPoint:(CGPoint)point rightAligned:(BOOL)rightAligned inView:(UI [theItem setTag:index]; [theItem setTarget:self]; [_menu addItem:theItem]; - [theItem release]; } } @@ -242,13 +244,13 @@ - (void)_actuallyPresentTheMenuFromPoint:(NSValue *)aPoint } // this goes modal... meh. - BOOL itemSelected = [_menu popUpMenuPositioningItem:nil atLocation:NSPointFromCGPoint([aPoint CGPointValue]) inView:[self.window.screen UIKitView]]; + BOOL itemSelected = [_menu popUpMenuPositioningItem:nil atLocation:NSPointFromCGPoint([aPoint CGPointValue]) inView:self.window.screen.UIKitView]; // because of the modal nature of NSMenu, if there's a touch active (like, being held down) when a menu is triggered, the modal NSMenu // takes over the event stream and so a mouseUp is never delivered to the UIKitView. This means it never gets to the app and it leaves // the "touch" tracking system in an inconsistent state. This triggers the touchesCancelled UIResponder stuff to allow UIKit code to clean // itself up after the menu is done. - [[UIApplication sharedApplication] _cancelTouches]; + UIApplicationInterruptTouchesInView(nil); if (!itemSelected) { [self _clickedButtonAtIndex:_cancelButtonIndex]; @@ -302,7 +304,6 @@ - (void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)anim } // kill off the menu - [_menu release]; _menu = nil; // remove ourself from the superview that we piggy-backed on diff --git a/UIKit/Classes/UIActivityIndicatorView.h b/UIKit/Classes/UIActivityIndicatorView.h index 71fe74b5..d3764b1e 100644 --- a/UIKit/Classes/UIActivityIndicatorView.h +++ b/UIKit/Classes/UIActivityIndicatorView.h @@ -29,19 +29,13 @@ #import "UIView.h" -typedef enum { +typedef NS_ENUM(NSInteger, UIActivityIndicatorViewStyle) { UIActivityIndicatorViewStyleWhiteLarge, UIActivityIndicatorViewStyleWhite, UIActivityIndicatorViewStyleGray, -} UIActivityIndicatorViewStyle; - -@interface UIActivityIndicatorView : UIView { -@private - UIActivityIndicatorViewStyle _activityIndicatorViewStyle; - BOOL _hidesWhenStopped; - BOOL _animating; -} +}; +@interface UIActivityIndicatorView : UIView - (id)initWithActivityIndicatorStyle:(UIActivityIndicatorViewStyle)style; - (void)startAnimating; - (void)stopAnimating; @@ -49,5 +43,5 @@ typedef enum { @property BOOL hidesWhenStopped; @property UIActivityIndicatorViewStyle activityIndicatorViewStyle; - +@property (readwrite, nonatomic, retain) UIColor *color; @end diff --git a/UIKit/Classes/UIActivityIndicatorView.m b/UIKit/Classes/UIActivityIndicatorView.m index af715172..503ab0f4 100644 --- a/UIKit/Classes/UIActivityIndicatorView.m +++ b/UIKit/Classes/UIActivityIndicatorView.m @@ -45,7 +45,7 @@ static CGSize UIActivityIndicatorViewStyleSize(UIActivityIndicatorViewStyle styl } } -static UIImage *UIActivityIndicatorViewFrameImage(UIActivityIndicatorViewStyle style, NSInteger frame, NSInteger numberOfFrames, CGFloat scale) +static UIImage *UIActivityIndicatorViewFrameImage(UIActivityIndicatorViewStyle style, UIColor *toothColor, NSInteger frame, NSInteger numberOfFrames, CGFloat scale) { const CGSize frameSize = UIActivityIndicatorViewStyleSize(style); const CGFloat radius = frameSize.width / 2.f; @@ -53,7 +53,9 @@ static CGSize UIActivityIndicatorViewStyleSize(UIActivityIndicatorViewStyle styl const CGFloat numberOfTeeth = 12; const CGFloat toothWidth = (style == UIActivityIndicatorViewStyleWhiteLarge)? 3.5 : 2; - UIColor *toothColor = (style == UIActivityIndicatorViewStyleGray)? [UIColor grayColor] : [UIColor whiteColor]; + if (!toothColor) { + toothColor = (style == UIActivityIndicatorViewStyleGray)? [UIColor grayColor] : [UIColor whiteColor]; + } UIGraphicsBeginImageContextWithOptions(frameSize, NO, scale); CGContextRef c = UIGraphicsGetCurrentContext(); @@ -82,7 +84,11 @@ static CGSize UIActivityIndicatorViewStyleSize(UIActivityIndicatorViewStyle styl return frameImage; } -@implementation UIActivityIndicatorView +@implementation UIActivityIndicatorView { + BOOL _animating; + UIActivityIndicatorViewStyle _activityIndicatorViewStyle; + BOOL _hidesWhenStopped; +} - (id)initWithActivityIndicatorStyle:(UIActivityIndicatorViewStyle)style { @@ -94,6 +100,7 @@ - (id)initWithActivityIndicatorStyle:(UIActivityIndicatorViewStyle)style self.activityIndicatorViewStyle = style; self.hidesWhenStopped = YES; self.opaque = NO; + self.contentMode = UIViewContentModeCenter; } return self; @@ -110,13 +117,7 @@ - (id)initWithFrame:(CGRect)frame - (CGSize)sizeThatFits:(CGSize)aSize { - UIActivityIndicatorViewStyle style; - - @synchronized (self) { - style = _activityIndicatorViewStyle; - } - - return UIActivityIndicatorViewStyleSize(style); + return UIActivityIndicatorViewStyleSize(self.activityIndicatorViewStyle); } - (void)setActivityIndicatorViewStyle:(UIActivityIndicatorViewStyle)style @@ -135,13 +136,9 @@ - (void)setActivityIndicatorViewStyle:(UIActivityIndicatorViewStyle)style - (UIActivityIndicatorViewStyle)activityIndicatorViewStyle { - UIActivityIndicatorViewStyle style; - @synchronized (self) { - style = _activityIndicatorViewStyle; + return _activityIndicatorViewStyle; } - - return style; } - (void)setHidesWhenStopped:(BOOL)hides @@ -159,45 +156,45 @@ - (void)setHidesWhenStopped:(BOOL)hides - (BOOL)hidesWhenStopped { - BOOL hides; - @synchronized (self) { - hides = _hidesWhenStopped; + return _hidesWhenStopped; } - - return hides; } - (void)_startAnimation { - const NSInteger numberOfFrames = 12; - const CFTimeInterval animationDuration = 0.8; - - NSMutableArray *images = [[NSMutableArray alloc] initWithCapacity:numberOfFrames]; - - for (NSInteger frameNumber=0; frameNumber _delegate; - NSInteger _cancelButtonIndex; - NSMutableArray *_buttonTitles; - - struct { - unsigned clickedButtonAtIndex : 1; - unsigned alertViewCancel : 1; - unsigned willPresentAlertView : 1; - unsigned didPresentAlertView : 1; - unsigned willDismissWithButtonIndex : 1; - unsigned didDismissWithButtonIndex : 1; - } _delegateHas; -} - +@interface UIAlertView : UIView - (id)initWithTitle:(NSString *)title message:(NSString *)message delegate:(id)delegate cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSString *)otherButtonTitles, ...; - - (NSInteger)addButtonWithTitle:(NSString *)title; - (NSString *)buttonTitleAtIndex:(NSInteger)buttonIndex; - (void)show; @@ -61,7 +43,6 @@ @property (nonatomic, assign) id delegate; @property (nonatomic) NSInteger cancelButtonIndex; @property (nonatomic,readonly) NSInteger numberOfButtons; - @end @protocol UIAlertViewDelegate diff --git a/UIKit/Classes/UIAlertView.m b/UIKit/Classes/UIAlertView.m index 94fee20f..9e004774 100644 --- a/UIKit/Classes/UIAlertView.m +++ b/UIKit/Classes/UIAlertView.m @@ -34,12 +34,18 @@ #import #import -@interface UIAlertView () -@property (nonatomic, retain) NSMutableArray *buttonTitles; -@end - -@implementation UIAlertView -@synthesize title=_title, message=_message, delegate=_delegate, cancelButtonIndex=_cancelButtonIndex, buttonTitles=_buttonTitles; +@implementation UIAlertView { + NSMutableArray *_buttonTitles; + + struct { + unsigned clickedButtonAtIndex : 1; + unsigned alertViewCancel : 1; + unsigned willPresentAlertView : 1; + unsigned didPresentAlertView : 1; + unsigned willDismissWithButtonIndex : 1; + unsigned didDismissWithButtonIndex : 1; + } _delegateHas; +} - (id)initWithTitle:(NSString *)title message:(NSString *)message delegate:(id)delegate cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSString *)otherButtonTitles, ... { @@ -47,7 +53,7 @@ - (id)initWithTitle:(NSString *)title message:(NSString *)message delegate:(id)d self.title = title; self.message = message; self.delegate = delegate; - self.buttonTitles = [NSMutableArray arrayWithCapacity:1]; + _buttonTitles = [NSMutableArray arrayWithCapacity:1]; if (cancelButtonTitle) { self.cancelButtonIndex = [self addButtonWithTitle:cancelButtonTitle]; @@ -60,7 +66,7 @@ - (id)initWithTitle:(NSString *)title message:(NSString *)message delegate:(id)d va_list argumentList; va_start(argumentList, otherButtonTitles); - while ((buttonTitle=(__bridge NSString *)va_arg(argumentList, void *))) { + while ((buttonTitle=va_arg(argumentList, NSString *))) { [self addButtonWithTitle:buttonTitle]; } @@ -70,13 +76,6 @@ - (id)initWithTitle:(NSString *)title message:(NSString *)message delegate:(id)d return self; } -- (void)dealloc -{ - [_title release]; - [_message release]; - [_buttonTitles release]; - [super dealloc]; -} - (void)setDelegate:(id)newDelegate { @@ -91,19 +90,19 @@ - (void)setDelegate:(id)newDelegate - (NSInteger)addButtonWithTitle:(NSString *)title { - [self.buttonTitles addObject:title]; - return ([self.buttonTitles count] - 1); + [_buttonTitles addObject:title]; + return ([_buttonTitles count] - 1); } - (NSString *)buttonTitleAtIndex:(NSInteger)buttonIndex { - return [self.buttonTitles objectAtIndex:buttonIndex]; + return [_buttonTitles objectAtIndex:buttonIndex]; } - (NSInteger)numberOfButtons { - return [self.buttonTitles count]; + return [_buttonTitles count]; } - (void)show @@ -115,8 +114,8 @@ - (void)show // NSAlert does have a mode that doesn't block the runloop, but it has other drawbacks that I didn't like // so opting to do it this way here. :/ - NSAlert *alert = [[[NSAlert alloc] init] autorelease]; - NSMutableArray *buttonOrder = [[[NSMutableArray alloc] initWithCapacity:self.numberOfButtons] autorelease]; + NSAlert *alert = [[NSAlert alloc] init]; + NSMutableArray *buttonOrder = [[NSMutableArray alloc] initWithCapacity:self.numberOfButtons]; if (self.title) { [alert setMessageText:self.title]; @@ -128,13 +127,13 @@ - (void)show for (NSInteger buttonIndex=0; buttonIndex= 0) { - NSButton *btn = [alert addButtonWithTitle:[self.buttonTitles objectAtIndex:self.cancelButtonIndex]]; + NSButton *btn = [alert addButtonWithTitle:[_buttonTitles objectAtIndex:self.cancelButtonIndex]]; // only change the key equivelent if there's more than one button, otherwise we lose the "Return" key for triggering the default action if (self.numberOfButtons > 1) { diff --git a/UIKit/Classes/UIAppearanceInstance.h b/UIKit/Classes/UIAppearanceInstance.h index 05a5cc26..f60166f3 100644 --- a/UIKit/Classes/UIAppearanceInstance.h +++ b/UIKit/Classes/UIAppearanceInstance.h @@ -35,8 +35,8 @@ + (id)appearance; + (id)appearanceWhenContainedIn:(Class )containerClass, ...; -- (void)_appearancePropertyDidChange:(UIAppearanceProperty *)property; -- (id)_appearanceContainer; -- (void)_updateAppearanceIfNeeded; -- (void)_setAppearanceNeedsUpdate; +- (id)_UIAppearanceContainer; +- (void)_UIAppearancePropertyDidChange:(id)property; +- (void)_UIAppearanceUpdateIfNeeded; +- (void)_UIAppearanceSetNeedsUpdate; @end diff --git a/UIKit/Classes/UIAppearanceInstance.m b/UIKit/Classes/UIAppearanceInstance.m index 5583b3c3..9a9474c7 100644 --- a/UIKit/Classes/UIAppearanceInstance.m +++ b/UIKit/Classes/UIAppearanceInstance.m @@ -33,56 +33,8 @@ #import static const char *UIAppearanceClassAssociatedObjectKey = "UIAppearanceClassAssociatedObjectKey"; -static const char *UIAppearanceInstanceAssociatedObjectKey = "UIAppearanceInstanceAssociatedObjectKey"; - -static NSString * const UIAppearanceInstancePropertiesKey = @"UIAppearanceInstancePropertiesKey"; -static NSString * const UIAppearanceInstanceNeedsUpdateKey = @"UIAppearanceInstanceNeedsUpdateKey"; - -static NSMutableDictionary *UIAppearanceInstanceDictionary(id object) -{ - return objc_getAssociatedObject(object, UIAppearanceInstanceAssociatedObjectKey); -} - -static NSMutableDictionary *UIAppearanceInstanceDictionaryCreateIfNeeded(id object) -{ - NSMutableDictionary *info = UIAppearanceInstanceDictionary(object); - - if (!info) { - info = [NSMutableDictionary dictionaryWithCapacity:1]; - objc_setAssociatedObject(object, UIAppearanceInstanceAssociatedObjectKey, info, OBJC_ASSOCIATION_RETAIN); - } - - return info; -} - -static void UIAppearanceInstanceSetProperties(id object, NSSet *properties) -{ - if ([properties count] > 0) { - [UIAppearanceInstanceDictionaryCreateIfNeeded(object) setObject:properties forKey:UIAppearanceInstancePropertiesKey]; - } else { - [UIAppearanceInstanceDictionary(object) removeObjectForKey:UIAppearanceInstancePropertiesKey]; - } -} - -static NSSet *UIAppearanceInstanceProperties(id object) -{ - return [UIAppearanceInstanceDictionary(object) objectForKey:UIAppearanceInstancePropertiesKey]; -} - -static void UIAppearanceInstancePropertyDidChange(id object, UIAppearanceProperty *property) -{ - UIAppearanceInstanceSetProperties(object, [[NSSet setWithObject:property] setByAddingObjectsFromSet:UIAppearanceInstanceProperties(object)]); -} - -static BOOL UIAppearanceInstanceNeedsUpdate(id object) -{ - return [[UIAppearanceInstanceDictionary(object) objectForKey:UIAppearanceInstanceNeedsUpdateKey] boolValue]; -} - -static void UIAppearanceInstanceSetNeedsUpdate(id object, BOOL needsUpdate) -{ - [UIAppearanceInstanceDictionaryCreateIfNeeded(object) setObject:[NSNumber numberWithBool:needsUpdate] forKey:UIAppearanceInstanceNeedsUpdateKey]; -} +static const char *UIAppearanceChangedPropertiesKey = "UIAppearanceChangedPropertiesKey"; +static const char *UIAppearancePropertiesAreUpToDateKey = "UIAppearancePropertiesAreUpToDateKey"; static NSArray *UIAppearanceHierarchyForClass(Class klass) { @@ -93,7 +45,7 @@ static void UIAppearanceInstanceSetNeedsUpdate(id object, BOOL needsUpdate) klass = [klass superclass]; } - return [classes autorelease]; + return classes; } @implementation NSObject (UIAppearanceInstance) @@ -124,107 +76,114 @@ + (id)appearanceWhenContainedIn:(Class )containerClass, . UIAppearanceProxy *record = [appearanceRules objectForKey:containmentPath]; if (!record) { - record = [[[UIAppearanceProxy alloc] initWithClass:self] autorelease]; + record = [[UIAppearanceProxy alloc] initWithClass:self]; [appearanceRules setObject:record forKey:containmentPath]; } return record; } -- (void)_appearancePropertyDidChange:(UIAppearanceProperty *)property -{ - UIAppearanceInstancePropertyDidChange(self, property); -} - -- (id)_appearanceContainer +- (id)_UIAppearanceContainer { return nil; } -- (void)_updateAppearanceIfNeeded +- (void)_UIAppearanceUpdateIfNeeded { - if (UIAppearanceInstanceNeedsUpdate(self)) { - // first go down our own class heirarchy until we find the root of the UIAppearance protocol - // then we'll start at the bottom and work up while checking each class for all relevant rules - // that apply to this instance at this time. - - NSArray *classes = UIAppearanceHierarchyForClass([self class]); - NSMutableDictionary *propertiesToSet = [NSMutableDictionary dictionaryWithCapacity:0]; + // check if we are already up to date, if so, return early + if (objc_getAssociatedObject(self, UIAppearancePropertiesAreUpToDateKey)) { + return; + } + + // first go down our own class heirarchy until we find the root of the UIAppearance protocol + // then we'll start at the bottom and work up while checking each class for all relevant rules + // that apply to this instance at this time. + + NSArray *classes = UIAppearanceHierarchyForClass([self class]); + NSMutableDictionary *propertiesToSet = [NSMutableDictionary dictionaryWithCapacity:0]; + + for (Class klass in classes) { + NSMutableDictionary *rules = objc_getAssociatedObject(klass, UIAppearanceClassAssociatedObjectKey); - for (Class klass in classes) { - NSMutableDictionary *rules = objc_getAssociatedObject(klass, UIAppearanceClassAssociatedObjectKey); - - // sorts the rule keys (which are arrays of classes) by length - // if the lengths match, it sorts based on the last class being a superclass of the other or vice-versa - // if the last classes aren't related at all, it marks them equal (I suspect these cases will always be filtered out in the next step) - NSArray *sortedRulePaths = [[rules allKeys] sortedArrayUsingComparator:^NSComparisonResult(NSArray *path1, NSArray *path2) { - if ([path1 count] == [path2 count]) { - if ([[path2 lastObject] isKindOfClass:[path1 lastObject]]) { - return (NSComparisonResult)NSOrderedAscending; - } else if ([[path1 lastObject] isKindOfClass:[path2 lastObject]]) { - return (NSComparisonResult)NSOrderedDescending; - } else { - return (NSComparisonResult)NSOrderedSame; - } - } else if ([path1 count] < [path2 count]) { + // sorts the rule keys (which are arrays of classes) by length + // if the lengths match, it sorts based on the last class being a superclass of the other or vice-versa + // if the last classes aren't related at all, it marks them equal (I suspect these cases will always be filtered out in the next step) + NSArray *sortedRulePaths = [[rules allKeys] sortedArrayUsingComparator:^NSComparisonResult(NSArray *path1, NSArray *path2) { + if ([path1 count] == [path2 count]) { + if ([[path2 lastObject] isKindOfClass:[path1 lastObject]]) { return (NSComparisonResult)NSOrderedAscending; - } else { + } else if ([[path1 lastObject] isKindOfClass:[path2 lastObject]]) { return (NSComparisonResult)NSOrderedDescending; + } else { + return (NSComparisonResult)NSOrderedSame; } - }]; + } else if ([path1 count] < [path2 count]) { + return (NSComparisonResult)NSOrderedAscending; + } else { + return (NSComparisonResult)NSOrderedDescending; + } + }]; + + // we should now have a list of classes to check for rule settings for this instance, so now we spin + // through those and fetch the properties and values and add them to the dictionary of things to do. + // before applying a rule's properties, we must make sure this instance is qualified, so we must check + // this instance's container hierarchy against ever class that makes up the rule. + for (NSArray *rule in sortedRulePaths) { + BOOL shouldApplyRule = YES; - // we should now have a list of classes to check for rule settings for this instance, so now we spin - // through those and fetch the properties and values and add them to the dictionary of things to do. - // before applying a rule's properties, we must make sure this instance is qualified, so we must check - // this instance's container hierarchy against ever class that makes up the rule. - for (NSArray *rule in sortedRulePaths) { - BOOL shouldApplyRule = YES; - - for (Class klass in [rule reverseObjectEnumerator]) { - id container = [self _appearanceContainer]; + for (Class klass in [rule reverseObjectEnumerator]) { + id container = [self _UIAppearanceContainer]; - while (container && ![container isKindOfClass:klass]) { - container = [container _appearanceContainer]; - } - - if (!container) { - shouldApplyRule = NO; - break; - } + while (container && ![container isKindOfClass:klass]) { + container = [container _UIAppearanceContainer]; } - if (shouldApplyRule) { - UIAppearanceProxy *proxy = [rules objectForKey:rule]; - [propertiesToSet addEntriesFromDictionary:[proxy _appearancePropertiesAndValues]]; + if (!container) { + shouldApplyRule = NO; + break; } } + + if (shouldApplyRule) { + UIAppearanceProxy *proxy = [rules objectForKey:rule]; + [propertiesToSet addEntriesFromDictionary:[proxy _appearancePropertiesAndValues]]; + } } - - // before setting the actual properties on the instance, save off a copy of the existing modified properties - // because the act of setting the UIAppearance properties will end up messing with that set. - // after we're done actually applying everything, reset the modified properties set to what it was before. - NSSet *originalProperties = [UIAppearanceInstanceProperties(self) copy]; - - // subtract any properties that have been overriden from the list to apply - [propertiesToSet removeObjectsForKeys:[originalProperties allObjects]]; - - // now apply everything that's left - [propertiesToSet enumerateKeysAndObjectsUsingBlock:^(UIAppearanceProperty *property, NSValue *value, BOOL *stop) { - [property invokeSetterUsingTarget:self withValue:value]; - }]; - - // now reset our set of changes properties to the original set so we don't count the UIAppearance defaults - UIAppearanceInstanceSetProperties(self, originalProperties); - [originalProperties release]; - - // done! - UIAppearanceInstanceSetNeedsUpdate(self, NO); } + + // before setting the actual properties on the instance, save off a copy of the existing modified properties + // because the act of setting the UIAppearance properties will end up messing with that set. + // after we're done actually applying everything, reset the modified properties set to what it was before. + NSSet *originalProperties = objc_getAssociatedObject(self, UIAppearanceChangedPropertiesKey); + + // subtract any properties that have been overriden from the list to apply + [propertiesToSet removeObjectsForKeys:[originalProperties allObjects]]; + + // now apply everything that's left + for (UIAppearanceProperty *property in [propertiesToSet allValues]) { + [property invokeUsingTarget:self]; + } + + // now reset our set of changes properties to the original set so we don't count the UIAppearance defaults as overrides + objc_setAssociatedObject(self, UIAppearanceChangedPropertiesKey, originalProperties, OBJC_ASSOCIATION_RETAIN); + + // done! + objc_setAssociatedObject(self, UIAppearancePropertiesAreUpToDateKey, @(1), OBJC_ASSOCIATION_RETAIN); } -- (void)_setAppearanceNeedsUpdate +- (void)_UIAppearanceSetNeedsUpdate { - UIAppearanceInstanceSetNeedsUpdate(self, YES); + // this removes UIAppearancePropertiesAreUpToDateKey which will trigger _UIAppearanceUpdateIfNeeded to run (if it is called later) + objc_setAssociatedObject(self, UIAppearancePropertiesAreUpToDateKey, nil, OBJC_ASSOCIATION_RETAIN); +} + +- (void)_UIAppearancePropertyDidChange:(id)property +{ + // note an overridden property value so we don't override it with a default value in -_UIAppearanceUpdateIfNeeded + // this occurs when a value is set directly using a setter on an instance (such as "label.textColor = myColor;") + + NSSet *changedProperties = [NSSet setWithSet:objc_getAssociatedObject(self, UIAppearanceChangedPropertiesKey)]; + objc_setAssociatedObject(self, UIAppearanceChangedPropertiesKey, [changedProperties setByAddingObject:property], OBJC_ASSOCIATION_RETAIN); } @end diff --git a/UIKit/Classes/UIAppearanceProperty.h b/UIKit/Classes/UIAppearanceProperty.h index d9e1ff66..20451623 100644 --- a/UIKit/Classes/UIAppearanceProperty.h +++ b/UIKit/Classes/UIAppearanceProperty.h @@ -27,16 +27,10 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#import - -@interface UIAppearanceProperty : NSObject { - SEL cmd; - NSArray *axisValues; -} - -- (id)initWithSelector:(SEL)sel axisValues:(NSArray *)values; -- (void)invokeSetterUsingTarget:(id)target withValue:(NSValue *)value; - -@property (nonatomic, readonly) NSArray *axisValues; +#import "UIAppearanceProxy.h" +@interface UIAppearanceProperty : NSObject +- (id)initWithInvocation:(NSInvocation *)setterInvocation; +- (void)invokeUsingTarget:(id)target; +- (void)setReturnValueForInvocation:(NSInvocation *)getterInvocation; @end diff --git a/UIKit/Classes/UIAppearanceProperty.m b/UIKit/Classes/UIAppearanceProperty.m index 2b8f3143..c08f368e 100644 --- a/UIKit/Classes/UIAppearanceProperty.m +++ b/UIKit/Classes/UIAppearanceProperty.m @@ -29,69 +29,59 @@ #import "UIAppearanceProperty.h" -@implementation UIAppearanceProperty -@synthesize axisValues; +@implementation UIAppearanceProperty { + NSInvocation *_invocation; +} -- (id)initWithSelector:(SEL)sel axisValues:(NSArray *)values +- (id)initWithInvocation:(NSInvocation *)setterInvocation { if ((self=[super init])) { - cmd = sel; - axisValues = [values copy]; + NSMethodSignature *methodSignature = [setterInvocation methodSignature]; + _invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; + + // we want to copy every argument except for target (which is argument 0) + // so start at 1 and copy... + for (int i = 1; i < [methodSignature numberOfArguments]; i++) { + const char *valueType = [methodSignature getArgumentTypeAtIndex:i]; + NSUInteger bufferSize = 0; + NSGetSizeAndAlignment(valueType, &bufferSize, NULL); + UInt8 valueBuffer[bufferSize]; + memset(valueBuffer, 0, bufferSize); + + [setterInvocation getArgument:valueBuffer atIndex:i]; + [_invocation setArgument:valueBuffer atIndex:i]; + } + + // this is very important since we're caching this invocation! + [_invocation retainArguments]; } return self; } -- (void)dealloc -{ - [axisValues release]; - [super dealloc]; -} - -- (BOOL)isEqual:(id)object +- (void)invokeUsingTarget:(id)target { - if (object == self) { - return YES; - } else if ([object isKindOfClass:[UIAppearanceProperty class]]) { - UIAppearanceProperty *entry = (UIAppearanceProperty *)object; - return cmd == entry->cmd && [axisValues isEqual:entry->axisValues]; - } else { - return NO; - } + [_invocation invokeWithTarget:target]; } -- (NSUInteger)hash +- (void)setReturnValueForInvocation:(NSInvocation *)getterInvocation { - return [NSStringFromSelector(cmd) hash] ^ [axisValues hash]; -} - -- (id)copyWithZone:(NSZone *)zone -{ - return [[UIAppearanceProperty alloc] initWithSelector:cmd axisValues:axisValues]; -} + NSMethodSignature *methodSignature = [_invocation methodSignature]; + + // ensure we have a value to return (which is expected to be at argument index 2) + NSAssert([methodSignature numberOfArguments] >= 2, @"stored invocation has no property value"); -- (void)invokeSetterUsingTarget:(id)target withValue:(NSValue *)value -{ - NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[target methodSignatureForSelector:cmd]]; + // fetch and return the property value from our stored invocation + const char *valueType = [methodSignature getArgumentTypeAtIndex:2]; + NSUInteger bufferSize = 0; + NSGetSizeAndAlignment(valueType, &bufferSize, NULL); + UInt8 valueBuffer[bufferSize]; + memset(valueBuffer, 0, bufferSize); + [_invocation getArgument:valueBuffer atIndex:2]; - for (int i=0; i<[[invocation methodSignature] numberOfArguments]; i++) { - if (i == 0) { - [invocation setTarget:target]; - } else if (i == 1) { - [invocation setSelector:cmd]; - } else { - NSValue *v = (i == 2)? value : [axisValues objectAtIndex:i-3]; - - NSUInteger bufferSize = 0; - NSGetSizeAndAlignment([v objCType], &bufferSize, NULL); - UInt8 argumentBuffer[bufferSize]; - memset(argumentBuffer, 0, bufferSize); - - [v getValue:argumentBuffer]; - [invocation setArgument:argumentBuffer atIndex:i]; - } - } + // ensure the property value type's size matches the expected return value's size + NSAssert(bufferSize == [[getterInvocation methodSignature] methodReturnLength], @"getter return length not equal to property value size"); - [invocation invoke]; + [getterInvocation setReturnValue:valueBuffer]; } @end diff --git a/UIKit/Classes/UIAppearanceProxy.h b/UIKit/Classes/UIAppearanceProxy.h index 8161109d..93c837c2 100644 --- a/UIKit/Classes/UIAppearanceProxy.h +++ b/UIKit/Classes/UIAppearanceProxy.h @@ -30,12 +30,7 @@ #import "UIAppearance.h" #import -@interface UIAppearanceProxy : NSObject { - Class _targetClass; - NSMutableDictionary *_settings; -} - +@interface UIAppearanceProxy : NSObject - (id)initWithClass:(Class)k; - (NSDictionary *)_appearancePropertiesAndValues; - @end diff --git a/UIKit/Classes/UIAppearanceProxy.m b/UIKit/Classes/UIAppearanceProxy.m index 2bbfc74f..251d6aba 100644 --- a/UIKit/Classes/UIAppearanceProxy.m +++ b/UIKit/Classes/UIAppearanceProxy.m @@ -134,20 +134,24 @@ static IMP GetOriginalMethodIMP(id self, SEL cmd) // is the reason we have to go through all this trouble overriding stuff in the first place! static void DidSetPropertyWithAxisValues(id self, SEL cmd, NSInteger numberOfAxisValues, NSInteger *axisValues) { - NSMutableArray *values = [NSMutableArray arrayWithCapacity:numberOfAxisValues]; + NSMutableArray *propertyKey = [NSMutableArray array]; + // IMPORTANT! Must build the property key the same way we do down in -forwardInvocation: for (NSInteger i=0; i= 0) { \ va_list args; va_start(args, property); \ @@ -212,7 +216,10 @@ static IMP ImplementationForPropertyType(const char *t) } } -@implementation UIAppearanceProxy +@implementation UIAppearanceProxy { + Class _targetClass; + NSMutableDictionary *_settings; +} - (id)initWithClass:(Class)k { @@ -223,12 +230,6 @@ - (id)initWithClass:(Class)k return self; } -- (void)dealloc -{ - [_settings release]; - [super dealloc]; -} - - (void)forwardInvocation:(NSInvocation *)anInvocation { // allowed selector formats: @@ -242,54 +243,75 @@ - (void)forwardInvocation:(NSInvocation *)anInvocation // each axis must be either NSInteger or NSUInteger. // throw an exception if other types are used in an axis. + NSMethodSignature *methodSignature = [anInvocation methodSignature]; + NSMutableArray *propertyKey = [NSMutableArray array]; + // see if this selector is a setter or a getter - const BOOL isSetter = [NSStringFromSelector([anInvocation selector]) hasPrefix:@"set"] && [[anInvocation methodSignature] numberOfArguments] > 2 && strcmp([[anInvocation methodSignature] methodReturnType], @encode(void)) == 0; - const BOOL isGetter = !isSetter && strcmp([[anInvocation methodSignature] methodReturnType], @encode(void)) != 0; + const BOOL isSetter = [NSStringFromSelector([anInvocation selector]) hasPrefix:@"set"] && [methodSignature numberOfArguments] > 2 && strcmp([methodSignature methodReturnType], @encode(void)) == 0; + const BOOL isGetter = !isSetter && strcmp([methodSignature methodReturnType], @encode(void)) != 0; // ensure that the property type is legit - const char *propertyType = isSetter? [[anInvocation methodSignature] getArgumentTypeAtIndex:2] : (isGetter? [[anInvocation methodSignature] methodReturnType] : NULL); + const char *propertyType = isSetter? [methodSignature getArgumentTypeAtIndex:2] : (isGetter? [methodSignature methodReturnType] : NULL); if (!TypeIsPropertyType(propertyType)) { @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"property type must be id, NSInteger, NSUInteger, CGFloat, CGPoint, CGSize, CGRect, UIEdgeInsets or UIOffset" userInfo:nil]; } - - // this will hold the NSValue objects made out of the arguments - NSMutableArray *argumentValues = [NSMutableArray arrayWithCapacity:[[anInvocation methodSignature] numberOfArguments]-2]; - - // box the arguments - for (int i=2; i<[[anInvocation methodSignature] numberOfArguments]; i++) { - const char *type = [[anInvocation methodSignature] getArgumentTypeAtIndex:i]; - - if ((isSetter && i > 2) || isGetter) { - // ensure that the axis arguments are integers - if (!TypeIsIntegerType(type)) { - @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"axis type must be NSInteger or NSUInteger" userInfo:nil]; - } + + // use axis arguments when building the unique key for this property + const int axisStartIndex = isSetter? 3 : 2; + for (int i=axisStartIndex; i<[methodSignature numberOfArguments]; i++) { + const char *type = [methodSignature getArgumentTypeAtIndex:i]; + + // ensure that the axis arguments are integers + if (!TypeIsIntegerType(type)) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"axis type must be NSInteger or NSUInteger" userInfo:nil]; } - // we need a buffer to pull out the argument data, so we'll figure out the size of the data first and then make the buffer - NSUInteger bufferSize = 0; - NSGetSizeAndAlignment(type, &bufferSize, NULL); - UInt8 argumentBuffer[bufferSize]; - memset(argumentBuffer, 0, bufferSize); - - // fetch the actual value data into our fancy buffer - [anInvocation getArgument:argumentBuffer atIndex:i]; - - // now box it up and tie it with a bow - NSValue *value = [NSValue value:argumentBuffer withObjCType:type]; - - if (value) { - [argumentValues addObject:value]; + NSInteger axisValue = 0; + [anInvocation getArgument:&axisValue atIndex:i]; + [propertyKey addObject:@(axisValue)]; + } + + if (isGetter) { + // convert the getter's selector into a setter's selector since that's what we actually key the property value with + NSMutableString *selectorKeyString = [NSStringFromSelector([anInvocation selector]) mutableCopy]; + [selectorKeyString replaceCharactersInRange:NSMakeRange(0, 1) withString:[[selectorKeyString substringToIndex:1] uppercaseString]]; + [selectorKeyString insertString:@"set" atIndex:0]; + + // if the property has 1 or more axis parts, we need to take those into account, too + if ([methodSignature numberOfArguments] > 2) { + const NSRange colonRange = [selectorKeyString rangeOfString:@":"]; + const NSRange forRange = [selectorKeyString rangeOfString:@"For"]; + + if (colonRange.location != NSNotFound && forRange.location != NSNotFound && colonRange.location > NSMaxRange(forRange)) { + const NSRange axisNameRange = NSMakeRange(forRange.location+3, colonRange.location-forRange.location-3); + NSString *axisName = [selectorKeyString substringWithRange:axisNameRange]; + axisName = [axisName stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:[[axisName substringToIndex:1] uppercaseString]]; + NSString *axisSelectorPartName = [NSString stringWithFormat:@"for%@:", axisName]; + [selectorKeyString insertString:axisSelectorPartName atIndex:NSMaxRange(colonRange)]; + [selectorKeyString replaceCharactersInRange:NSMakeRange(forRange.location, colonRange.location-forRange.location) withString:@""]; + } } else { - @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"something terrible has happened" userInfo:nil]; + [selectorKeyString appendString:@":"]; } + + // finish building the property key now that we have the expected selector name + [propertyKey addObject:[selectorKeyString copy]]; + + // fetch the current property value using the key and put it in the current invocation + // so it can be returned to the caller + UIAppearanceProperty *propertyValue = [_settings objectForKey:propertyKey]; + [propertyValue setReturnValueForInvocation:anInvocation]; } + else if (isSetter) { + NSString *selectorString = NSStringFromSelector([anInvocation selector]); - if (isSetter) { - // make a key so we can store this particular property value given the axis values - UIAppearanceProperty *key = [[UIAppearanceProperty alloc] initWithSelector:[anInvocation selector] - axisValues:[argumentValues subarrayWithRange:NSMakeRange(1, [argumentValues count]-1)]]; - [_settings setObject:[argumentValues objectAtIndex:0] forKey:key]; + // finish building the property key using the selector we have + [propertyKey addObject:selectorString]; + + // save the actual property value using the key + [_settings setObject:[[UIAppearanceProperty alloc] initWithInvocation:anInvocation] forKey:propertyKey]; + + // WARNING! Swizzling ahead! // what we're doing here is sneakily overriding the existing implemention with our own so we can track when the setter is called // and not have the appearance defaults override if a more local setting has been made. @@ -302,9 +324,8 @@ - (void)forwardInvocation:(NSInvocation *)anInvocation // for that are either deprecated or marked as "don't use" in the docs. :/ this is the best I could come up with given my // current knowledge of how everything works at this abstraction level. abandon all hope, ye who enter here... - NSString *selectorString = NSStringFromSelector([anInvocation selector]); NSMutableDictionary *methodOverrides = objc_getAssociatedObject(_targetClass, UIAppearanceSetterOverridesAssociatedObjectKey); - + if (!methodOverrides) { methodOverrides = [NSMutableDictionary dictionaryWithCapacity:1]; objc_setAssociatedObject(_targetClass, UIAppearanceSetterOverridesAssociatedObjectKey, methodOverrides, OBJC_ASSOCIATION_RETAIN); @@ -315,7 +336,7 @@ - (void)forwardInvocation:(NSInvocation *)anInvocation if (method) { IMP implementation = method_getImplementation(method); - IMP overrideImplementation = ImplementationForPropertyType([[anInvocation methodSignature] getArgumentTypeAtIndex:2]); + IMP overrideImplementation = ImplementationForPropertyType([methodSignature getArgumentTypeAtIndex:2]); if (implementation != overrideImplementation) { [methodOverrides setObject:[NSValue valueWithBytes:&implementation objCType:@encode(IMP)] forKey:selectorString]; @@ -323,47 +344,8 @@ - (void)forwardInvocation:(NSInvocation *)anInvocation } } } - - [key release]; - } else if (isGetter) { - // convert the getter's selector into a setter's selector since that's what we keyed on above - NSMutableString *selectorString = [NSStringFromSelector([anInvocation selector]) mutableCopy]; - [selectorString replaceCharactersInRange:NSMakeRange(0, 1) withString:[[selectorString substringToIndex:1] uppercaseString]]; - [selectorString insertString:@"set" atIndex:0]; - - // if the property has 1 or more axis parts, we need to take those into account, too - if ([[anInvocation methodSignature] numberOfArguments] > 2) { - const NSRange colonRange = [selectorString rangeOfString:@":"]; - const NSRange forRange = [selectorString rangeOfString:@"For"]; - - if (colonRange.location != NSNotFound && forRange.location != NSNotFound && colonRange.location > NSMaxRange(forRange)) { - const NSRange axisNameRange = NSMakeRange(forRange.location+3, colonRange.location-forRange.location-3); - NSString *axisName = [selectorString substringWithRange:axisNameRange]; - axisName = [axisName stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:[[axisName substringToIndex:1] uppercaseString]]; - NSString *axisSelectorPartName = [NSString stringWithFormat:@"for%@:", axisName]; - [selectorString insertString:axisSelectorPartName atIndex:NSMaxRange(colonRange)]; - [selectorString replaceCharactersInRange:NSMakeRange(forRange.location, colonRange.location-forRange.location) withString:@""]; - } - } else { - [selectorString appendString:@":"]; - } - - // now build a key based on the generated setter selector and the given axis arguments and fetch the matching stored property value - UIAppearanceProperty *key = [[UIAppearanceProperty alloc] initWithSelector:NSSelectorFromString(selectorString) axisValues:argumentValues]; - NSValue *propertyValue = [_settings objectForKey:key]; - - // setup a return data buffer and zero it - const NSUInteger returnLength = [[anInvocation methodSignature] methodReturnLength]; - UInt8 returnData[returnLength]; - memset(returnData, 0, returnLength); - - // fetch the value and return it - if there is none, this ends up returning a zeroed data structure - [propertyValue getValue:returnData]; - [anInvocation setReturnValue:returnData]; - - [key release]; - [selectorString release]; - } else { + } + else { // derp [self doesNotRecognizeSelector:[anInvocation selector]]; } @@ -376,7 +358,7 @@ - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector - (NSDictionary *)_appearancePropertiesAndValues { - return [[_settings copy] autorelease]; + return [_settings copy]; } @end diff --git a/UIKit/Classes/UIApplication.h b/UIKit/Classes/UIApplication.h index d72a1f25..1ee7e7f9 100644 --- a/UIKit/Classes/UIApplication.h +++ b/UIKit/Classes/UIApplication.h @@ -51,18 +51,34 @@ extern NSString *const UIApplicationDidReceiveMemoryWarningNotification; extern NSString *const UITrackingRunLoopMode; -typedef enum { +typedef NS_ENUM(NSInteger, UIStatusBarStyle) { UIStatusBarStyleDefault, UIStatusBarStyleBlackTranslucent, UIStatusBarStyleBlackOpaque -} UIStatusBarStyle; +}; -typedef enum { +typedef NS_ENUM(NSInteger, UIStatusBarAnimation) { + UIStatusBarAnimationNone, + UIStatusBarAnimationFade, + UIStatusBarAnimationSlide, +}; + +typedef NS_ENUM(NSInteger, UIInterfaceOrientation) { UIInterfaceOrientationPortrait = UIDeviceOrientationPortrait, UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown, UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight, UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft -} UIInterfaceOrientation; +}; + +typedef NS_OPTIONS(NSUInteger, UIInterfaceOrientationMask) { + UIInterfaceOrientationMaskPortrait = (1 << UIInterfaceOrientationPortrait), + UIInterfaceOrientationMaskLandscapeLeft = (1 << UIInterfaceOrientationLandscapeLeft), + UIInterfaceOrientationMaskLandscapeRight = (1 << UIInterfaceOrientationLandscapeRight), + UIInterfaceOrientationMaskPortraitUpsideDown = (1 << UIInterfaceOrientationPortraitUpsideDown), + UIInterfaceOrientationMaskLandscape = (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight), + UIInterfaceOrientationMaskAll = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortraitUpsideDown), + UIInterfaceOrientationMaskAllButUpsideDown = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight), +}; #define UIInterfaceOrientationIsPortrait(orientation) \ ((orientation) == UIInterfaceOrientationPortrait || \ @@ -73,12 +89,13 @@ typedef enum { (orientation) == UIInterfaceOrientationLandscapeRight) // push is not gonna work in mac os, unless you are apple (facetime) -typedef enum { - UIRemoteNotificationTypeNone = 0, - UIRemoteNotificationTypeBadge = 1 << 0, - UIRemoteNotificationTypeSound = 1 << 1, - UIRemoteNotificationTypeAlert = 1 << 2 -} UIRemoteNotificationType; +typedef NS_OPTIONS(NSUInteger, UIRemoteNotificationType) { + UIRemoteNotificationTypeNone = 0, + UIRemoteNotificationTypeBadge = 1 << 0, + UIRemoteNotificationTypeSound = 1 << 1, + UIRemoteNotificationTypeAlert = 1 << 2, + UIRemoteNotificationTypeNewsstandContentAvailability = 1 << 3 +}; // whenever the NSApplication is no longer "active" from OSX's point of view, your UIApplication instance // will switch to UIApplicationStateInactive. This happens when the app is no longer in the foreground, for instance. @@ -101,11 +118,11 @@ typedef enum { // guarentee that your expiration handler will even be called. additionally, the reliability of your network is certainly // going to be suspect when entering sleep as well. so be aware - but basically these same constraints exist on iOS so // in many respects it shouldn't affect your code much or at all. -typedef enum { +typedef NS_ENUM(NSInteger, UIApplicationState) { UIApplicationStateActive, UIApplicationStateInactive, UIApplicationStateBackground -} UIApplicationState; +}; typedef NSUInteger UIBackgroundTaskIdentifier; @@ -114,22 +131,7 @@ extern const NSTimeInterval UIMinimumKeepAliveTimeout; @class UIWindow, UIApplication, UILocalNotification; -@interface UIApplication : UIResponder { -@private - UIEvent *_currentEvent; - UIWindow *_keyWindow; - NSMutableSet *_visibleWindows; - UIApplicationState _applicationState; - __unsafe_unretained id _delegate; - BOOL _idleTimerDisabled; - BOOL _networkActivityIndicatorVisible; - BOOL _applicationSupportsShakeToEdit; - NSUInteger _ignoringInteractionEvents; - NSInteger _applicationIconBadgeNumber; - NSDate *_backgroundTasksExpirationDate; - NSMutableArray *_backgroundTasks; -} - +@interface UIApplication : UIResponder + (UIApplication *)sharedApplication; - (BOOL)sendAction:(SEL)action to:(id)target from:(id)sender forEvent:(UIEvent *)event; @@ -139,6 +141,7 @@ extern const NSTimeInterval UIMinimumKeepAliveTimeout; - (BOOL)canOpenURL:(NSURL *)URL; - (void)setStatusBarStyle:(UIStatusBarStyle)statusBarStyle animated:(BOOL)animated; // no effect +- (void)setStatusBarHidden:(BOOL)hidden withAnimation:(UIStatusBarAnimation)animation; - (void)beginIgnoringInteractionEvents; - (void)endIgnoringInteractionEvents; @@ -148,10 +151,14 @@ extern const NSTimeInterval UIMinimumKeepAliveTimeout; - (void)cancelLocalNotification:(UILocalNotification *)notification; - (void)cancelAllLocalNotifications; +- (void)registerForRemoteNotificationTypes:(UIRemoteNotificationType)types; +- (void)unregisterForRemoteNotifications; +- (UIRemoteNotificationType)enabledRemoteNotificationTypes; + - (UIBackgroundTaskIdentifier)beginBackgroundTaskWithExpirationHandler:(void(^)(void))handler; - (void)endBackgroundTask:(UIBackgroundTaskIdentifier)identifier; -@property (nonatomic, readonly) UIWindow *keyWindow; +@property (nonatomic, weak, readonly) UIWindow *keyWindow; @property (nonatomic, readonly) NSArray *windows; @property (nonatomic, getter=isStatusBarHidden, readonly) BOOL statusBarHidden; @property (nonatomic, readonly) CGRect statusBarFrame; @@ -166,10 +173,18 @@ extern const NSTimeInterval UIMinimumKeepAliveTimeout; @property (nonatomic, readonly) NSTimeInterval backgroundTimeRemaining; // always 0 @property (nonatomic) NSInteger applicationIconBadgeNumber; // no effect, but does set/get the number correctly @property (nonatomic, copy) NSArray *scheduledLocalNotifications; // no effect, returns nil - @end - @interface UIApplication(UIApplicationDeprecated) - (void)setStatusBarHidden:(BOOL)hidden animated:(BOOL)animated __attribute__((deprecated)); // use -setStatusBarHidden:withAnimation: @end + +// This can replace your call to NSApplicationMain. It does not implement NSApplicationMain exactly (and it never calls NSApplicationMain) +// so you should use this with some caution. It does *not* subclass NSApplication but does allow you to subclass UIApplication if you want, +// although that's not really tested so it probably wouldn't work very well. It sets NSApplication's delegate to a very simple dummy object +// which traps -applicationShouldTerminate: to handle background tasks so you don't have to bother with it. Like NSApplicationMain, this +// looks for a NIB file in the Info.plist identified by the NSMainNibFile key and will load it using AppKit's NIB loading stuff. In an +// attempt to make this as confusing as possible, when the main NIB is loaded, it uses the UIApplication (NOT THE NSApplication!) as the +// file's owner! Yep. Insane, I know. I generally do not use NIBs myself, but it's nice for the menu bar. So... yeah... +// NOTE: This does not use NSPrincipalClass from Info.plist since iOS doesn't either, so if that exists in your Info.plist, it is ignored. +extern int UIApplicationMain(int argc, char *argv[], NSString *principalClassName, NSString *delegateClassName); diff --git a/UIKit/Classes/UIApplication.m b/UIKit/Classes/UIApplication.m index b9ac380d..6d05dd09 100644 --- a/UIKit/Classes/UIApplication.m +++ b/UIKit/Classes/UIApplication.m @@ -27,18 +27,12 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#import "UIApplication+UIPrivate.h" -#import "UIScreen+UIPrivate.h" +#import "UIApplicationAppKitIntegration.h" #import "UIScreenAppKitIntegration.h" -#import "UIKitView.h" -#import "UIEvent+UIPrivate.h" -#import "UITouch+UIPrivate.h" #import "UIWindow+UIPrivate.h" -#import "UIPopoverController+UIPrivate.h" -#import "UIResponderAppKitIntegration.h" -#import "UIApplicationAppKitIntegration.h" -#import "UIKey+UIPrivate.h" +#import "UIKitView.h" #import "UIBackgroundTask.h" +#import "UINSApplicationDelegate.h" #import NSString *const UIApplicationWillChangeStatusBarOrientationNotification = @"UIApplicationWillChangeStatusBarOrientationNotification"; @@ -68,86 +62,31 @@ static UIApplication *_theApplication = nil; -static CGPoint ScreenLocationFromNSEvent(UIScreen *theScreen, NSEvent *theNSEvent) -{ - CGPoint screenLocation = NSPointToCGPoint([[theScreen UIKitView] convertPoint:[theNSEvent locationInWindow] fromView:nil]); - if (![[theScreen UIKitView] isFlipped]) { - // the y coord from the NSView might be inverted - screenLocation.y = theScreen.bounds.size.height - screenLocation.y - 1; - } - return screenLocation; -} - -static CGPoint ScrollDeltaFromNSEvent(NSEvent *theNSEvent) -{ - double dx, dy; - - CGEventRef cgEvent = [theNSEvent CGEvent]; - const int64_t isContinious = CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventIsContinuous); - - if (isContinious == 0) { - CGEventSourceRef source = CGEventCreateSourceFromEvent(cgEvent); - double pixelsPerLine; - - if (source) { - pixelsPerLine = CGEventSourceGetPixelsPerLine(source); - CFRelease(source); - } else { - // docs often say things like, "the default is near 10" so it seems reasonable that if the source doesn't work - // for some reason to fetch the pixels per line, then 10 is probably a decent fallback value. :) - pixelsPerLine = 10; - } - - dx = CGEventGetDoubleValueField(cgEvent, kCGScrollWheelEventFixedPtDeltaAxis2) * pixelsPerLine; - dy = CGEventGetDoubleValueField(cgEvent, kCGScrollWheelEventFixedPtDeltaAxis1) * pixelsPerLine; - } else { - dx = CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis2); - dy = CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis1); - } - - return CGPointMake(-dx, -dy); -} - -static BOOL TouchIsActiveGesture(UITouch *touch) -{ - return (touch.phase == _UITouchPhaseGestureBegan || touch.phase == _UITouchPhaseGestureChanged); -} - -static BOOL TouchIsActiveNonGesture(UITouch *touch) -{ - return (touch.phase == UITouchPhaseBegan || touch.phase == UITouchPhaseMoved || touch.phase == UITouchPhaseStationary); -} - -static BOOL TouchIsActive(UITouch *touch) -{ - return TouchIsActiveGesture(touch) || TouchIsActiveNonGesture(touch); -} - -@implementation UIApplication -@synthesize keyWindow=_keyWindow, delegate=_delegate, idleTimerDisabled=_idleTimerDisabled, applicationSupportsShakeToEdit=_applicationSupportsShakeToEdit; -@synthesize applicationIconBadgeNumber = _applicationIconBadgeNumber, applicationState=_applicationState; - -+ (void)initialize -{ - if (self == [UIApplication class]) { - _theApplication = [[UIApplication alloc] init]; - } +@implementation UIApplication { + NSUInteger _ignoringInteractionEvents; + NSDate *_backgroundTasksExpirationDate; + NSMutableArray *_backgroundTasks; } + (UIApplication *)sharedApplication { + if (!_theApplication) { + _theApplication = [[self alloc] init]; + } + return _theApplication; } - (id)init { if ((self=[super init])) { - _currentEvent = [[UIEvent alloc] initWithEventType:UIEventTypeTouches]; - [_currentEvent _setTouch:[[[UITouch alloc] init] autorelease]]; - _visibleWindows = [[NSMutableSet alloc] init]; _backgroundTasks = [[NSMutableArray alloc] init]; _applicationState = UIApplicationStateActive; _applicationSupportsShakeToEdit = YES; // yeah... not *really* true, but UIKit defaults to YES :) + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_applicationWillFinishLaunching:) name:NSApplicationWillFinishLaunchingNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_applicationDidFinishLaunching:) name:NSApplicationDidFinishLaunchingNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_applicationWillTerminate:) name:NSApplicationWillTerminateNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_applicationWillResignActive:) name:NSApplicationWillResignActiveNotification object:nil]; @@ -166,11 +105,6 @@ - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; [[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:self]; - [_currentEvent release]; - [_visibleWindows release]; - [_backgroundTasks release]; - [_backgroundTasksExpirationDate release]; - [super dealloc]; } - (NSTimeInterval)statusBarOrientationAnimationDuration @@ -193,11 +127,6 @@ - (NSTimeInterval)backgroundTimeRemaining return [_backgroundTasksExpirationDate timeIntervalSinceNow]; } -- (BOOL)isNetworkActivityIndicatorVisible -{ - return _networkActivityIndicatorVisible; -} - - (void)setNetworkActivityIndicatorVisible:(BOOL)b { if (b != [self isNetworkActivityIndicatorVisible]) { @@ -243,6 +172,23 @@ - (void)setStatusBarStyle:(UIStatusBarStyle)statusBarStyle animated:(BOOL)animat { } +- (void)setStatusBarHidden:(BOOL)hidden withAnimation:(UIStatusBarAnimation)animation +{ +} + +- (void)registerForRemoteNotificationTypes:(UIRemoteNotificationType)types +{ +} + +- (void)unregisterForRemoteNotifications +{ +} + +- (UIRemoteNotificationType)enabledRemoteNotificationTypes +{ + return UIRemoteNotificationTypeNone; +} + - (void)presentLocalNotificationNow:(UILocalNotification *)notification { } @@ -266,7 +212,7 @@ - (void)setScheduledLocalNotifications:(NSArray *)scheduledLocalNotifications - (UIBackgroundTaskIdentifier)beginBackgroundTaskWithExpirationHandler:(void(^)(void))handler { - UIBackgroundTask *task = [[[UIBackgroundTask alloc] initWithExpirationHandler:handler] autorelease]; + UIBackgroundTask *task = [[UIBackgroundTask alloc] initWithExpirationHandler:handler]; [_backgroundTasks addObject:task]; return task.taskIdentifier; } @@ -335,7 +281,7 @@ - (BOOL)_runRunLoopForBackgroundTasksBeforeDate:(NSDate *)date - (void)_cancelBackgroundTasks { // if there's any remaining tasks, run their expiration handlers - for (UIBackgroundTask *task in [[_backgroundTasks copy] autorelease]) { + for (UIBackgroundTask *task in [_backgroundTasks copy]) { if (task.expirationHandler) { task.expirationHandler(); } @@ -354,8 +300,7 @@ - (NSApplicationTerminateReply)terminateApplicationBeforeDate:(NSDate *)timeoutD { [self _enterBackground]; - [_backgroundTasksExpirationDate release]; - _backgroundTasksExpirationDate = [timeoutDate retain]; + _backgroundTasksExpirationDate = timeoutDate; // we will briefly block here for a short time and run the runloop in an attempt to let the background tasks finish up before // actually prompting the user with an annoying alert. users are much more used to an app hanging for a brief moment while @@ -375,7 +320,6 @@ - (NSApplicationTerminateReply)terminateApplicationBeforeDate:(NSDate *)timeoutD [self _cancelBackgroundTasks]; // and reset our timer since we're done - [_backgroundTasksExpirationDate release]; _backgroundTasksExpirationDate = nil; // and return @@ -411,7 +355,6 @@ - (NSApplicationTerminateReply)terminateApplicationBeforeDate:(NSDate *)timeoutD [self _cancelBackgroundTasks]; // and reset our timer since we're done - [_backgroundTasksExpirationDate release]; _backgroundTasksExpirationDate = nil; // now just in case all of this happened too quickly and the user might not have had time to read and understand the alert, @@ -424,7 +367,6 @@ - (NSApplicationTerminateReply)terminateApplicationBeforeDate:(NSDate *)timeoutD } } - [alert release]; [NSApp endModalSession:session]; @@ -436,7 +378,7 @@ - (NSApplicationTerminateReply)terminateApplicationBeforeDate:(NSDate *)timeoutD // because we're probably in that run loop mode due to how -applicationShouldTerminate: does things. I don't // know if I could do this same thing with a couple of simple GCD calls, but whatever, this works too. :) [self performSelectorOnMainThread:@selector(_runBackgroundTasks:) - withObject:[[taskFinisher copy] autorelease] + withObject:[taskFinisher copy] waitUntilDone:NO modes:[NSArray arrayWithObjects:NSModalPanelRunLoopMode, NSRunLoopCommonModes, nil]]; @@ -453,7 +395,6 @@ - (void)_computerWillSleep:(NSNotification *)note // the machine is about to go to sleep.. so we'll just do things in a blocking way in this case while still handling // any pending background tasks. - [_backgroundTasksExpirationDate release]; _backgroundTasksExpirationDate = [[NSDate alloc] initWithTimeIntervalSinceNow:29]; for (;;) { @@ -465,7 +406,6 @@ - (void)_computerWillSleep:(NSNotification *)note [self _cancelBackgroundTasks]; // and reset our timer since we're done - [_backgroundTasksExpirationDate release]; _backgroundTasksExpirationDate = nil; } } @@ -475,36 +415,26 @@ - (void)_computerDidWakeUp:(NSNotification *)note [self _enterForeground]; } -- (void)_setKeyWindow:(UIWindow *)newKeyWindow +- (NSArray *)windows { - _keyWindow = newKeyWindow; - - if (_keyWindow) { - // this will make the NSView that the key window lives on the first responder in its NSWindow - // highly confusing, but I think this is mostly the correct thing to do - // when a UIView is made first responder, it also tells its window to become the key window - // which means that we can ultimately end up here and if keyboard stuff is to work as expected - // (for example) the underlying NSView really needs to be the first responder as far as AppKit - // is concerned. this is all very confusing in my mind right now, but I think it makes sense. - [[[_keyWindow.screen UIKitView] window] makeFirstResponder:[_keyWindow.screen UIKitView]]; + NSMutableArray *windows = [NSMutableArray new]; + + for (UIScreen *screen in [UIScreen screens]) { + [windows addObjectsFromArray:screen.windows]; } + + return [windows sortedArrayUsingDescriptors:@[[[NSSortDescriptor alloc] initWithKey:@"windowLevel" ascending:YES]]]; } -- (void)_windowDidBecomeVisible:(UIWindow *)theWindow -{ - [_visibleWindows addObject:[NSValue valueWithNonretainedObject:theWindow]]; -} - -- (void)_windowDidBecomeHidden:(UIWindow *)theWindow -{ - if (theWindow == _keyWindow) [self _setKeyWindow:nil]; - [_visibleWindows removeObject:[NSValue valueWithNonretainedObject:theWindow]]; -} - -- (NSArray *)windows +- (UIWindow *)keyWindow { - NSSortDescriptor *sort = [[[NSSortDescriptor alloc] initWithKey:@"windowLevel" ascending:YES] autorelease]; - return [[_visibleWindows valueForKey:@"nonretainedObjectValue"] sortedArrayUsingDescriptors:[NSArray arrayWithObject:sort]]; + for (UIWindow *window in self.windows) { + if (window.isKeyWindow) { + return window; + } + } + + return nil; } - (BOOL)sendAction:(SEL)action to:(id)target from:(id)sender forEvent:(UIEvent *)event @@ -542,47 +472,21 @@ - (BOOL)sendAction:(SEL)action to:(id)target from:(id)sender forEvent:(UIEvent * } if (target) { - [target performSelector:action withObject:sender withObject:event]; + typedef void(*EventActionMethod)(id, SEL, id, UIEvent *); + EventActionMethod method = (EventActionMethod)[target methodForSelector:action]; + method(target, action, sender, event); return YES; - } else { - return NO; - } -} - -- (UIResponder *)_firstResponderForScreen:(UIScreen *)screen -{ - if (_keyWindow.screen == screen) { - return [_keyWindow _firstResponder]; - } else { - return nil; - } -} - -- (BOOL)_sendActionToFirstResponder:(SEL)action withSender:(id)sender fromScreen:(UIScreen *)theScreen -{ - UIResponder *responder = [self _firstResponderForScreen:theScreen]; - - while (responder) { - if ([responder respondsToSelector:action]) { - [responder performSelector:action withObject:sender]; - return YES; - } else { - responder = [responder nextResponder]; - } } return NO; } -- (BOOL)_firstResponderCanPerformAction:(SEL)action withSender:(id)sender fromScreen:(UIScreen *)theScreen -{ - return [[self _firstResponderForScreen:theScreen] canPerformAction:action withSender:sender]; -} - - (void)sendEvent:(UIEvent *)event { - for (UITouch *touch in [event allTouches]) { - [touch.window sendEvent:event]; + if (event.type == UIEventTypeTouches) { + [self.windows makeObjectsPerformSelector:@selector(sendEvent:) withObject:event]; + } else { + [self.keyWindow sendEvent:event]; } } @@ -596,204 +500,42 @@ - (BOOL)canOpenURL:(NSURL *)url return (url? [[NSWorkspace sharedWorkspace] URLForApplicationToOpenURL:url] : nil) != nil; } -- (BOOL)_sendGlobalKeyboardNSEvent:(NSEvent *)theNSEvent fromScreen:(UIScreen *)theScreen +- (void)_applicationWillFinishLaunching:(NSNotification *)note { - if (![self isIgnoringInteractionEvents]) { - UIKey *key = [[[UIKey alloc] initWithNSEvent:theNSEvent] autorelease]; - - if (key.type == UIKeyTypeEnter || (key.commandKeyPressed && key.type == UIKeyTypeReturn)) { - if ([self _firstResponderCanPerformAction:@selector(commit:) withSender:key fromScreen:theScreen]) { - return [self _sendActionToFirstResponder:@selector(commit:) withSender:key fromScreen:theScreen]; - } - } - } + NSDictionary *options = nil; - return NO; -} - -- (BOOL)_sendKeyboardNSEvent:(NSEvent *)theNSEvent fromScreen:(UIScreen *)theScreen -{ - if (![self isIgnoringInteractionEvents]) { - if (![self _sendGlobalKeyboardNSEvent:theNSEvent fromScreen:theScreen]) { - UIResponder *firstResponder = [self _firstResponderForScreen:theScreen]; - - if (firstResponder) { - UIKey *key = [[[UIKey alloc] initWithNSEvent:theNSEvent] autorelease]; - UIEvent *event = [[[UIEvent alloc] initWithEventType:UIEventTypeKeyPress] autorelease]; - [event _setTimestamp:[theNSEvent timestamp]]; - - [firstResponder keyPressed:key withEvent:event]; - return ![event _isUnhandledKeyPressEvent]; - } - } + if ([_delegate respondsToSelector:@selector(application:willFinishLaunchingOnDesktopWithOptions:)]) { + [_delegate application:self willFinishLaunchingOnDesktopWithOptions:options]; } - return NO; -} - -- (void)_setCurrentEventTouchedViewWithNSEvent:(NSEvent *)theNSEvent fromScreen:(UIScreen *)theScreen -{ - const CGPoint screenLocation = ScreenLocationFromNSEvent(theScreen, theNSEvent); - UITouch *touch = [[_currentEvent allTouches] anyObject]; - UIView *previousView = [touch.view retain]; - - [touch _setTouchedView:[theScreen _hitTest:screenLocation event:_currentEvent]]; - - if (touch.view != previousView) { - [previousView mouseExitedView:previousView enteredView:touch.view withEvent:_currentEvent]; - [touch.view mouseExitedView:previousView enteredView:touch.view withEvent:_currentEvent]; + if ([_delegate respondsToSelector:@selector(application:willFinishLaunchingWithOptions:)]) { + [_delegate application:self willFinishLaunchingWithOptions:options]; } - - [previousView release]; } -- (void)_sendMouseNSEvent:(NSEvent *)theNSEvent fromScreen:(UIScreen *)theScreen +- (void)_applicationDidFinishLaunching:(NSNotification *)note { - UITouch *touch = [[_currentEvent allTouches] anyObject]; - - [_currentEvent _setTimestamp:[theNSEvent timestamp]]; - - const NSTimeInterval timestamp = [theNSEvent timestamp]; - const CGPoint screenLocation = ScreenLocationFromNSEvent(theScreen, theNSEvent); - - // this is a special case to cancel any existing gestures (as far as the client code is concerned) if a mouse - // button is pressed mid-gesture. the reason is that sometimes when using a magic mouse a user will intend to - // click but if their finger moves against the surface ever so slightly, it will trigger a touch gesture to - // begin instead. without this, the fact that we're in a touch gesture phase effectively overrules everything - // else and clicks end up not getting registered. I don't think it's right to allow clicks to pass through when - // we're in a gesture state since that'd be somewhat like a multitouch scenerio on a real iOS device and we're - // not supporting anything like that at the moment. - if (TouchIsActiveGesture(touch) && ([theNSEvent type] == NSLeftMouseDown || [theNSEvent type] == NSRightMouseDown)) { - [touch _updatePhase:_UITouchPhaseGestureEnded screenLocation:screenLocation timestamp:timestamp]; - [self sendEvent:_currentEvent]; - } - - if (TouchIsActiveNonGesture(touch)) { - switch ([theNSEvent type]) { - case NSLeftMouseUp: - [touch _updatePhase:UITouchPhaseEnded screenLocation:screenLocation timestamp:timestamp]; - [self sendEvent:_currentEvent]; - break; - - case NSLeftMouseDragged: - [touch _updatePhase:UITouchPhaseMoved screenLocation:screenLocation timestamp:timestamp]; - [self sendEvent:_currentEvent]; - break; - } - } else if (TouchIsActiveGesture(touch)) { - switch ([theNSEvent type]) { - case NSEventTypeEndGesture: - [touch _updatePhase:_UITouchPhaseGestureEnded screenLocation:screenLocation timestamp:timestamp]; - [self sendEvent:_currentEvent]; - break; - - case NSScrollWheel: - // when captured here, the scroll wheel event had to have been part of a gesture - in other words it is a - // touch device scroll event and is therefore mapped to UIPanGestureRecognizer. - [touch _updateGesture:_UITouchGesturePan screenLocation:screenLocation delta:ScrollDeltaFromNSEvent(theNSEvent) rotation:0 magnification:0 timestamp:timestamp]; - [self sendEvent:_currentEvent]; - break; - - case NSEventTypeMagnify: - [touch _updateGesture:_UITouchGesturePinch screenLocation:screenLocation delta:CGPointZero rotation:0 magnification:[theNSEvent magnification] timestamp:timestamp]; - [self sendEvent:_currentEvent]; - break; - - case NSEventTypeRotate: - [touch _updateGesture:_UITouchGestureRotation screenLocation:screenLocation delta:CGPointZero rotation:[theNSEvent rotation] magnification:0 timestamp:timestamp]; - [self sendEvent:_currentEvent]; - break; - - case NSEventTypeSwipe: - [touch _updateGesture:_UITouchGestureSwipe screenLocation:screenLocation delta:ScrollDeltaFromNSEvent(theNSEvent) rotation:0 magnification:0 timestamp:timestamp]; - [self sendEvent:_currentEvent]; - break; - } - } else if (![self isIgnoringInteractionEvents]) { - switch ([theNSEvent type]) { - case NSLeftMouseDown: - [touch _setPhase:UITouchPhaseBegan screenLocation:screenLocation tapCount:[theNSEvent clickCount] timestamp:timestamp]; - [self _setCurrentEventTouchedViewWithNSEvent:theNSEvent fromScreen:theScreen]; - [self sendEvent:_currentEvent]; - break; - - case NSEventTypeBeginGesture: - [touch _setPhase:_UITouchPhaseGestureBegan screenLocation:screenLocation tapCount:0 timestamp:timestamp]; - [self _setCurrentEventTouchedViewWithNSEvent:theNSEvent fromScreen:theScreen]; - [self sendEvent:_currentEvent]; - break; - - case NSScrollWheel: - // we should only get a scroll wheel event down here if it was done on a non-touch device or was the result of a momentum - // scroll, so they are treated differently so we can tell them apart later in UIPanGestureRecognizer and UIScrollWheelGestureRecognizer - // which are both used by UIScrollView. - [touch _setDiscreteGesture:_UITouchDiscreteGestureScrollWheel screenLocation:screenLocation tapCount:0 delta:ScrollDeltaFromNSEvent(theNSEvent) timestamp:timestamp]; - [self _setCurrentEventTouchedViewWithNSEvent:theNSEvent fromScreen:theScreen]; - [self sendEvent:_currentEvent]; - break; + NSDictionary *options = nil; - case NSRightMouseDown: - [touch _setDiscreteGesture:_UITouchDiscreteGestureRightClick screenLocation:screenLocation tapCount:[theNSEvent clickCount] delta:CGPointZero timestamp:timestamp]; - [self _setCurrentEventTouchedViewWithNSEvent:theNSEvent fromScreen:theScreen]; - [self sendEvent:_currentEvent]; - break; - - case NSMouseMoved: - case NSMouseEntered: - case NSMouseExited: - [touch _setDiscreteGesture:_UITouchDiscreteGestureMouseMove screenLocation:screenLocation tapCount:0 delta:ScrollDeltaFromNSEvent(theNSEvent) timestamp:timestamp]; - [self _setCurrentEventTouchedViewWithNSEvent:theNSEvent fromScreen:theScreen]; - [self sendEvent:_currentEvent]; - break; - } - } -} - -// this is used to cause an interruption/cancel of the current touches. -// Use this when a modal UI element appears (such as a native popup menu), or when a UIPopoverController appears. It seems to make the most sense -// to call _cancelTouches *after* the modal menu has been dismissed, as this causes UI elements to remain in their "pushed" state while the menu -// is being displayed. If that behavior isn't desired, the simple solution is to present the menu from touchesEnded: instead of touchesBegan:. -- (void)_cancelTouches -{ - UITouch *touch = [[_currentEvent allTouches] anyObject]; - const BOOL wasActiveTouch = TouchIsActive(touch); - - [touch _setTouchPhaseCancelled]; - - if (wasActiveTouch) { - [self sendEvent:_currentEvent]; + if ([_delegate respondsToSelector:@selector(application:didFinishLaunchingOnDesktopWithOptions:)]) { + [_delegate application:self didFinishLaunchingOnDesktopWithOptions:options]; } -} -// this sets the touches view property to nil (while retaining the window property setting) -// this is used when a view is removed from its superview while it may have been the origin -// of an active touch. after a view is removed, we don't want to deliver any more touch events -// to it, but we still may need to route the touch itself for the sake of gesture recognizers -// so we need to retain the touch's original window setting so that events can still be routed. -// -// note that the touch itself is not being cancelled here so its phase remains unchanged. -// I'm not entirely certain if that's the correct thing to do, but I think it makes sense. The -// touch itself has not gone anywhere - just the view that it first touched. That breaks the -// delivery of the touch events themselves as far as the usual responder chain delivery is -// concerned, but that appears to be what happens in the real UIKit when you remove a view out -// from under an active touch. -// -// this whole thing is necessary because otherwise a gesture which may have been initiated over -// some specific view would end up getting cancelled/failing if the view under it happens to be -// removed. this is more common than you might expect. a UITableView that is not reusing rows -// does exactly this as it scrolls - which coincidentally is how I found this bug in the first -// place. :P -- (void)_removeViewFromTouches:(UIView *)aView -{ - for (UITouch *touch in [_currentEvent allTouches]) { - if (touch.view == aView) { - [touch _removeFromView]; - } + if ([_delegate respondsToSelector:@selector(application:didFinishLaunchingWithOptions:)]) { + [_delegate application:self didFinishLaunchingWithOptions:options]; + } else if ([_delegate respondsToSelector:@selector(applicationDidFinishLaunching:)]) { + [_delegate applicationDidFinishLaunching:self]; } + + [[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationDidFinishLaunchingNotification object:self]; } - (void)_applicationWillTerminate:(NSNotification *)note { + if ([_delegate respondsToSelector:@selector(applicationWillTerminateOnDesktop:)]) { + [_delegate applicationWillTerminateOnDesktop:self]; + } + if ([_delegate respondsToSelector:@selector(applicationWillTerminate:)]) { [_delegate applicationWillTerminate:self]; } @@ -827,6 +569,12 @@ - (void)_applicationDidBecomeActive:(NSNotification *)note } } +// this is only here because there's a real private API in Apple's UIKit that does something similar +- (void)_performMemoryWarning +{ + [[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationDidReceiveMemoryWarningNotification object:self]; +} + @end @@ -837,3 +585,65 @@ - (void)setStatusBarHidden:(BOOL)hidden animated:(BOOL)animated } @end + +int UIApplicationMain(int argc, char *argv[], NSString *principalClassName, NSString *delegateClassName) +{ + @autoreleasepool { + UIApplication *app = principalClassName? [NSClassFromString(principalClassName) sharedApplication] : [UIApplication sharedApplication]; + id delegate = delegateClassName? [NSClassFromString(delegateClassName) new] : nil; + + [app setDelegate:delegate]; + + NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary]; + NSString *mainNibName = [infoDictionary objectForKey:@"NSMainNibFile"]; + NSArray *topLevelObjects = nil; + NSNib *mainNib = [[NSNib alloc] initWithNibNamed:mainNibName bundle:[NSBundle mainBundle]]; + + [mainNib instantiateWithOwner:app topLevelObjects:&topLevelObjects]; + + id backgroundTaskCatchingDelegate = [UINSApplicationDelegate new]; + [[NSApplication sharedApplication] setDelegate:backgroundTaskCatchingDelegate]; + [[NSApplication sharedApplication] run]; + + // the only purpose of this is to confuse ARC. I'm not sure how else to do it. + // without this here, ARC thinks it can dealloc some stuff before we're really done + // with it, and since we're never really going to be done with this stuff, it has to + // be kept around as long as the app runs, but since the app never actually gets here + // it will never be executed but this prevents ARC from preemptively releasing things. + // meh. + [@[app, delegate, topLevelObjects, backgroundTaskCatchingDelegate] count]; + } + + // this never happens + return 0; +} + +void UIApplicationSendStationaryTouches(void) +{ + for (UIScreen *screen in [UIScreen screens]) { + [screen.UIKitView sendStationaryTouches]; + } +} + +void UIApplicationInterruptTouchesInView(UIView *view) +{ + // the intent here was that there needed to be a way to force-cancel touches to somewhat replicate situations that + // might arise on OSX that you could kinda/sorta pretend were phonecall-like events where you'd want a touch or + // gesture or something to cancel. these situations come up when things like popovers and modal menus are presented, + // + // If the need arises, my intent here is to send a notification or something on the *next* runloop to all UIKitViews + // attached to screens to tell them to kill off their current touch sequence (if any). It seems important that this + // happen on the *next* runloop cycle and not immediately because there were cases where the touch cancelling would + // happen in response to something like a touch ended event, so we can't just blindly cancel a touch while it's in + // the process of being evalulated since that could lead to very inconsistent behavior and really weird edge cases. + // by deferring the cancel, it would then be able to take the right action if the touch phase was something *other* + // than ended or cancelled by the time it attemped cancellation. + + if (!view) { + for (UIScreen *screen in [UIScreen screens]) { + [screen.UIKitView performSelector:@selector(cancelTouchesInView:) withObject:nil afterDelay:0]; + } + } else { + [view.window.screen.UIKitView performSelector:@selector(cancelTouchesInView:) withObject:view afterDelay:0]; + } +} diff --git a/UIKit/Classes/UIApplicationAppKitIntegration.h b/UIKit/Classes/UIApplicationAppKitIntegration.h index 9c9d158d..1c425e16 100644 --- a/UIKit/Classes/UIApplicationAppKitIntegration.h +++ b/UIKit/Classes/UIApplicationAppKitIntegration.h @@ -54,3 +54,9 @@ extern NSString *const UIApplicationNetworkActivityIndicatorChangedNotification; - (NSApplicationTerminateReply)terminateApplicationBeforeDate:(NSDate *)timeoutDate; @end + +// these are probably more internal the meant to be used publically, but just in case... here they are. +extern void UIApplicationInterruptTouchesInView(UIView *view); +extern void UIApplicationSendStationaryTouches(void); + + diff --git a/UIKit/Classes/UIApplicationDelegate.h b/UIKit/Classes/UIApplicationDelegate.h index fe094838..aa4f78a6 100644 --- a/UIKit/Classes/UIApplicationDelegate.h +++ b/UIKit/Classes/UIApplicationDelegate.h @@ -33,12 +33,22 @@ @protocol UIApplicationDelegate @optional +- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions; -- (void)applicationDidFinishLaunching:(UIApplication *)application; +- (void)applicationDidFinishLaunching:(UIApplication *)application; // not recommended - (void)applicationDidBecomeActive:(UIApplication *)application; - (void)applicationWillResignActive:(UIApplication *)application; - (void)applicationWillTerminate:(UIApplication *)application; - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation; - (void)applicationDidEnterBackground:(UIApplication *)application; - (void)applicationWillEnterForeground:(UIApplication *)application; + +// non-standard + +// these are all called immediately before the normal delegate methods of similar name +// these do NOT supercede the normal methods, if the normal ones also exist, they are also called! +- (void)application:(UIApplication *)application willFinishLaunchingOnDesktopWithOptions:(NSDictionary *)launchOptions; +- (void)application:(UIApplication *)application didFinishLaunchingOnDesktopWithOptions:(NSDictionary *)launchOptions; +- (void)applicationWillTerminateOnDesktop:(UIApplication *)application; + @end diff --git a/UIKit/Classes/UIBackgroundTask.h b/UIKit/Classes/UIBackgroundTask.h index 5805bf0f..dc55e8f6 100644 --- a/UIKit/Classes/UIBackgroundTask.h +++ b/UIKit/Classes/UIBackgroundTask.h @@ -29,14 +29,11 @@ #import "UIApplication.h" -@interface UIBackgroundTask : NSObject { - void (^_expirationHandler)(void); - UIBackgroundTaskIdentifier _taskIdentifier; -} +@interface UIBackgroundTask : NSObject - (id)initWithExpirationHandler:(void(^)(void))handler; -@property (nonatomic, readonly) void (^expirationHandler)(void); +@property (copy, nonatomic, readonly) void (^expirationHandler)(void); @property (nonatomic, readonly) UIBackgroundTaskIdentifier taskIdentifier; @end diff --git a/UIKit/Classes/UIBackgroundTask.m b/UIKit/Classes/UIBackgroundTask.m index 70997f10..9a555fda 100644 --- a/UIKit/Classes/UIBackgroundTask.m +++ b/UIKit/Classes/UIBackgroundTask.m @@ -30,7 +30,6 @@ #import "UIBackgroundTask.h" @implementation UIBackgroundTask -@synthesize expirationHandler=_expirationHandler, taskIdentifier=_taskIdentifier; - (id)initWithExpirationHandler:(void(^)(void))handler { @@ -42,10 +41,5 @@ - (id)initWithExpirationHandler:(void(^)(void))handler return self; } -- (void)dealloc -{ - [_expirationHandler release]; - [super dealloc]; -} @end diff --git a/UIKit/Classes/UIBarButtonItem.h b/UIKit/Classes/UIBarButtonItem.h index 9de8fc96..dfeddf0d 100644 --- a/UIKit/Classes/UIBarButtonItem.h +++ b/UIKit/Classes/UIBarButtonItem.h @@ -28,8 +28,9 @@ */ #import "UIBarItem.h" +#import "UIInterface.h" -typedef enum { +typedef NS_ENUM(NSInteger, UIBarButtonSystemItem) { UIBarButtonSystemItemDone, UIBarButtonSystemItemCancel, UIBarButtonSystemItemEdit, @@ -53,25 +54,20 @@ typedef enum { UIBarButtonSystemItemFastForward, UIBarButtonSystemItemUndo, // iPhoneOS 3.0 UIBarButtonSystemItemRedo, // iPhoneOS 3.0 -} UIBarButtonSystemItem; +}; -typedef enum { +typedef NS_ENUM(NSInteger, UIBarButtonItemStyle) { UIBarButtonItemStylePlain, UIBarButtonItemStyleBordered, UIBarButtonItemStyleDone, -} UIBarButtonItemStyle; +}; @class UIView, UIImage; @interface UIBarButtonItem : UIBarItem { @package - CGFloat _width; - UIView *_customView; - __unsafe_unretained id _target; - SEL _action; BOOL _isSystemItem; UIBarButtonSystemItem _systemItem; - UIBarButtonItemStyle _style; } - (id)initWithBarButtonSystemItem:(UIBarButtonSystemItem)systemItem target:(id)target action:(SEL)action; @@ -79,10 +75,25 @@ typedef enum { - (id)initWithTitle:(NSString *)title style:(UIBarButtonItemStyle)style target:(id)target action:(SEL)action; - (id)initWithImage:(UIImage *)image style:(UIBarButtonItemStyle)style target:(id)target action:(SEL)action; +- (UIImage *)backButtonBackgroundImageForState:(UIControlState)state barMetrics:(UIBarMetrics)barMetrics; +- (void)setBackButtonBackgroundImage:(UIImage *)backgroundImage forState:(UIControlState)state barMetrics:(UIBarMetrics)barMetrics; +- (UIOffset)backButtonTitlePositionAdjustmentForBarMetrics:(UIBarMetrics)barMetrics; +- (void)setBackButtonTitlePositionAdjustment:(UIOffset)adjustment forBarMetrics:(UIBarMetrics)barMetrics; +- (CGFloat)backButtonBackgroundVerticalPositionAdjustmentForBarMetrics:(UIBarMetrics)barMetrics; +- (void)setBackButtonBackgroundVerticalPositionAdjustment:(CGFloat)adjustment forBarMetrics:(UIBarMetrics)barMetrics; +- (CGFloat)backgroundVerticalPositionAdjustmentForBarMetrics:(UIBarMetrics)barMetrics; +- (void)setBackgroundVerticalPositionAdjustment:(CGFloat)adjustment forBarMetrics:(UIBarMetrics)barMetrics; +- (UIImage *)backgroundImageForState:(UIControlState)state barMetrics:(UIBarMetrics)barMetrics; +- (void)setBackgroundImage:(UIImage *)backgroundImage forState:(UIControlState)state barMetrics:(UIBarMetrics)barMetrics; +- (UIImage *)backgroundImageForState:(UIControlState)state style:(UIBarButtonItemStyle)style barMetrics:(UIBarMetrics)barMetrics; +- (void)setBackgroundImage:(UIImage *)backgroundImage forState:(UIControlState)state style:(UIBarButtonItemStyle)style barMetrics:(UIBarMetrics)barMetrics; +- (UIOffset)titlePositionAdjustmentForBarMetrics:(UIBarMetrics)barMetrics; +- (void)setTitlePositionAdjustment:(UIOffset)adjustment forBarMetrics:(UIBarMetrics)barMetrics; + @property (nonatomic) UIBarButtonItemStyle style; @property (nonatomic) CGFloat width; -@property (nonatomic, retain) UIView *customView; +@property (nonatomic, strong) UIView *customView; @property (nonatomic, assign) id target; @property (nonatomic) SEL action; - +@property (nonatomic, strong) UIColor *tintColor; @end diff --git a/UIKit/Classes/UIBarButtonItem.m b/UIKit/Classes/UIBarButtonItem.m index 2054a05a..7ef0f341 100644 --- a/UIKit/Classes/UIBarButtonItem.m +++ b/UIKit/Classes/UIBarButtonItem.m @@ -31,7 +31,6 @@ #import "UIView.h" @implementation UIBarButtonItem -@synthesize width=_width, customView=_customView, action=_action, target=_target, style=_style; - (id)init { @@ -84,15 +83,73 @@ - (id)initWithImage:(UIImage *)image style:(UIBarButtonItemStyle)style target:(i return self; } -- (void)dealloc -{ - [_customView release]; - [super dealloc]; -} - (UIView *)customView { return _isSystemItem? nil : _customView; } +- (UIImage *)backButtonBackgroundImageForState:(UIControlState)state barMetrics:(UIBarMetrics)barMetrics +{ + return nil; +} + +- (void)setBackButtonBackgroundImage:(UIImage *)backgroundImage forState:(UIControlState)state barMetrics:(UIBarMetrics)barMetrics +{ +} + +- (UIOffset)backButtonTitlePositionAdjustmentForBarMetrics:(UIBarMetrics)barMetrics +{ + return UIOffsetZero; +} + +- (void)setBackButtonTitlePositionAdjustment:(UIOffset)adjustment forBarMetrics:(UIBarMetrics)barMetrics +{ +} + +- (CGFloat)backButtonBackgroundVerticalPositionAdjustmentForBarMetrics:(UIBarMetrics)barMetrics +{ + return 0; +} + +- (void)setBackButtonBackgroundVerticalPositionAdjustment:(CGFloat)adjustment forBarMetrics:(UIBarMetrics)barMetrics +{ +} + +- (CGFloat)backgroundVerticalPositionAdjustmentForBarMetrics:(UIBarMetrics)barMetrics +{ + return 0; +} + +- (void)setBackgroundVerticalPositionAdjustment:(CGFloat)adjustment forBarMetrics:(UIBarMetrics)barMetrics +{ +} + +- (UIImage *)backgroundImageForState:(UIControlState)state barMetrics:(UIBarMetrics)barMetrics +{ + return nil; +} + +- (void)setBackgroundImage:(UIImage *)backgroundImage forState:(UIControlState)state barMetrics:(UIBarMetrics)barMetrics +{ +} + +- (UIImage *)backgroundImageForState:(UIControlState)state style:(UIBarButtonItemStyle)style barMetrics:(UIBarMetrics)barMetrics +{ + return nil; +} + +- (void)setBackgroundImage:(UIImage *)backgroundImage forState:(UIControlState)state style:(UIBarButtonItemStyle)style barMetrics:(UIBarMetrics)barMetrics +{ +} + +- (UIOffset)titlePositionAdjustmentForBarMetrics:(UIBarMetrics)barMetrics +{ + return UIOffsetZero; +} + +- (void)setTitlePositionAdjustment:(UIOffset)adjustment forBarMetrics:(UIBarMetrics)barMetrics +{ +} + @end diff --git a/UIKit/Classes/UIBarItem.h b/UIKit/Classes/UIBarItem.h index c27fe69c..2db53b00 100644 --- a/UIKit/Classes/UIBarItem.h +++ b/UIKit/Classes/UIBarItem.h @@ -31,22 +31,13 @@ @class UIImage; -@interface UIBarItem : NSObject { -@private - BOOL _enabled; - UIImage *_image; - UIEdgeInsets _imageInsets; - NSString *_title; - NSInteger _tag; -} +@interface UIBarItem : NSObject +- (void)setTitleTextAttributes:(NSDictionary *)attributes forState:(UIControlState)state; +- (NSDictionary *)titleTextAttributesForState:(UIControlState)state; @property (nonatomic, getter=isEnabled) BOOL enabled; -@property (nonatomic, retain) UIImage *image; +@property (nonatomic, strong) UIImage *image; @property (nonatomic, assign) UIEdgeInsets imageInsets; @property (nonatomic, copy) NSString *title; @property (nonatomic) NSInteger tag; - -- (void)setTitleTextAttributes:(NSDictionary *)attributes forState:(UIControlState)state; -- (NSDictionary *)titleTextAttributesForState:(UIControlState)state; - @end diff --git a/UIKit/Classes/UIBarItem.m b/UIKit/Classes/UIBarItem.m index cd19a5e9..e417420d 100644 --- a/UIKit/Classes/UIBarItem.m +++ b/UIKit/Classes/UIBarItem.m @@ -29,9 +29,9 @@ #import "UIBarItem.h" #import "UIImage.h" +#import "UIAppearanceInstance.h" @implementation UIBarItem -@synthesize enabled=_enabled, image=_image, imageInsets=_imageInsets, title=_title, tag=_tag; - (id)init { @@ -42,12 +42,6 @@ - (id)init return self; } -- (void)dealloc -{ - [_image release]; - [_title release]; - [super dealloc]; -} - (void)setTitleTextAttributes:(NSDictionary *)attributes forState:(UIControlState)state { diff --git a/UIKit/Classes/UIBezierPath.h b/UIKit/Classes/UIBezierPath.h index 8ebb18ad..c949a507 100644 --- a/UIKit/Classes/UIBezierPath.h +++ b/UIKit/Classes/UIBezierPath.h @@ -29,29 +29,15 @@ #import -enum { +typedef NS_OPTIONS(NSUInteger, UIRectCorner) { UIRectCornerTopLeft = 1 << 0, UIRectCornerTopRight = 1 << 1, UIRectCornerBottomLeft = 1 << 2, UIRectCornerBottomRight = 1 << 3, UIRectCornerAllCorners = ~0 }; -typedef NSUInteger UIRectCorner; - -@interface UIBezierPath : NSObject { -@private - CGPathRef _path; - CGFloat _lineWidth; - CGLineCap _lineCapStyle; - CGLineJoin _lineJoinStyle; - CGFloat _miterLimit; - CGFloat _flatness; - BOOL _usesEvenOddFillRule; - CGFloat *_lineDashPattern; - NSInteger _lineDashCount; - CGFloat _lineDashPhase; -} +@interface UIBezierPath : NSObject + (UIBezierPath *)bezierPath; + (UIBezierPath *)bezierPathWithRect:(CGRect)rect; + (UIBezierPath *)bezierPathWithOvalInRect:(CGRect)rect; @@ -68,33 +54,24 @@ typedef NSUInteger UIRectCorner; - (void)closePath; - (void)removeAllPoints; - (void)appendPath:(UIBezierPath *)bezierPath; - -@property (nonatomic) CGPathRef CGPath; -@property (nonatomic, readonly) CGPoint currentPoint; - -@property (nonatomic) CGFloat lineWidth; -@property (nonatomic) CGLineCap lineCapStyle; -@property (nonatomic) CGLineJoin lineJoinStyle; -@property (nonatomic) CGFloat miterLimit; -@property (nonatomic) CGFloat flatness; -@property (nonatomic) BOOL usesEvenOddFillRule; - - (void)setLineDash:(const CGFloat *)pattern count:(NSInteger)count phase:(CGFloat)phase; - (void)getLineDash:(CGFloat *)pattern count:(NSInteger *)count phase:(CGFloat *)phase; - - (void)fill; - (void)fillWithBlendMode:(CGBlendMode)blendMode alpha:(CGFloat)alpha; - - (void)stroke; - (void)strokeWithBlendMode:(CGBlendMode)blendMode alpha:(CGFloat)alpha; - - (void)addClip; - - (BOOL)containsPoint:(CGPoint)point; +- (void)applyTransform:(CGAffineTransform)transform; +@property (nonatomic) CGPathRef CGPath; +@property (nonatomic, readonly) CGPoint currentPoint; +@property (nonatomic) CGFloat lineWidth; +@property (nonatomic) CGLineCap lineCapStyle; +@property (nonatomic) CGLineJoin lineJoinStyle; +@property (nonatomic) CGFloat miterLimit; +@property (nonatomic) CGFloat flatness; +@property (nonatomic) BOOL usesEvenOddFillRule; @property (readonly, getter=isEmpty) BOOL empty; @property (nonatomic, readonly) CGRect bounds; - -- (void)applyTransform:(CGAffineTransform)transform; - @end diff --git a/UIKit/Classes/UIBezierPath.m b/UIKit/Classes/UIBezierPath.m index a21993a8..f100b989 100644 --- a/UIKit/Classes/UIBezierPath.m +++ b/UIKit/Classes/UIBezierPath.m @@ -30,9 +30,12 @@ #import "UIBezierPath.h" #import "UIGraphics.h" -@implementation UIBezierPath -@synthesize lineWidth=_lineWidth, lineCapStyle=_lineCapStyle, lineJoinStyle=_lineJoinStyle, miterLimit=_miterLimit; -@synthesize flatness=_flatness, usesEvenOddFillRule=_usesEvenOddFillRule, CGPath=_path; +@implementation UIBezierPath { + CGFloat *_lineDashPattern; + NSInteger _lineDashCount; + CGFloat _lineDashPhase; +} +@synthesize CGPath=_path; - (id)init { @@ -53,7 +56,32 @@ - (id)init - (void)dealloc { if (_path) CGPathRelease(_path); - [super dealloc]; +} + +- (id)copyWithZone:(NSZone *)zone +{ + UIBezierPath *copy = [[self class] new]; + + copy.CGPath = self.CGPath; + copy.lineWidth = self.lineWidth; + copy.lineCapStyle = self.lineCapStyle; + copy.lineJoinStyle = self.lineJoinStyle; + copy.miterLimit = self.miterLimit; + copy.flatness = self.flatness; + copy.usesEvenOddFillRule = self.usesEvenOddFillRule; + + NSInteger lineDashCount = 0; + [self getLineDash:NULL count:&lineDashCount phase:NULL]; + + if (lineDashCount > 0) { + CGFloat *lineDashPattern = malloc(sizeof(CGFloat) * lineDashCount); + CGFloat lineDashPhase = 0; + [self getLineDash:lineDashPattern count:NULL phase:&lineDashPhase]; + [copy setLineDash:lineDashPattern count:lineDashCount phase:lineDashPhase]; + free(lineDashPattern); + } + + return copy; } + (UIBezierPath *)bezierPathWithCGPath:(CGPathRef)CGPath @@ -61,14 +89,14 @@ + (UIBezierPath *)bezierPathWithCGPath:(CGPathRef)CGPath NSAssert(CGPath != NULL, @"CGPath must not be NULL"); UIBezierPath *bezierPath = [[self alloc] init]; bezierPath.CGPath = CGPath; - return [bezierPath autorelease]; + return bezierPath; } + (UIBezierPath *)bezierPath { UIBezierPath *bezierPath = [[self alloc] init]; bezierPath->_path = CGPathCreateMutable(); - return [bezierPath autorelease]; + return bezierPath; } + (UIBezierPath *)bezierPathWithRect:(CGRect)rect @@ -78,7 +106,7 @@ + (UIBezierPath *)bezierPathWithRect:(CGRect)rect UIBezierPath *bezierPath = [[self alloc] init]; bezierPath->_path = path; - return [bezierPath autorelease]; + return bezierPath; } + (UIBezierPath *)bezierPathWithOvalInRect:(CGRect)rect @@ -88,7 +116,7 @@ + (UIBezierPath *)bezierPathWithOvalInRect:(CGRect)rect UIBezierPath *bezierPath = [[self alloc] init]; bezierPath->_path = path; - return [bezierPath autorelease]; + return bezierPath; } + (UIBezierPath *)bezierPathWithRoundedRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius @@ -143,7 +171,7 @@ + (UIBezierPath *)bezierPathWithRoundedRect:(CGRect)rect byRoundingCorners:(UIRe UIBezierPath *bezierPath = [[self alloc] init]; bezierPath->_path = path; - return [bezierPath autorelease]; + return bezierPath; } + (UIBezierPath *)bezierPathWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise @@ -153,7 +181,7 @@ + (UIBezierPath *)bezierPathWithArcCenter:(CGPoint)center radius:(CGFloat)radius UIBezierPath *bezierPath = [[self alloc] init]; bezierPath->_path = path; - return [bezierPath autorelease]; + return bezierPath; } - (void)moveToPoint:(CGPoint)point diff --git a/UIKit/Classes/UIButton.h b/UIKit/Classes/UIButton.h index d9ecdc3e..27fe1a62 100644 --- a/UIKit/Classes/UIButton.h +++ b/UIKit/Classes/UIButton.h @@ -29,36 +29,21 @@ #import "UIControl.h" -typedef enum { +typedef NS_ENUM(NSInteger, UIButtonType) { UIButtonTypeCustom = 0, UIButtonTypeRoundedRect, UIButtonTypeDetailDisclosure, UIButtonTypeInfoLight, UIButtonTypeInfoDark, UIButtonTypeContactAdd, -} UIButtonType; +}; @class UILabel, UIImageView, UIImage; @interface UIButton : UIControl { -@protected +@package UIButtonType _buttonType; -@private - UILabel *_titleLabel; - UIImageView *_imageView; - UIImageView *_backgroundImageView; - BOOL _reversesTitleShadowWhenHighlighted; - BOOL _adjustsImageWhenHighlighted; - BOOL _adjustsImageWhenDisabled; - BOOL _showsTouchWhenHighlighted; - UIEdgeInsets _contentEdgeInsets; - UIEdgeInsets _titleEdgeInsets; - UIEdgeInsets _imageEdgeInsets; - NSMutableDictionary *_content; - UIImage *_adjustedHighlightImage; - UIImage *_adjustedDisabledImage; } - + (id)buttonWithType:(UIButtonType)buttonType; - (void)setTitle:(NSString *)title forState:(UIControlState)state; @@ -79,8 +64,8 @@ typedef enum { - (CGRect)imageRectForContentRect:(CGRect)contentRect; @property (nonatomic, readonly) UIButtonType buttonType; -@property (nonatomic,readonly,retain) UILabel *titleLabel; -@property (nonatomic,readonly,retain) UIImageView *imageView; +@property (nonatomic,readonly,strong) UILabel *titleLabel; +@property (nonatomic,readonly,strong) UIImageView *imageView; @property (nonatomic) BOOL reversesTitleShadowWhenHighlighted; @property (nonatomic) BOOL adjustsImageWhenHighlighted; @property (nonatomic) BOOL adjustsImageWhenDisabled; @@ -89,11 +74,9 @@ typedef enum { @property (nonatomic) UIEdgeInsets titleEdgeInsets; @property (nonatomic) UIEdgeInsets imageEdgeInsets; -@property (nonatomic, readonly, retain) NSString *currentTitle; -@property (nonatomic, readonly, retain) UIColor *currentTitleColor; -@property (nonatomic, readonly, retain) UIColor *currentTitleShadowColor; -@property (nonatomic, readonly, retain) UIImage *currentImage; -@property (nonatomic, readonly, retain) UIImage *currentBackgroundImage; - - +@property (nonatomic, readonly, strong) NSString *currentTitle; +@property (nonatomic, readonly, strong) UIColor *currentTitleColor; +@property (nonatomic, readonly, strong) UIColor *currentTitleShadowColor; +@property (nonatomic, readonly, strong) UIImage *currentImage; +@property (nonatomic, readonly, strong) UIImage *currentBackgroundImage; @end diff --git a/UIKit/Classes/UIButton.m b/UIKit/Classes/UIButton.m index 9cbb4892..707d83e8 100644 --- a/UIKit/Classes/UIButton.m +++ b/UIKit/Classes/UIButton.m @@ -41,11 +41,12 @@ static NSString *UIButtonContentTypeBackgroundImage = @"UIButtonContentTypeBackgroundImage"; static NSString *UIButtonContentTypeImage = @"UIButtonContentTypeImage"; -@implementation UIButton -@synthesize buttonType=_buttonType, titleLabel=_titleLabel, reversesTitleShadowWhenHighlighted=_reversesTitleShadowWhenHighlighted; -@synthesize adjustsImageWhenHighlighted=_adjustsImageWhenHighlighted, adjustsImageWhenDisabled=_adjustsImageWhenDisabled; -@synthesize showsTouchWhenHighlighted=_showsTouchWhenHighlighted, imageView=_imageView, contentEdgeInsets=_contentEdgeInsets; -@synthesize titleEdgeInsets=_titleEdgeInsets, imageEdgeInsets=_imageEdgeInsets; +@implementation UIButton { + UIImageView *_backgroundImageView; + NSMutableDictionary *_content; + UIImage *_adjustedHighlightImage; + UIImage *_adjustedDisabledImage; +} + (id)buttonWithType:(UIButtonType)buttonType { @@ -55,11 +56,11 @@ + (id)buttonWithType:(UIButtonType)buttonType case UIButtonTypeInfoLight: case UIButtonTypeInfoDark: case UIButtonTypeContactAdd: - return [[[UIRoundedRectButton alloc] init] autorelease]; + return [[UIRoundedRectButton alloc] init]; case UIButtonTypeCustom: default: - return [[[self alloc] init] autorelease]; + return [[self alloc] init]; } } @@ -87,16 +88,6 @@ - (id)initWithFrame:(CGRect)frame return self; } -- (void)dealloc -{ - [_content release]; - [_titleLabel release]; - [_imageView release]; - [_backgroundImageView release]; - [_adjustedHighlightImage release]; - [_adjustedDisabledImage release]; - [super dealloc]; -} - (NSString *)currentTitle { @@ -190,7 +181,7 @@ - (void)_setContent:(id)value forState:(UIControlState)state type:(NSString *)ty NSMutableDictionary *typeContent = [_content objectForKey:type]; if (!typeContent) { - typeContent = [[[NSMutableDictionary alloc] init] autorelease]; + typeContent = [[NSMutableDictionary alloc] init]; [_content setObject:typeContent forKey:type]; } @@ -226,8 +217,6 @@ - (void)setBackgroundImage:(UIImage *)image forState:(UIControlState)state - (void)setImage:(UIImage *)image forState:(UIControlState)state { - [_adjustedHighlightImage release]; - [_adjustedDisabledImage release]; _adjustedDisabledImage = _adjustedHighlightImage = nil; [self _setContent:image forState:state type:UIButtonContentTypeImage]; } diff --git a/UIKit/Classes/UIColor.h b/UIKit/Classes/UIColor.h index a3a9d51f..2d5ae67b 100644 --- a/UIKit/Classes/UIColor.h +++ b/UIKit/Classes/UIColor.h @@ -31,11 +31,7 @@ @class UIImage; -@interface UIColor : NSObject { -@private - id _representations; -} - +@interface UIColor : NSObject + (UIColor *)colorWithWhite:(CGFloat)white alpha:(CGFloat)alpha; + (UIColor *)colorWithHue:(CGFloat)hue saturation:(CGFloat)saturation brightness:(CGFloat)brightness alpha:(CGFloat)alpha; + (UIColor *)colorWithRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha; @@ -58,6 +54,9 @@ + (UIColor *)brownColor; + (UIColor *)clearColor; ++ (UIColor *)lightTextColor; ++ (UIColor *)darkTextColor; + - (id)initWithWhite:(CGFloat)white alpha:(CGFloat)alpha; - (id)initWithHue:(CGFloat)hue saturation:(CGFloat)saturation brightness:(CGFloat)brightness alpha:(CGFloat)alpha; - (id)initWithRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha; @@ -71,5 +70,4 @@ - (void)setStroke; @property (nonatomic, readonly) CGColorRef CGColor; - @end diff --git a/UIKit/Classes/UIColor.m b/UIKit/Classes/UIColor.m index 7dea338a..4e371402 100644 --- a/UIKit/Classes/UIColor.m +++ b/UIKit/Classes/UIColor.m @@ -49,13 +49,15 @@ static UIColor *PurpleColor = nil; static UIColor *BrownColor = nil; static UIColor *ClearColor = nil; +static UIColor *LightTextColor = nil; -@implementation UIColor +@implementation UIColor { + NSArray *_representations; +} - (id)initWithNSColor:(NSColor *)aColor { if (!aColor) { - [self release]; self = nil; } else { NSColor *c = [aColor colorUsingColorSpace:[NSColorSpace deviceRGBColorSpace]]; @@ -68,40 +70,35 @@ - (id)initWithNSColor:(NSColor *)aColor return self; } -- (void)dealloc -{ - [_representations release]; - [super dealloc]; -} + (id)colorWithNSColor:(NSColor *)c { - return [[[self alloc] initWithNSColor:c] autorelease]; + return [[self alloc] initWithNSColor:c]; } + (UIColor *)colorWithWhite:(CGFloat)white alpha:(CGFloat)alpha { - return [[[self alloc] initWithWhite:white alpha:alpha] autorelease]; + return [[self alloc] initWithWhite:white alpha:alpha]; } + (UIColor *)colorWithHue:(CGFloat)hue saturation:(CGFloat)saturation brightness:(CGFloat)brightness alpha:(CGFloat)alpha { - return [[[self alloc] initWithHue:hue saturation:saturation brightness:brightness alpha:alpha] autorelease]; + return [[self alloc] initWithHue:hue saturation:saturation brightness:brightness alpha:alpha]; } + (UIColor *)colorWithRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha { - return [[[self alloc] initWithRed:red green:green blue:blue alpha:alpha] autorelease]; + return [[self alloc] initWithRed:red green:green blue:blue alpha:alpha]; } + (UIColor *)colorWithCGColor:(CGColorRef)ref { - return [[[self alloc] initWithCGColor:ref] autorelease]; + return [[self alloc] initWithCGColor:ref]; } + (UIColor *)colorWithPatternImage:(UIImage *)patternImage { - return [[[self alloc] initWithPatternImage:patternImage] autorelease]; + return [[self alloc] initWithPatternImage:patternImage]; } + (UIColor *)blackColor { return BlackColor ?: (BlackColor = [[self alloc] initWithNSColor:[NSColor blackColor]]); } @@ -119,6 +116,8 @@ + (UIColor *)orangeColor { return OrangeColor ?: (OrangeColor = [[self alloc] i + (UIColor *)purpleColor { return PurpleColor ?: (PurpleColor = [[self alloc] initWithNSColor:[NSColor purpleColor]]); } + (UIColor *)brownColor { return BrownColor ?: (BrownColor = [[self alloc] initWithNSColor:[NSColor brownColor]]); } + (UIColor *)clearColor { return ClearColor ?: (ClearColor = [[self alloc] initWithNSColor:[NSColor clearColor]]); } ++ (UIColor *)lightTextColor { return LightTextColor ?: (LightTextColor = [[self alloc] initWithWhite:1 alpha:0.6]); } ++ (UIColor *)darkTextColor { return [self blackColor]; } - (id)initWithWhite:(CGFloat)white alpha:(CGFloat)alpha { @@ -138,7 +137,6 @@ - (id)initWithRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CG - (id)_initWithRepresentations:(NSArray *)reps { if ([reps count] == 0) { - [self release]; self = nil; } else if ((self=[super init])) { _representations = [reps copy]; @@ -148,7 +146,7 @@ - (id)_initWithRepresentations:(NSArray *)reps - (id)initWithCGColor:(CGColorRef)ref { - return [self _initWithRepresentations:[NSArray arrayWithObjects:[[[UIColorRep alloc] initWithCGColor:ref] autorelease], nil]]; + return [self _initWithRepresentations:[NSArray arrayWithObjects:[[UIColorRep alloc] initWithCGColor:ref], nil]]; } - (id)initWithPatternImage:(UIImage *)patternImage @@ -157,7 +155,7 @@ - (id)initWithPatternImage:(UIImage *)patternImage NSMutableArray *colorReps = [NSMutableArray arrayWithCapacity:[imageReps count]]; for (UIImageRep *imageRep in imageReps) { - [colorReps addObject:[[[UIColorRep alloc] initWithPatternImageRepresentation:imageRep] autorelease]]; + [colorReps addObject:[[UIColorRep alloc] initWithPatternImageRepresentation:imageRep]]; } return [self _initWithRepresentations:colorReps]; @@ -227,7 +225,6 @@ - (NSColor *)NSColor const NSInteger numberOfComponents = CGColorGetNumberOfComponents(color); const CGFloat *components = CGColorGetComponents(color); NSColor *theColor = [NSColor colorWithColorSpace:colorSpace components:components count:numberOfComponents]; - [colorSpace release]; return theColor; } @@ -239,7 +236,7 @@ - (NSString *)description // Apple doesn't actually define UIDeviceRGBColorSpace or any of the other responses anywhere public, // so there isn't any easy way to emulate it. CGColorSpaceRef colorSpaceRef = CGColorGetColorSpace(self.CGColor); - NSString *colorSpace = [NSString stringWithFormat:@"%@", [(NSString *)CGColorSpaceCopyName(colorSpaceRef) autorelease]]; + NSString *colorSpace = [NSString stringWithFormat:@"%@", (NSString *)CFBridgingRelease(CGColorSpaceCopyName(colorSpaceRef))]; const size_t numberOfComponents = CGColorGetNumberOfComponents(self.CGColor); const CGFloat *components = CGColorGetComponents(self.CGColor); diff --git a/UIKit/Classes/UIColorRep.h b/UIKit/Classes/UIColorRep.h index 9251c70c..205b4f91 100644 --- a/UIKit/Classes/UIColorRep.h +++ b/UIKit/Classes/UIColorRep.h @@ -31,10 +31,7 @@ @class UIImageRep; -@interface UIColorRep : NSObject { - CGColorRef _CGColor; - UIImageRep *_patternImageRep; -} +@interface UIColorRep : NSObject - (id)initWithPatternImageRepresentation:(UIImageRep *)patternImageRep; - (id)initWithCGColor:(CGColorRef)color; diff --git a/UIKit/Classes/UIColorRep.m b/UIKit/Classes/UIColorRep.m index 6d0d4b9b..80d9dd21 100644 --- a/UIKit/Classes/UIColorRep.m +++ b/UIKit/Classes/UIColorRep.m @@ -35,7 +35,7 @@ static void drawPatternImage(void *info, CGContextRef ctx) { - UIImageRep *rep = [(UIColorRep *)info patternImageRep]; + UIImageRep *rep = [(__bridge UIColorRep *)info patternImageRep]; UIGraphicsPushContext(ctx); CGContextSaveGState(ctx); @@ -63,16 +63,16 @@ static void drawPatternImage(void *info, CGContextRef ctx) UIGraphicsPopContext(); } -@implementation UIColorRep -@synthesize patternImageRep = _patternImageRep; +@implementation UIColorRep { + CGColorRef _CGColor; +} - (id)initWithPatternImageRepresentation:(UIImageRep *)patternImageRep { if (!patternImageRep) { - [self release]; self = nil; } else if ((self=[super init])) { - _patternImageRep = [patternImageRep retain]; + _patternImageRep = patternImageRep; } return self; } @@ -80,7 +80,6 @@ - (id)initWithPatternImageRepresentation:(UIImageRep *)patternImageRep - (id)initWithCGColor:(CGColorRef)color { if (!color) { - [self release]; self = nil; } else if ((self=[super init])) { _CGColor = CGColorRetain(color); @@ -90,9 +89,7 @@ - (id)initWithCGColor:(CGColorRef)color - (void)dealloc { - [_patternImageRep release]; CGColorRelease(_CGColor); - [super dealloc]; } - (CGColorRef)CGColor @@ -104,7 +101,7 @@ - (CGColorRef)CGColor const CGAffineTransform t = CGAffineTransformMakeScale(scaler, scaler); static const CGPatternCallbacks callbacks = {0, &drawPatternImage, NULL}; - CGPatternRef pattern = CGPatternCreate ((void *)self, + CGPatternRef pattern = CGPatternCreate ((__bridge void *)self, CGRectMake (0, 0, imageSize.width, imageSize.height), t, imageSize.width, diff --git a/UIKit/Classes/UIControl.h b/UIKit/Classes/UIControl.h index eed037b7..eb4eb52b 100644 --- a/UIKit/Classes/UIControl.h +++ b/UIKit/Classes/UIControl.h @@ -29,7 +29,7 @@ #import "UIView.h" -enum { +typedef NS_OPTIONS(NSUInteger, UIControlEvents) { UIControlEventTouchDown = 1 << 0, UIControlEventTouchDownRepeat = 1 << 1, UIControlEventTouchDragInside = 1 << 2, @@ -54,9 +54,7 @@ enum { UIControlEventAllEvents = 0xFFFFFFFF }; -typedef NSUInteger UIControlEvents; - -enum { +typedef NS_OPTIONS(NSUInteger, UIControlState) { UIControlStateNormal = 0, UIControlStateHighlighted = 1 << 0, UIControlStateDisabled = 1 << 1, @@ -65,34 +63,23 @@ enum { UIControlStateReserved = 0xFF000000 }; -typedef NSUInteger UIControlState; - -typedef enum { +typedef NS_ENUM(NSInteger, UIControlContentHorizontalAlignment) { UIControlContentHorizontalAlignmentCenter = 0, UIControlContentHorizontalAlignmentLeft = 1, UIControlContentHorizontalAlignmentRight = 2, UIControlContentHorizontalAlignmentFill = 3, -} UIControlContentHorizontalAlignment; +}; -typedef enum { +typedef NS_ENUM(NSInteger, UIControlContentVerticalAlignment) { UIControlContentVerticalAlignmentCenter = 0, UIControlContentVerticalAlignmentTop = 1, UIControlContentVerticalAlignmentBottom = 2, UIControlContentVerticalAlignmentFill = 3, -} UIControlContentVerticalAlignment; +}; -@interface UIControl : UIView { -@protected - NSMutableArray *_registeredActions; - BOOL _tracking; - BOOL _touchInside; - BOOL _enabled; - BOOL _selected; - BOOL _highlighted; - UIControlContentHorizontalAlignment _contentHorizontalAlignment; - UIControlContentVerticalAlignment _contentVerticalAlignment; -} +@class UITouch; +@interface UIControl : UIView - (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents; - (void)removeTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents; - (NSArray *)actionsForTarget:(id)target forControlEvent:(UIControlEvents)controlEvent; @@ -117,5 +104,4 @@ typedef enum { @property (nonatomic) UIControlContentHorizontalAlignment contentHorizontalAlignment; @property (nonatomic) UIControlContentVerticalAlignment contentVerticalAlignment; - @end diff --git a/UIKit/Classes/UIControl.m b/UIKit/Classes/UIControl.m index 02431f6a..0a10dfbe 100644 --- a/UIKit/Classes/UIControl.m +++ b/UIKit/Classes/UIControl.m @@ -33,9 +33,9 @@ #import "UIApplication.h" #import "UIControlAction.h" -@implementation UIControl -@synthesize tracking=_tracking, touchInside=_touchInside, selected=_selected, enabled=_enabled, highlighted=_highlighted; -@synthesize contentHorizontalAlignment=_contentHorizontalAlignment, contentVerticalAlignment=_contentVerticalAlignment; +@implementation UIControl { + NSMutableArray *_registeredActions; +} - (id)initWithFrame:(CGRect)frame { @@ -48,11 +48,6 @@ - (id)initWithFrame:(CGRect)frame return self; } -- (void)dealloc -{ - [_registeredActions release]; - [super dealloc]; -} - (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents { @@ -61,7 +56,6 @@ - (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvent controlAction.action = action; controlAction.controlEvents = controlEvents; [_registeredActions addObject:controlAction]; - [controlAction release]; } - (void)removeTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents @@ -75,7 +69,6 @@ - (void)removeTarget:(id)target action:(SEL)action forControlEvents:(UIControlEv } [_registeredActions removeObjectsInArray:discard]; - [discard release]; } - (NSArray *)actionsForTarget:(id)target forControlEvent:(UIControlEvents)controlEvent @@ -89,10 +82,9 @@ - (NSArray *)actionsForTarget:(id)target forControlEvent:(UIControlEvents)contro } if ([actions count] == 0) { - [actions release]; return nil; } else { - return [actions autorelease]; + return actions; } } diff --git a/UIKit/Classes/UIControlAction.h b/UIKit/Classes/UIControlAction.h index 207ec53e..4358720d 100644 --- a/UIKit/Classes/UIControlAction.h +++ b/UIKit/Classes/UIControlAction.h @@ -30,10 +30,6 @@ #import "UIAction.h" #import "UIControl.h" -@interface UIControlAction : UIAction { - UIControlEvents _controlEvents; -} - +@interface UIControlAction : UIAction @property (nonatomic, assign) UIControlEvents controlEvents; - @end diff --git a/UIKit/Classes/UIControlAction.m b/UIKit/Classes/UIControlAction.m index a8e445fb..bcb514a6 100644 --- a/UIKit/Classes/UIControlAction.m +++ b/UIKit/Classes/UIControlAction.m @@ -30,6 +30,4 @@ #import "UIControlAction.h" @implementation UIControlAction -@synthesize controlEvents=_controlEvents; - @end diff --git a/UIKit/Classes/UICustomNSClipView.h b/UIKit/Classes/UICustomNSClipView.h index 56b2175b..1b09df4f 100644 --- a/UIKit/Classes/UICustomNSClipView.h +++ b/UIKit/Classes/UICustomNSClipView.h @@ -40,18 +40,13 @@ - (BOOL)clipViewShouldScroll; @end -@interface UICustomNSClipView : NSClipView { - CALayer *parentLayer; - id behaviorDelegate; -} - +@interface UICustomNSClipView : NSClipView - (id)initWithFrame:(NSRect)frame; // A layer parent is just a layer that UICustonNSClipView will attempt to always remain a sublayer of. // Circumventing AppKit for fun and profit! // The hitDelegate is for faking out the NSView's usual hitTest: checks to handle cases where UIViews are above // the UIView that's displaying this layer. -@property (nonatomic, assign) CALayer *parentLayer; +@property (nonatomic, weak) CALayer *parentLayer; @property (nonatomic, assign) id behaviorDelegate; - @end diff --git a/UIKit/Classes/UICustomNSClipView.m b/UIKit/Classes/UICustomNSClipView.m index e18137d0..f879504f 100644 --- a/UIKit/Classes/UICustomNSClipView.m +++ b/UIKit/Classes/UICustomNSClipView.m @@ -33,7 +33,6 @@ #import @implementation UICustomNSClipView -@synthesize parentLayer, behaviorDelegate; - (id)initWithFrame:(NSRect)frame { @@ -46,7 +45,7 @@ - (id)initWithFrame:(NSRect)frame - (void)scrollWheel:(NSEvent *)event { - if ([behaviorDelegate clipViewShouldScroll]) { + if ([self.behaviorDelegate clipViewShouldScroll]) { NSPoint offset = [self bounds].origin; offset.x += [event deltaX]; offset.y -= [event deltaY]; @@ -60,19 +59,18 @@ - (void)scrollWheel:(NSEvent *)event - (void)fixupTheLayer { - if ([self superview] && parentLayer) { + if ([self superview] && self.parentLayer) { [CATransaction begin]; - [CATransaction setValue:(id)kCFBooleanTrue - forKey:kCATransactionDisableActions]; + [CATransaction setAnimationDuration:0]; CALayer *layer = [self layer]; - if (parentLayer != layer.superlayer) { - [parentLayer addSublayer:layer]; + if (self.parentLayer != layer.superlayer) { + [self.parentLayer addSublayer:layer]; } - if (!CGRectEqualToRect(layer.frame, parentLayer.bounds)) { - layer.frame = parentLayer.bounds; + if (!CGRectEqualToRect(layer.frame, self.parentLayer.bounds)) { + layer.frame = self.parentLayer.bounds; } [CATransaction commit]; @@ -107,12 +105,12 @@ - (NSView *)hitTest:(NSPoint)aPoint { NSView *hit = [super hitTest:aPoint]; - if (hit && behaviorDelegate) { + if (hit && self.behaviorDelegate) { // call out to the text layer via a delegate or something and ask if this point should be considered a hit or not. // if not, then we set hit to nil, otherwise we return it like normal. // the purpose of this is to make the NSView act invisible/hidden to clicks when it's visually behind other UIViews. // super tricky, eh? - if (![behaviorDelegate hitTestForClipViewPoint:aPoint]) { + if (![self.behaviorDelegate hitTestForClipViewPoint:aPoint]) { hit = nil; } } diff --git a/UIKit/Classes/UICustomNSTextView.h b/UIKit/Classes/UICustomNSTextView.h index d8f6b749..76700fd7 100644 --- a/UIKit/Classes/UICustomNSTextView.h +++ b/UIKit/Classes/UICustomNSTextView.h @@ -37,10 +37,7 @@ - (BOOL)textView:(UICustomNSTextView *)textView shouldAcceptKeyDown:(NSEvent *)event; @end -@interface UICustomNSTextView: NSTextView { - BOOL secureTextEntry; - BOOL isBecomingFirstResponder; -} +@interface UICustomNSTextView: NSTextView - (id)initWithFrame:(NSRect)frame secureTextEntry:(BOOL)isSecure isField:(BOOL)isField; - (void)setSecureTextEntry:(BOOL)isSecure; diff --git a/UIKit/Classes/UICustomNSTextView.m b/UIKit/Classes/UICustomNSTextView.m index cc3165ba..8fef4c3b 100644 --- a/UIKit/Classes/UICustomNSTextView.m +++ b/UIKit/Classes/UICustomNSTextView.m @@ -44,7 +44,10 @@ @interface UICustomNSTextView () @end -@implementation UICustomNSTextView +@implementation UICustomNSTextView { + BOOL _secureTextEntry; + BOOL _isBecomingFirstResponder; +} - (id)initWithFrame:(NSRect)frame secureTextEntry:(BOOL)isSecure isField:(BOOL)isField { @@ -66,11 +69,13 @@ - (id)initWithFrame:(NSRect)frame secureTextEntry:(BOOL)isSecure isField:(BOOL)i [self setVerticallyResizable:NO]; [[self textContainer] setWidthTracksTextView:NO]; [[self textContainer] setContainerSize:maxSize]; + [self setTextContainerInset:NSMakeSize(0, 0)]; } else { [self setFieldEditor:NO]; [self setHorizontallyResizable:NO]; [self setVerticallyResizable:YES]; [self setAutoresizingMask:NSViewWidthSizable]; + [self setTextContainerInset:NSMakeSize(3, 8)]; } [self setMaxSize:maxSize]; @@ -81,7 +86,9 @@ - (id)initWithFrame:(NSRect)frame secureTextEntry:(BOOL)isSecure isField:(BOOL)i [self setAllowsImageEditing:NO]; [self setDisplaysLinkToolTips:NO]; [self setAutomaticDataDetectionEnabled:NO]; - [self setSecureTextEntry:isSecure]; + + // same color as iOS + [self setInsertionPointColor:[NSColor colorWithCalibratedRed:62/255.f green:100/255.f blue:243/255.f alpha:1]]; [self setLayerContentsPlacement:NSViewLayerContentsPlacementTopLeft]; @@ -96,7 +103,7 @@ - (void)updateStyles NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init]; [style setParagraphStyle:[NSParagraphStyle defaultParagraphStyle]]; - if (secureTextEntry) { + if (_secureTextEntry) { // being all super-paranoid here... [self setAutomaticQuoteSubstitutionEnabled:NO]; [self setGrammarCheckingEnabled:NO]; @@ -107,7 +114,7 @@ - (void)updateStyles [self setSmartInsertDeleteEnabled:NO]; [self setUsesFindPanel:NO]; [self setAllowsUndo:NO]; - [[self layoutManager] setGlyphGenerator:[[[UIBulletGlyphGenerator alloc] init] autorelease]]; + [[self layoutManager] setGlyphGenerator:[[UIBulletGlyphGenerator alloc] init]]; [style setLineBreakMode:NSLineBreakByCharWrapping]; } else { [self setAllowsUndo:YES]; @@ -122,18 +129,17 @@ - (void)updateStyles } [self setDefaultParagraphStyle:style]; - [style release]; } - (void)setSecureTextEntry:(BOOL)isSecure { - secureTextEntry = isSecure; + _secureTextEntry = isSecure; [self updateStyles]; } - (BOOL)validateMenuItem:(NSMenuItem *)menuItem { - if (secureTextEntry && ([menuItem action] == @selector(copy:) || [menuItem action] == @selector(cut:))) { + if (_secureTextEntry && ([menuItem action] == @selector(copy:) || [menuItem action] == @selector(cut:))) { return NO; // don't allow copying/cutting out from a secure field } else { return [super validateMenuItem:menuItem]; @@ -142,7 +148,7 @@ - (BOOL)validateMenuItem:(NSMenuItem *)menuItem - (NSSelectionGranularity)selectionGranularity { - if (secureTextEntry) { + if (_secureTextEntry) { return NSSelectByCharacter; // trying to avoid the secure one giving any hints about what's under it. :/ } else { return [super selectionGranularity]; @@ -152,14 +158,14 @@ - (NSSelectionGranularity)selectionGranularity - (void)startSpeaking:(id)sender { // only allow speaking if it's not secure - if (!secureTextEntry) { + if (!_secureTextEntry) { [super startSpeaking:sender]; } } - (id)validRequestorForSendType:(NSString *)sendType returnType:(NSString *)returnType { - if (secureTextEntry) { + if (_secureTextEntry) { return nil; } else { return [super validRequestorForSendType:sendType returnType:returnType]; @@ -173,8 +179,8 @@ - (NSMenu *)menuForEvent:(NSEvent *)theEvent // screw it.. why not just remove everything from the context menu if it's a secure field? :) // it's possible that various key combos could still allow things like searching in spotlight which // then would revel the actual value of the password field, but at least those are sorta obscure :) - if (secureTextEntry) { - NSArray *items = [[[menu itemArray] copy] autorelease]; + if (_secureTextEntry) { + NSArray *items = [[menu itemArray] copy]; for (NSMenuItem *item in items) { if ([item action] != @selector(paste:)) { [menu removeItem:item]; @@ -198,9 +204,9 @@ - (void)setDelegate:(id)d - (BOOL)becomeFirstResponder { - isBecomingFirstResponder = YES; + _isBecomingFirstResponder = YES; BOOL result = [[self delegate] textViewBecomeFirstResponder:self]; - isBecomingFirstResponder = NO; + _isBecomingFirstResponder = NO; return result; } @@ -211,7 +217,7 @@ - (BOOL)reallyBecomeFirstResponder - (BOOL)resignFirstResponder { - if(isBecomingFirstResponder) return NO; + if(_isBecomingFirstResponder) return NO; return [[self delegate] textViewResignFirstResponder:self]; } diff --git a/UIKit/Classes/UIDataDetectors.h b/UIKit/Classes/UIDataDetectors.h index 1e3f895d..8d15acef 100644 --- a/UIKit/Classes/UIDataDetectors.h +++ b/UIKit/Classes/UIDataDetectors.h @@ -29,11 +29,10 @@ #import -enum { +typedef NS_OPTIONS(NSUInteger, UIDataDetectorTypes) { UIDataDetectorTypePhoneNumber = 1 << 0, UIDataDetectorTypeLink = 1 << 1, UIDataDetectorTypeNone = 0, UIDataDetectorTypeAll = NSUIntegerMax }; -typedef NSUInteger UIDataDetectorTypes; diff --git a/UIKit/Classes/UIDatePicker.h b/UIKit/Classes/UIDatePicker.h index e6a3cfa7..e0f26d0f 100644 --- a/UIKit/Classes/UIDatePicker.h +++ b/UIKit/Classes/UIDatePicker.h @@ -31,39 +31,21 @@ #import #import "UIControl.h" -typedef enum { +typedef NS_ENUM(NSInteger, UIDatePickerMode) { UIDatePickerModeTime, UIDatePickerModeDate, UIDatePickerModeDateAndTime, UIDatePickerModeCountDownTimer -} UIDatePickerMode; +}; @interface UIDatePicker : UIControl -{ - @private - NSCalendar *_calendar; - NSDate *_date; - NSLocale *_locale; - NSTimeZone *_timeZone; - - UIDatePickerMode _datePickerMode; - - NSDate *_minimumDate; - NSDate *_maximumDate; - NSInteger _minuteInterval; - NSTimeInterval _countDownDuration; -} - -@property (nonatomic, retain) NSCalendar *calendar; -@property (nonatomic, retain) NSDate *date; -@property (nonatomic, retain) NSLocale *locale; -@property (nonatomic, retain) NSTimeZone *timeZone; - +@property (nonatomic, strong) NSCalendar *calendar; +@property (nonatomic, strong) NSDate *date; +@property (nonatomic, strong) NSLocale *locale; +@property (nonatomic, strong) NSTimeZone *timeZone; @property (nonatomic, assign) UIDatePickerMode datePickerMode; - -@property (nonatomic, retain) NSDate *minimumDate; -@property (nonatomic, retain) NSDate *maximumDate; +@property (nonatomic, strong) NSDate *minimumDate; +@property (nonatomic, strong) NSDate *maximumDate; @property (nonatomic, assign) NSInteger minuteInterval; @property (nonatomic, assign) NSTimeInterval countDownDuration; - @end diff --git a/UIKit/Classes/UIDatePicker.m b/UIKit/Classes/UIDatePicker.m index c8a12ef6..1f83f599 100644 --- a/UIKit/Classes/UIDatePicker.m +++ b/UIKit/Classes/UIDatePicker.m @@ -29,28 +29,5 @@ #import "UIDatePicker.h" - @implementation UIDatePicker - -@synthesize calendar = _calendar; -@synthesize date = _date; -@synthesize locale = _locale; -@synthesize timeZone = _timeZone; -@synthesize datePickerMode = _datePickerMode; -@synthesize minimumDate = _minimumDate; -@synthesize maximumDate = _maximumDate; -@synthesize minuteInterval = _minuteInterval; -@synthesize countDownDuration = _countDownDuration; - -- (void) dealloc -{ - [_calendar release]; - [_date release]; - [_locale release]; - [_timeZone release]; - [_minimumDate release]; - [_maximumDate release]; - [super dealloc]; -} - @end diff --git a/UIKit/Classes/UIDevice.h b/UIKit/Classes/UIDevice.h index c2ce9ea3..d1d035a2 100644 --- a/UIKit/Classes/UIDevice.h +++ b/UIKit/Classes/UIDevice.h @@ -31,7 +31,7 @@ extern NSString *const UIDeviceOrientationDidChangeNotification; -typedef enum { +typedef NS_ENUM(NSInteger, UIDeviceOrientation) { UIDeviceOrientationUnknown, UIDeviceOrientationPortrait, UIDeviceOrientationPortraitUpsideDown, @@ -39,13 +39,13 @@ typedef enum { UIDeviceOrientationLandscapeRight, UIDeviceOrientationFaceUp, UIDeviceOrientationFaceDown -} UIDeviceOrientation; +}; -typedef enum { +typedef NS_ENUM(NSInteger, UIUserInterfaceIdiom) { UIUserInterfaceIdiomPhone, UIUserInterfaceIdiomPad, UIUserInterfaceIdiomDesktop, -} UIUserInterfaceIdiom; +}; #define UI_USER_INTERFACE_IDIOM() \ ([[UIDevice currentDevice] respondsToSelector:@selector(userInterfaceIdiom)] ? \ @@ -60,21 +60,18 @@ typedef enum { ((orientation) == UIDeviceOrientationLandscapeLeft || \ (orientation) == UIDeviceOrientationLandscapeRight) -@interface UIDevice : NSObject { -} - +@interface UIDevice : NSObject + (UIDevice *)currentDevice; -@property (nonatomic, readonly, retain) NSString *name; -@property (nonatomic, readonly) UIUserInterfaceIdiom userInterfaceIdiom; // always returns UIUserInterfaceIdiomDesktop -@property (nonatomic, readonly) UIDeviceOrientation orientation; // always returns UIDeviceOrientationPortrait -@property (nonatomic, readonly,getter=isMultitaskingSupported) BOOL multitaskingSupported; // always returns YES -@property (nonatomic, readonly, retain) NSString *systemName; -@property (nonatomic, readonly, retain) NSString *systemVersion; -@property (nonatomic, readonly, retain) NSString *model; -@property (nonatomic, readonly, getter=isGeneratingDeviceOrientationNotifications) BOOL generatesDeviceOrientationNotifications; // aways returns NO - - (void)beginGeneratingDeviceOrientationNotifications; // no effect - (void)endGeneratingDeviceOrientationNotifications; // no effect +@property (nonatomic, readonly, strong) NSString *name; +@property (nonatomic, assign) UIUserInterfaceIdiom userInterfaceIdiom; // default is UIUserInterfaceIdiomDesktop (obviously real UIKit doesn't allow setting this!) +@property (nonatomic, readonly) UIDeviceOrientation orientation; // always returns UIDeviceOrientationPortrait +@property (nonatomic, readonly,getter=isMultitaskingSupported) BOOL multitaskingSupported; // always returns YES +@property (nonatomic, readonly, strong) NSString *systemName; +@property (nonatomic, readonly, strong) NSString *systemVersion; +@property (nonatomic, readonly, strong) NSString *model; +@property (nonatomic, readonly, getter=isGeneratingDeviceOrientationNotifications) BOOL generatesDeviceOrientationNotifications; // aways returns NO @end diff --git a/UIKit/Classes/UIDevice.m b/UIKit/Classes/UIDevice.m index a5622709..76e0db75 100644 --- a/UIKit/Classes/UIDevice.m +++ b/UIKit/Classes/UIDevice.m @@ -49,14 +49,17 @@ + (UIDevice *)currentDevice return theDevice; } -- (UIUserInterfaceIdiom)userInterfaceIdiom +- (id)init { - return UIUserInterfaceIdiomDesktop; + if ((self=[super init])) { + _userInterfaceIdiom = UIUserInterfaceIdiomDesktop; + } + return self; } - (NSString *)name { - return [(__bridge NSString *)SCDynamicStoreCopyComputerName(NULL,NULL) autorelease]; + return (__bridge_transfer NSString *)SCDynamicStoreCopyComputerName(NULL,NULL); } - (UIDeviceOrientation)orientation diff --git a/UIKit/Classes/UIEvent.h b/UIKit/Classes/UIEvent.h index 97665912..8a2fb180 100644 --- a/UIKit/Classes/UIEvent.h +++ b/UIKit/Classes/UIEvent.h @@ -29,35 +29,29 @@ #import -typedef enum { +typedef NS_ENUM(NSInteger, UIEventType) { UIEventTypeTouches, UIEventTypeMotion, - UIEventTypeKeyPress // AppKitIntegration -} UIEventType; + + // nonstandard + UIEventTypeKeyboard, + UIEventTypeAction +}; -typedef enum { +typedef NS_ENUM(NSInteger, UIEventSubtype) { UIEventSubtypeNone = 0, UIEventSubtypeMotionShake = 1, -} UIEventSubtype; +}; -@class UITouch, UIWindow, UIView, UIGestureRecognizer; - -@interface UIEvent : NSObject { -@private - UIEventType _type; - UITouch *_touch; - NSTimeInterval _timestamp; - BOOL _unhandledKeyPressEvent; -} - -@property (nonatomic, readonly) NSTimeInterval timestamp; +@class UIWindow, UIView, UIGestureRecognizer; +@interface UIEvent : NSObject - (NSSet *)allTouches; - (NSSet *)touchesForView:(UIView *)view; - (NSSet *)touchesForWindow:(UIWindow *)window; - (NSSet *)touchesForGestureRecognizer:(UIGestureRecognizer *)gesture; +@property (nonatomic, readonly) NSTimeInterval timestamp; @property (nonatomic, readonly) UIEventType type; @property (nonatomic, readonly) UIEventSubtype subtype; - @end diff --git a/UIKit/Classes/UIEvent.m b/UIKit/Classes/UIEvent.m index cc2546e2..427b61aa 100644 --- a/UIKit/Classes/UIEvent.m +++ b/UIKit/Classes/UIEvent.m @@ -27,55 +27,22 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#import "UIEvent+UIPrivate.h" +#import "UIEvent.h" #import "UITouch.h" @implementation UIEvent -@synthesize timestamp=_timestamp, type=_type; -- (id)initWithEventType:(UIEventType)type +- (id)init { if ((self=[super init])) { - _type = type; - _unhandledKeyPressEvent = NO; + _timestamp = [NSDate timeIntervalSinceReferenceDate]; } return self; } -- (void)dealloc -{ - [_touch release]; - [super dealloc]; -} - -- (void)_setTouch:(UITouch *)t -{ - if (_touch != t) { - [_touch release]; - _touch = [t retain]; - } -} - -- (void)_setTimestamp:(NSTimeInterval)timestamp -{ - _timestamp = timestamp; -} - -// this is stupid hack so that keyboard events can fall to AppKit's next responder if nothing within UIKit handles it -// I couldn't come up with a better way at the time. meh. -- (void)_setUnhandledKeyPressEvent -{ - _unhandledKeyPressEvent = YES; -} - -- (BOOL)_isUnhandledKeyPressEvent -{ - return _unhandledKeyPressEvent; -} - - (NSSet *)allTouches { - return [NSSet setWithObject:_touch]; + return nil; } - (NSSet *)touchesForView:(UIView *)view @@ -111,6 +78,11 @@ - (NSSet *)touchesForGestureRecognizer:(UIGestureRecognizer *)gesture return touches; } +- (UIEventType)type +{ + return -1; +} + - (UIEventSubtype)subtype { return UIEventSubtypeNone; diff --git a/UIKit/Classes/UIFont.h b/UIKit/Classes/UIFont.h index 80d6ee9a..43393ed5 100644 --- a/UIKit/Classes/UIFont.h +++ b/UIKit/Classes/UIFont.h @@ -43,14 +43,12 @@ - (UIFont *)fontWithSize:(CGFloat)fontSize; -@property (nonatomic, readonly, retain) NSString *fontName; - +@property (nonatomic, readonly, strong) NSString *fontName; @property (nonatomic, readonly) CGFloat ascender; @property (nonatomic, readonly) CGFloat descender; @property (nonatomic, readonly) CGFloat lineHeight; @property (nonatomic, readonly) CGFloat pointSize; @property (nonatomic, readonly) CGFloat xHeight; @property (nonatomic, readonly) CGFloat capHeight; -@property (nonatomic, readonly, retain) NSString *familyName; - +@property (nonatomic, readonly, strong) NSString *familyName; @end diff --git a/UIKit/Classes/UIFont.m b/UIKit/Classes/UIFont.m index dcbab16e..a7628bf5 100644 --- a/UIKit/Classes/UIFont.m +++ b/UIKit/Classes/UIFont.m @@ -37,13 +37,11 @@ @implementation UIFont + (void)setSystemFontName:(NSString *)aName { - [UIFontSystemFontName release]; UIFontSystemFontName = [aName copy]; } + (void)setBoldSystemFontName:(NSString *)aName { - [UIFontBoldSystemFontName release]; UIFontBoldSystemFontName = [aName copy]; } @@ -51,7 +49,7 @@ + (UIFont *)_fontWithCTFont:(CTFontRef)aFont { UIFont *theFont = [[UIFont alloc] init]; theFont->_font = CFRetain(aFont); - return [theFont autorelease]; + return theFont; } + (UIFont *)fontWithNSFont:(NSFont *)aFont @@ -140,12 +138,11 @@ + (UIFont *)boldSystemFontOfSize:(CGFloat)fontSize - (void)dealloc { if (_font) CFRelease(_font); - [super dealloc]; } - (NSString *)fontName { - return [(NSString *)CTFontCopyFullName(_font) autorelease]; + return (NSString *)CFBridgingRelease(CTFontCopyPostScriptName(_font)); } - (CGFloat)ascender @@ -184,14 +181,14 @@ - (CGFloat)lineHeight - (NSString *)familyName { - return [(NSString *)CTFontCopyFamilyName(_font) autorelease]; + return (NSString *)CFBridgingRelease(CTFontCopyFamilyName(_font)); } - (UIFont *)fontWithSize:(CGFloat)fontSize { CTFontRef newFont = CTFontCreateCopyWithAttributes(_font, fontSize, NULL, NULL); if (newFont) { - UIFont *theFont = [isa _fontWithCTFont:newFont]; + UIFont *theFont = [[self class] _fontWithCTFont:newFont]; CFRelease(newFont); return theFont; } else { diff --git a/UIKit/Classes/UIGestureRecognizer+UIPrivate.h b/UIKit/Classes/UIGestureRecognizer+UIPrivate.h index 3e2b5ff9..fb57e1d0 100644 --- a/UIKit/Classes/UIGestureRecognizer+UIPrivate.h +++ b/UIKit/Classes/UIGestureRecognizer+UIPrivate.h @@ -29,7 +29,13 @@ #import "UIGestureRecognizer.h" +@class UITouchEvent; + @interface UIGestureRecognizer (UIPrivate) - (void)_setView:(UIView *)v; -- (void)_recognizeTouches:(NSSet *)touches withEvent:(UIEvent *)event; +- (void)_abort; + +- (void)_beginTrackingTouch:(UITouch *)touch withEvent:(UITouchEvent *)event; +- (void)_continueTrackingWithEvent:(UITouchEvent *)event; +- (void)_endTrackingTouch:(UITouch *)touch withEvent:(UITouchEvent *)event; @end diff --git a/UIKit/Classes/UIGestureRecognizer.h b/UIKit/Classes/UIGestureRecognizer.h index 7dbf1f3d..84d49d6b 100644 --- a/UIKit/Classes/UIGestureRecognizer.h +++ b/UIKit/Classes/UIGestureRecognizer.h @@ -29,7 +29,7 @@ #import -typedef enum { +typedef NS_ENUM(NSInteger, UIGestureRecognizerState) { UIGestureRecognizerStatePossible, UIGestureRecognizerStateBegan, UIGestureRecognizerStateChanged, @@ -37,7 +37,7 @@ typedef enum { UIGestureRecognizerStateCancelled, UIGestureRecognizerStateFailed, UIGestureRecognizerStateRecognized = UIGestureRecognizerStateEnded -} UIGestureRecognizerState; +}; @class UIView, UIGestureRecognizer, UITouch, UIEvent; @@ -48,25 +48,7 @@ typedef enum { - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer; @end -@interface UIGestureRecognizer : NSObject { -@private - __unsafe_unretained id _delegate; - BOOL _delaysTouchesBegan; - BOOL _delaysTouchesEnded; - BOOL _cancelsTouchesInView; - BOOL _enabled; - UIGestureRecognizerState _state; - UIView *_view; - NSMutableArray *_registeredActions; - NSMutableArray *_trackingTouches; - - struct { - unsigned shouldBegin : 1; - unsigned shouldReceiveTouch : 1; - unsigned shouldRecognizeSimultaneouslyWithGestureRecognizer : 1; - } _delegateHas; -} - +@interface UIGestureRecognizer : NSObject - (id)initWithTarget:(id)target action:(SEL)action; - (void)addTarget:(id)target action:(SEL)action; @@ -84,5 +66,4 @@ typedef enum { @property (nonatomic, getter=isEnabled) BOOL enabled; @property (nonatomic, readonly) UIGestureRecognizerState state; @property (nonatomic, readonly) UIView *view; - @end diff --git a/UIKit/Classes/UIGestureRecognizer.m b/UIKit/Classes/UIGestureRecognizer.m index 37dc8f87..25a82102 100644 --- a/UIKit/Classes/UIGestureRecognizer.m +++ b/UIKit/Classes/UIGestureRecognizer.m @@ -32,10 +32,19 @@ #import "UITouch+UIPrivate.h" #import "UIAction.h" #import "UIApplication.h" +#import "UITouchEvent.h" -@implementation UIGestureRecognizer -@synthesize delegate=_delegate, delaysTouchesBegan=_delaysTouchesBegan, delaysTouchesEnded=_delaysTouchesEnded, cancelsTouchesInView=_cancelsTouchesInView; -@synthesize state=_state, enabled=_enabled, view=_view; +@implementation UIGestureRecognizer { + NSMutableArray *_registeredActions; + NSMutableArray *_trackingTouches; + __unsafe_unretained UIView *_view; + + struct { + unsigned shouldBegin : 1; + unsigned shouldReceiveTouch : 1; + unsigned shouldRecognizeSimultaneouslyWithGestureRecognizer : 1; + } _delegateHas; +} - (id)initWithTarget:(id)target action:(SEL)action { @@ -54,17 +63,12 @@ - (id)initWithTarget:(id)target action:(SEL)action return self; } -- (void)dealloc -{ - [_registeredActions release]; - [_trackingTouches release]; - [super dealloc]; -} - - (void)_setView:(UIView *)v { - [self reset]; // not sure about this, but it kinda makes sense - _view = v; + if (v != _view) { + [self reset]; // not sure about this, but I think it makes sense + _view = v; + } } - (void)setDelegate:(id)aDelegate @@ -86,7 +90,6 @@ - (void)addTarget:(id)target action:(SEL)action actionRecord.target = target; actionRecord.action = action; [_registeredActions addObject:actionRecord]; - [actionRecord release]; } - (void)removeTarget:(id)target action:(SEL)action @@ -95,7 +98,6 @@ - (void)removeTarget:(id)target action:(SEL)action actionRecord.target = target; actionRecord.action = action; [_registeredActions removeObject:actionRecord]; - [actionRecord release]; } - (void)requireGestureRecognizerToFail:(UIGestureRecognizer *)otherGestureRecognizer @@ -138,25 +140,31 @@ - (CGPoint)locationOfTouch:(NSUInteger)touchIndex inView:(UIView *)view - (void)setState:(UIGestureRecognizerState)state { + if (_delegateHas.shouldBegin && _state == UIGestureRecognizerStatePossible && (state == UIGestureRecognizerStateRecognized || state == UIGestureRecognizerStateBegan)) { + if (![_delegate gestureRecognizerShouldBegin:self]) { + state = UIGestureRecognizerStateFailed; + } + } + // the docs didn't say explicitly if these state transitions were verified, but I suspect they are. if anything, a check like this // should help debug things. it also helps me better understand the whole thing, so it's not a total waste of time :) - typedef struct { UIGestureRecognizerState fromState, toState; BOOL shouldNotify, shouldReset; } StateTransition; + typedef struct { UIGestureRecognizerState fromState, toState; BOOL shouldNotify; } StateTransition; #define NumberOfStateTransitions 9 static const StateTransition allowedTransitions[NumberOfStateTransitions] = { // discrete gestures - {UIGestureRecognizerStatePossible, UIGestureRecognizerStateRecognized, YES, YES}, - {UIGestureRecognizerStatePossible, UIGestureRecognizerStateFailed, NO, YES}, + {UIGestureRecognizerStatePossible, UIGestureRecognizerStateRecognized, YES}, + {UIGestureRecognizerStatePossible, UIGestureRecognizerStateFailed, NO}, // continuous gestures - {UIGestureRecognizerStatePossible, UIGestureRecognizerStateBegan, YES, NO }, - {UIGestureRecognizerStateBegan, UIGestureRecognizerStateChanged, YES, NO }, - {UIGestureRecognizerStateBegan, UIGestureRecognizerStateCancelled, YES, YES}, - {UIGestureRecognizerStateBegan, UIGestureRecognizerStateEnded, YES, YES}, - {UIGestureRecognizerStateChanged, UIGestureRecognizerStateChanged, YES, NO }, - {UIGestureRecognizerStateChanged, UIGestureRecognizerStateCancelled, YES, YES}, - {UIGestureRecognizerStateChanged, UIGestureRecognizerStateEnded, YES, YES} + {UIGestureRecognizerStatePossible, UIGestureRecognizerStateBegan, YES}, + {UIGestureRecognizerStateBegan, UIGestureRecognizerStateChanged, YES}, + {UIGestureRecognizerStateBegan, UIGestureRecognizerStateCancelled, YES}, + {UIGestureRecognizerStateBegan, UIGestureRecognizerStateEnded, YES}, + {UIGestureRecognizerStateChanged, UIGestureRecognizerStateChanged, YES}, + {UIGestureRecognizerStateChanged, UIGestureRecognizerStateCancelled, YES}, + {UIGestureRecognizerStateChanged, UIGestureRecognizerStateEnded, YES} }; const StateTransition *transition = NULL; @@ -168,7 +176,7 @@ - (void)setState:(UIGestureRecognizerState)state } } - NSAssert2((transition != NULL), @"invalid state transition from %d to %d", _state, state); + NSAssert2((transition != NULL), @"invalid state transition from %ld to %ld", _state, state); if (transition) { _state = transition->toState; @@ -178,22 +186,22 @@ - (void)setState:(UIGestureRecognizerState)state // docs mention that the action messages are sent on the next run loop, so we'll do that here. // note that this means that reset can't happen until the next run loop, either otherwise // the state property is going to be wrong when the action handler looks at it, so as a result - // I'm also delaying the reset call (if necessary) just below here. + // I'm also delaying the reset call (if necessary) below in -continueTrackingWithEvent: [actionRecord.target performSelector:actionRecord.action withObject:self afterDelay:0]; } } - - if (transition->shouldReset) { - // see note above about the delay - [self performSelector:@selector(reset) withObject:nil afterDelay:0]; - } } } - (void)reset { + // note - this is also supposed to ignore any currently tracked touches + // the touches themselves may not have gone away, so we don't just remove them from tracking, I think, + // but instead just mark them as ignored by this gesture until the touches eventually end themselves. + // in any case, this isn't implemented right now because we only have a single touch and so far I + // haven't needed it. + _state = UIGestureRecognizerStatePossible; - [_trackingTouches removeAllObjects]; } - (BOOL)canPreventGestureRecognizer:(UIGestureRecognizer *)preventedGestureRecognizer @@ -226,74 +234,72 @@ - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { } -- (void)_gesturesBegan:(NSSet *)touches withEvent:(UIEvent *)event -{ -} - -- (void)_gesturesMoved:(NSSet *)touches withEvent:(UIEvent *)event +- (void)_beginTrackingTouch:(UITouch *)touch withEvent:(UITouchEvent *)event { + if (self.enabled) { + if (!_delegateHas.shouldReceiveTouch || [_delegate gestureRecognizer:self shouldReceiveTouch:touch]) { + [touch _addGestureRecognizer:self]; + [_trackingTouches addObject:touch]; + } + } } -- (void)_gesturesEnded:(NSSet *)touches withEvent:(UIEvent *)event +- (void)_continueTrackingWithEvent:(UITouchEvent *)event { -} + NSMutableSet *began = [NSMutableSet new]; + NSMutableSet *moved = [NSMutableSet new]; + NSMutableSet *ended = [NSMutableSet new]; + NSMutableSet *cancelled = [NSMutableSet new]; + BOOL multitouchSequenceIsEnded = YES; + + for (UITouch *touch in _trackingTouches) { + if (touch.phase == UITouchPhaseBegan) { + multitouchSequenceIsEnded = NO; + [began addObject:touch]; + } else if (touch.phase == UITouchPhaseMoved) { + multitouchSequenceIsEnded = NO; + [moved addObject:touch]; + } else if (touch.phase == UITouchPhaseStationary) { + multitouchSequenceIsEnded = NO; + } else if (touch.phase == UITouchPhaseEnded) { + [ended addObject:touch]; + } else if (touch.phase == UITouchPhaseCancelled) { + [cancelled addObject:touch]; + } + } -- (void)_discreteGestures:(NSSet *)touches withEvent:(UIEvent *)event -{ -} + if (_state == UIGestureRecognizerStatePossible || _state == UIGestureRecognizerStateBegan || _state == UIGestureRecognizerStateChanged) { + if ([began count]) { + [self touchesBegan:began withEvent:event]; + } -- (BOOL)_shouldAttemptToRecognize -{ - return (self.enabled && - self.state != UIGestureRecognizerStateFailed && - self.state != UIGestureRecognizerStateCancelled && - self.state != UIGestureRecognizerStateEnded); + if ([moved count]) { + [self touchesMoved:moved withEvent:event]; + } + + if ([ended count]) { + [self touchesEnded:ended withEvent:event]; + } + + if ([cancelled count]) { + [self touchesCancelled:cancelled withEvent:event]; + } + } + + // if all the touches are ended or cancelled, then the multitouch sequence must be over - so we can reset + // our state back to normal and clear all the tracked touches, etc. to get ready for a new touch sequence + // in the future. + // this also applies to the special discrete gesture events because those events are only sent once! + if (multitouchSequenceIsEnded || event.isDiscreteGesture) { + // see note above in -setState: about the delay here! + [self performSelector:@selector(reset) withObject:nil afterDelay:0]; + } } -- (void)_recognizeTouches:(NSSet *)touches withEvent:(UIEvent *)event +- (void)_endTrackingTouch:(UITouch *)touch withEvent:(UITouchEvent *)event { - if ([self _shouldAttemptToRecognize]) { - [_trackingTouches setArray:[touches allObjects]]; - - for (UITouch *touch in _trackingTouches) { - switch (touch.phase) { - case UITouchPhaseBegan: - [self touchesBegan:touches withEvent:event]; - break; - - case UITouchPhaseMoved: - [self touchesMoved:touches withEvent:event]; - break; - - case UITouchPhaseEnded: - [self touchesEnded:touches withEvent:event]; - break; - - case UITouchPhaseCancelled: - [self touchesCancelled:touches withEvent:event]; - break; - - case _UITouchPhaseGestureBegan: - [self _gesturesBegan:touches withEvent:event]; - break; - - case _UITouchPhaseGestureChanged: - [self _gesturesMoved:touches withEvent:event]; - break; - - case _UITouchPhaseGestureEnded: - [self _gesturesEnded:touches withEvent:event]; - break; - - case _UITouchPhaseDiscreteGesture: - [self _discreteGestures:touches withEvent:event]; - break; - - default: - break; - } - } - } + [touch _removeGestureRecognizer:self]; + [_trackingTouches removeObject:touch]; } - (NSString *)description diff --git a/UIKit/Classes/UIGestureRecognizerSubclass.h b/UIKit/Classes/UIGestureRecognizerSubclass.h index 5f9987f1..78c8aeb8 100644 --- a/UIKit/Classes/UIGestureRecognizerSubclass.h +++ b/UIKit/Classes/UIGestureRecognizerSubclass.h @@ -30,11 +30,10 @@ #import "UIGestureRecognizer.h" @interface UIGestureRecognizer () +- (void)ignoreTouch:(UITouch *)touch forEvent:(UIEvent*)event; // don't override @property (nonatomic,readwrite) UIGestureRecognizerState state; -- (void)ignoreTouch:(UITouch *)touch forEvent:(UIEvent*)event; // don't override - // override, but be sure to call super - (void)reset; - (BOOL)canPreventGestureRecognizer:(UIGestureRecognizer *)preventedGestureRecognizer; @@ -43,5 +42,4 @@ - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event; - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event; - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event; - @end diff --git a/UIKit/Classes/UIGraphics.m b/UIKit/Classes/UIGraphics.m index 7e90f9fd..97881803 100644 --- a/UIKit/Classes/UIGraphics.m +++ b/UIKit/Classes/UIGraphics.m @@ -72,7 +72,7 @@ CGFloat _UIGraphicsGetContextScaleFactor(CGContextRef ctx) void UIGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque, CGFloat scale) { if (scale == 0.f) { - scale = [UIScreen mainScreen].scale; + scale = [UIScreen mainScreen].scale ?: 1; } const size_t width = size.width * scale; diff --git a/UIKit/Classes/UIImage+UIPrivate.m b/UIKit/Classes/UIImage+UIPrivate.m index dfade4f5..efa02818 100644 --- a/UIKit/Classes/UIImage+UIPrivate.m +++ b/UIKit/Classes/UIImage+UIPrivate.m @@ -152,7 +152,6 @@ + (UIImage *)_tabBarItemImage - (id)_initWithRepresentations:(NSArray *)reps { if ([reps count] == 0) { - [self release]; self = nil; } else if ((self=[super init])) { _representations = [reps copy]; diff --git a/UIKit/Classes/UIImage.h b/UIKit/Classes/UIImage.h index 893cef15..ee810a57 100644 --- a/UIKit/Classes/UIImage.h +++ b/UIKit/Classes/UIImage.h @@ -27,9 +27,9 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#import +#import "UIGeometry.h" -typedef enum { +typedef NS_ENUM(NSInteger, UIImageOrientation) { UIImageOrientationUp, UIImageOrientationDown, // 180 deg rotation UIImageOrientationLeft, // 90 deg CCW @@ -39,7 +39,7 @@ typedef enum { UIImageOrientationDownMirrored, // horizontal flip UIImageOrientationLeftMirrored, // vertical flip UIImageOrientationRightMirrored, // vertical flip -} UIImageOrientation; +}; @interface UIImage : NSObject { @private @@ -58,6 +58,7 @@ typedef enum { - (id)initWithCGImage:(CGImageRef)imageRef scale:(CGFloat)scale orientation:(UIImageOrientation)orientation; - (UIImage *)stretchableImageWithLeftCapWidth:(NSInteger)leftCapWidth topCapHeight:(NSInteger)topCapHeight; +- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets; // not correctly implemented // the draw methods will all check the scale of the current context and attempt to use the best representation it can - (void)drawAtPoint:(CGPoint)point blendMode:(CGBlendMode)blendMode alpha:(CGFloat)alpha; diff --git a/UIKit/Classes/UIImage.m b/UIKit/Classes/UIImage.m index 7948a19b..fc170979 100644 --- a/UIKit/Classes/UIImage.m +++ b/UIKit/Classes/UIImage.m @@ -73,7 +73,7 @@ - (id)initWithContentsOfFile:(NSString *)imagePath - (id)initWithData:(NSData *)data { - return [self _initWithRepresentations:[NSArray arrayWithObjects:[[[UIImageRep alloc] initWithData:data] autorelease], nil]]; + return [self _initWithRepresentations:[NSArray arrayWithObjects:[[UIImageRep alloc] initWithData:data], nil]]; } - (id)initWithCGImage:(CGImageRef)imageRef @@ -83,33 +83,28 @@ - (id)initWithCGImage:(CGImageRef)imageRef - (id)initWithCGImage:(CGImageRef)imageRef scale:(CGFloat)scale orientation:(UIImageOrientation)orientation { - return [self _initWithRepresentations:[NSArray arrayWithObjects:[[[UIImageRep alloc] initWithCGImage:imageRef scale:scale] autorelease], nil]]; + return [self _initWithRepresentations:[NSArray arrayWithObjects:[[UIImageRep alloc] initWithCGImage:imageRef scale:scale], nil]]; } -- (void)dealloc -{ - [_representations release]; - [super dealloc]; -} + (UIImage *)imageWithData:(NSData *)data { - return [[[self alloc] initWithData:data] autorelease]; + return [[self alloc] initWithData:data]; } + (UIImage *)imageWithContentsOfFile:(NSString *)path { - return [[[self alloc] initWithContentsOfFile:path] autorelease]; + return [[self alloc] initWithContentsOfFile:path]; } + (UIImage *)imageWithCGImage:(CGImageRef)imageRef { - return [[[self alloc] initWithCGImage:imageRef] autorelease]; + return [[self alloc] initWithCGImage:imageRef]; } + (UIImage *)imageWithCGImage:(CGImageRef)imageRef scale:(CGFloat)scale orientation:(UIImageOrientation)orientation { - return [[[self alloc] initWithCGImage:imageRef scale:scale orientation:orientation] autorelease]; + return [[self alloc] initWithCGImage:imageRef scale:scale orientation:orientation]; } - (UIImage *)stretchableImageWithLeftCapWidth:(NSInteger)leftCapWidth topCapHeight:(NSInteger)topCapHeight @@ -119,22 +114,27 @@ - (UIImage *)stretchableImageWithLeftCapWidth:(NSInteger)leftCapWidth topCapHeig if ((leftCapWidth == 0 && topCapHeight == 0) || (leftCapWidth >= size.width && topCapHeight >= size.height)) { return self; } else if (leftCapWidth <= 0 || leftCapWidth >= size.width) { - return [[[UIThreePartImage alloc] initWithRepresentations:[self _representations] capSize:MIN(topCapHeight,size.height) vertical:YES] autorelease]; + return [[UIThreePartImage alloc] initWithRepresentations:[self _representations] capSize:MIN(topCapHeight,size.height) vertical:YES]; } else if (topCapHeight <= 0 || topCapHeight >= size.height) { - return [[[UIThreePartImage alloc] initWithRepresentations:[self _representations] capSize:MIN(leftCapWidth,size.width) vertical:NO] autorelease]; + return [[UIThreePartImage alloc] initWithRepresentations:[self _representations] capSize:MIN(leftCapWidth,size.width) vertical:NO]; } else { - return [[[UINinePartImage alloc] initWithRepresentations:[self _representations] leftCapWidth:leftCapWidth topCapHeight:topCapHeight] autorelease]; + return [[UINinePartImage alloc] initWithRepresentations:[self _representations] leftCapWidth:leftCapWidth topCapHeight:topCapHeight]; } } +- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets +{ + return [self stretchableImageWithLeftCapWidth:capInsets.left topCapHeight:capInsets.top]; +} + - (CGSize)size { CGSize size = CGSizeZero; UIImageRep *rep = [_representations lastObject]; const CGSize repSize = rep.imageSize; const CGFloat scale = rep.scale; - size.width = repSize.width / scale; - size.height = repSize.height / scale; + size.width = floorf(repSize.width / scale); + size.height = floorf(repSize.height / scale); return size; } @@ -212,16 +212,10 @@ BOOL UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(NSString *videoPath) { CFMutableDataRef data = CFDataCreateMutable(NULL, 0); CGImageDestinationRef dest = CGImageDestinationCreateWithData(data, kUTTypeJPEG, 1, NULL); - CFNumberRef quality = CFNumberCreate(NULL, kCFNumberCGFloatType, &compressionQuality); - CFStringRef keys[] = { kCGImageDestinationLossyCompressionQuality }; - CFTypeRef values[] = { quality }; - CFDictionaryRef properties = CFDictionaryCreate(NULL, (const void **)&keys, (const void **)&values, 1, NULL, NULL); - CGImageDestinationAddImage(dest, image.CGImage, properties); - CFRelease(properties); - CFRelease(quality); + CGImageDestinationAddImage(dest, image.CGImage, (__bridge CFDictionaryRef)@{(__bridge NSString *)kCGImageDestinationLossyCompressionQuality : @(compressionQuality)}); CGImageDestinationFinalize(dest); CFRelease(dest); - return [(__bridge NSData *)data autorelease]; + return (__bridge_transfer NSMutableData *)data; } NSData *UIImagePNGRepresentation(UIImage *image) @@ -231,5 +225,5 @@ BOOL UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(NSString *videoPath) CGImageDestinationAddImage(dest, image.CGImage, NULL); CGImageDestinationFinalize(dest); CFRelease(dest); - return [(__bridge NSData *)data autorelease]; + return (__bridge_transfer NSMutableData *)data; } diff --git a/UIKit/Classes/UIImageAppKitIntegration.h b/UIKit/Classes/UIImageAppKitIntegration.h index 15c2b175..745a4713 100644 --- a/UIKit/Classes/UIImageAppKitIntegration.h +++ b/UIKit/Classes/UIImageAppKitIntegration.h @@ -35,4 +35,46 @@ + (id)imageWithNSImage:(NSImage *)theImage; - (id)initWithNSImage:(NSImage *)theImage; - (NSImage *)NSImage; + +/* + this is a hack to support screen scale factor changes (retina) which iOS doesn't + have a decent way to support as far as I can tell. + + these will build a UIImage object from multiple source UIImages that are already + at different scales and when the resulting UIImage is drawn, it should choose the + correct one based on the scale of the underlying context at the time it is drawn. + + pass an array of UIImage objects at different scales that represent the same image. + + each image must have a different .scale property value, no duplicates allowed! + + each image must be the same size as compared to the others: + - eg: and + + NOTE: internally, UIImage already loads both @1x and @2x versions of image files if + they are present (-initWithNSImage: does something similar), so for the most part you + probably don't need this. the primary purpose of this is if you are custom drawing + something using something like UIGraphicsBeginImageContext() and don't know what the + scale factor of the window might currently be now or in the future. + + EXAMPLE: + + // render @1x + UIGraphicsBeginImageContextWithOptions(size, NO, 1); + .. draw stuff .. + UIImage *image1x = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + // render @2x + UIGraphicsBeginImageContextWithOptions(size, NO, 2); + .. draw stuff .. + UIImage *image2x = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + // put them together + UIImage *finalImage = [UIImage imageWithScaledImages:@[image1, image2]]; + */ ++ (id)imageWithScaledImages:(NSArray *)images; +- (id)initWithScaledImages:(NSArray *)images; + @end diff --git a/UIKit/Classes/UIImageAppKitIntegration.m b/UIKit/Classes/UIImageAppKitIntegration.m index 01b7a13a..c3804c2e 100644 --- a/UIKit/Classes/UIImageAppKitIntegration.m +++ b/UIKit/Classes/UIImageAppKitIntegration.m @@ -37,14 +37,14 @@ static UIImageRep *UIImageRepFromNSImageRep(NSImageRep *rep, NSRect rect, CGFloat scale) { - return [[[UIImageRep alloc] initWithCGImage:[rep CGImageForProposedRect:&rect context:nil hints:nil] scale:scale] autorelease]; + return [[UIImageRep alloc] initWithCGImage:[rep CGImageForProposedRect:&rect context:nil hints:nil] scale:scale]; } @implementation UIImage (AppKitIntegration) + (id)imageWithNSImage:(NSImage *)theImage { - return [[[self alloc] initWithNSImage:theImage] autorelease]; + return [[self alloc] initWithNSImage:theImage]; } - (id)initWithNSImage:(NSImage *)theImage @@ -75,9 +75,9 @@ - (NSImage *)NSImage NSImage *cached = objc_getAssociatedObject(self, UIImageAssociatedNSImageKey); if (!cached) { - cached = [[[NSImage alloc] initWithSize:NSSizeFromCGSize(self.size)] autorelease]; + cached = [[NSImage alloc] initWithSize:NSSizeFromCGSize(self.size)]; for (UIImageRep *rep in [self _representations]) { - [cached addRepresentation:[[[NSBitmapImageRep alloc] initWithCGImage:rep.CGImage] autorelease]]; + [cached addRepresentation:[[NSBitmapImageRep alloc] initWithCGImage:rep.CGImage]]; } objc_setAssociatedObject(self, UIImageAssociatedNSImageKey, cached, OBJC_ASSOCIATION_RETAIN); } @@ -85,4 +85,26 @@ - (NSImage *)NSImage return cached; } ++ (id)imageWithScaledImages:(NSArray *)images +{ + return [[self alloc] initWithScaledImages:images]; +} + +- (id)initWithScaledImages:(NSArray *)images +{ + NSMutableArray *reps = [NSMutableArray arrayWithCapacity:[images count]]; + NSMutableSet *scaleFactors = [NSMutableSet setWithCapacity:[images count]]; + + for (UIImage *img in images) { + NSNumber *scale = [NSNumber numberWithFloat:img.scale]; + assert(CGSizeEqualToSize(img.size, [[images lastObject] size])); + assert(![scaleFactors containsObject:scale]); + + [scaleFactors addObject:scale]; + [reps addObject:[[UIImageRep alloc] initWithCGImage:img.CGImage scale:img.scale]]; + } + + return [self _initWithRepresentations:reps]; +} + @end diff --git a/UIKit/Classes/UIImagePickerController.h b/UIKit/Classes/UIImagePickerController.h index 1f3e042f..43de2487 100644 --- a/UIKit/Classes/UIImagePickerController.h +++ b/UIKit/Classes/UIImagePickerController.h @@ -29,12 +29,11 @@ #import "UINavigationController.h" -enum { +typedef NS_ENUM(NSInteger, UIImagePickerControllerSourceType) { UIImagePickerControllerSourceTypePhotoLibrary, UIImagePickerControllerSourceTypeCamera, UIImagePickerControllerSourceTypeSavedPhotosAlbum }; -typedef NSUInteger UIImagePickerControllerSourceType; extern NSString *const UIImagePickerControllerMediaType; extern NSString *const UIImagePickerControllerOriginalImage; @@ -45,17 +44,12 @@ extern NSString *const UIImagePickerControllerMediaURL; @protocol UIImagePickerControllerDelegate @end -@interface UIImagePickerController : UINavigationController { -@private - UIImagePickerControllerSourceType _sourceType; - NSArray *_mediaTypes; -} - +@interface UIImagePickerController : UINavigationController + (NSArray *)availableMediaTypesForSourceType:(UIImagePickerControllerSourceType)sourceType; + (BOOL)isSourceTypeAvailable:(UIImagePickerControllerSourceType)sourceType; @property (nonatomic) UIImagePickerControllerSourceType sourceType; -@property (nonatomic,assign) id delegate; -@property (nonatomic,copy) NSArray *mediaTypes; - +@property (nonatomic, assign) id delegate; +@property (nonatomic, copy) NSArray *mediaTypes; +@property (nonatomic) BOOL allowsEditing; @end diff --git a/UIKit/Classes/UIImagePickerController.m b/UIKit/Classes/UIImagePickerController.m index f4fb4a2f..11dcc4ec 100644 --- a/UIKit/Classes/UIImagePickerController.m +++ b/UIKit/Classes/UIImagePickerController.m @@ -36,8 +36,6 @@ NSString *const UIImagePickerControllerMediaURL = @"UIImagePickerControllerMediaURL"; @implementation UIImagePickerController -@synthesize sourceType=_sourceType, mediaTypes=_mediaTypes; -@dynamic delegate; + (NSArray *)availableMediaTypesForSourceType:(UIImagePickerControllerSourceType)sourceType { @@ -49,10 +47,4 @@ + (BOOL)isSourceTypeAvailable:(UIImagePickerControllerSourceType)sourceType return NO; } -- (void)dealloc -{ - [_mediaTypes release]; - [super dealloc]; -} - @end diff --git a/UIKit/Classes/UIImageRep.h b/UIKit/Classes/UIImageRep.h index 423700c0..c62b68ae 100644 --- a/UIKit/Classes/UIImageRep.h +++ b/UIKit/Classes/UIImageRep.h @@ -29,12 +29,7 @@ #import -@interface UIImageRep : NSObject { - CGFloat _scale; - CGImageSourceRef _imageSource; - NSInteger _imageSourceIndex; - CGImageRef _image; -} +@interface UIImageRep : NSObject + (NSArray *)imageRepsWithContentsOfFile:(NSString *)file; diff --git a/UIKit/Classes/UIImageRep.m b/UIKit/Classes/UIImageRep.m index 2d8f1fa2..fe8ea0d5 100644 --- a/UIKit/Classes/UIImageRep.m +++ b/UIKit/Classes/UIImageRep.m @@ -33,11 +33,14 @@ static CGImageSourceRef CreateCGImageSourceWithFile(NSString *imagePath) { NSString *macPath = [[[imagePath stringByDeletingPathExtension] stringByAppendingString:@"~mac"] stringByAppendingPathExtension:[imagePath pathExtension]]; - return CGImageSourceCreateWithURL((CFURLRef)[NSURL fileURLWithPath:macPath], NULL) ?: CGImageSourceCreateWithURL((CFURLRef)[NSURL fileURLWithPath:imagePath], NULL); + return CGImageSourceCreateWithURL((__bridge CFURLRef)[NSURL fileURLWithPath:macPath], NULL) ?: CGImageSourceCreateWithURL((__bridge CFURLRef)[NSURL fileURLWithPath:imagePath], NULL); } -@implementation UIImageRep -@synthesize scale=_scale; +@implementation UIImageRep { + CGImageSourceRef _imageSource; + NSInteger _imageSourceIndex; + CGImageRef _CGImage; +} + (NSArray *)_imageRepsWithContentsOfMultiResolutionFile:(NSString *)imagePath { @@ -57,13 +60,11 @@ + (NSArray *)_imageRepsWithContentsOfFiles:(NSString *)imagePath if (src1X) { UIImageRep *rep = [[UIImageRep alloc] initWithCGImageSource:src1X imageIndex:0 scale:1]; if (rep) [reps addObject:rep]; - [rep release]; CFRelease(src1X); } if (src2X) { UIImageRep *rep = [[UIImageRep alloc] initWithCGImageSource:src2X imageIndex:0 scale:2]; if (rep) [reps addObject:rep]; - [rep release]; CFRelease(src2X); } @@ -78,7 +79,6 @@ + (NSArray *)imageRepsWithContentsOfFile:(NSString *)imagePath - (id)initWithCGImageSource:(CGImageSourceRef)source imageIndex:(NSUInteger)index scale:(CGFloat)scale { if (!source || CGImageSourceGetCount(source) <= index) { - [self release]; self = nil; } else if ((self=[super init])) { CFRetain(source); @@ -92,23 +92,21 @@ - (id)initWithCGImageSource:(CGImageSourceRef)source imageIndex:(NSUInteger)inde - (id)initWithCGImage:(CGImageRef)image scale:(CGFloat)scale { if (!image) { - [self release]; self = nil; } else if ((self=[super init])) { _scale = scale; - _image = CGImageRetain(image); + _CGImage = CGImageRetain(image); } return self; } - (id)initWithData:(NSData *)data { - CGImageSourceRef src = data? CGImageSourceCreateWithData((CFDataRef)data, NULL) : NULL; + CGImageSourceRef src = data? CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL) : NULL; if (src) { self = [self initWithCGImageSource:src imageIndex:0 scale:1]; CFRelease(src); } else { - [self release]; self = nil; } @@ -117,22 +115,21 @@ - (id)initWithData:(NSData *)data - (void)dealloc { - if (_image) CGImageRelease(_image); + if (_CGImage) CGImageRelease(_CGImage); if (_imageSource) CFRelease(_imageSource); - [super dealloc]; } - (BOOL)isLoaded { - return (_image != NULL); + return (_CGImage != NULL); } - (BOOL)isOpaque { BOOL opaque = NO; - if (_image) { - CGImageAlphaInfo info = CGImageGetAlphaInfo(_image); + if (_CGImage) { + CGImageAlphaInfo info = CGImageGetAlphaInfo(_CGImage); opaque = (info == kCGImageAlphaNone) || (info == kCGImageAlphaNoneSkipLast) || (info == kCGImageAlphaNoneSkipFirst); } else if (_imageSource) { CFDictionaryRef info = CGImageSourceCopyPropertiesAtIndex(_imageSource, _imageSourceIndex, NULL); @@ -147,9 +144,9 @@ - (CGSize)imageSize { CGSize size = CGSizeZero; - if (_image) { - size.width = CGImageGetWidth(_image); - size.height = CGImageGetHeight(_image); + if (_CGImage) { + size.width = CGImageGetWidth(_CGImage); + size.height = CGImageGetHeight(_CGImage); } else if (_imageSource) { CFDictionaryRef info = CGImageSourceCopyPropertiesAtIndex(_imageSource, _imageSourceIndex, NULL); CFNumberRef width = CFDictionaryGetValue(info, kCGImagePropertyPixelWidth); @@ -167,13 +164,13 @@ - (CGSize)imageSize - (CGImageRef)CGImage { // lazy load if we only have an image source - if (!_image && _imageSource) { - _image = CGImageSourceCreateImageAtIndex(_imageSource, _imageSourceIndex, NULL); + if (!_CGImage && _imageSource) { + _CGImage = CGImageSourceCreateImageAtIndex(_imageSource, _imageSourceIndex, NULL); CFRelease(_imageSource); _imageSource = NULL; } - return _image; + return _CGImage; } - (void)drawInRect:(CGRect)rect fromRect:(CGRect)fromRect diff --git a/UIKit/Classes/UIImageView+UIPrivate.h b/UIKit/Classes/UIImageView+UIPrivate.h index 3798374b..5f3476d0 100644 --- a/UIKit/Classes/UIImageView+UIPrivate.h +++ b/UIKit/Classes/UIImageView+UIPrivate.h @@ -29,12 +29,12 @@ #import "UIImageView.h" -enum { +typedef NS_ENUM(NSInteger, _UIImageViewDrawMode) { _UIImageViewDrawModeNormal, _UIImageViewDrawModeHighlighted, _UIImageViewDrawModeDisabled, }; @interface UIImageView (UIPrivate) -- (void)_setDrawMode:(NSInteger)drawMode; +- (void)_setDrawMode:(_UIImageViewDrawMode)drawMode; @end diff --git a/UIKit/Classes/UIImageView.h b/UIKit/Classes/UIImageView.h index 2645d1dc..7b0aaef8 100644 --- a/UIKit/Classes/UIImageView.h +++ b/UIKit/Classes/UIImageView.h @@ -31,30 +31,18 @@ @class UIImage, CAKeyframeAnimation; -@interface UIImageView : UIView { -@private - UIImage *_image; - NSArray *_animationImages; - NSArray *_highlightedAnimationImages; - NSTimeInterval _animationDuration; - NSInteger _animationRepeatCount; - UIImage *_highlightedImage; - BOOL _highlighted; - NSInteger _drawMode; -} - +@interface UIImageView : UIView - (id)initWithImage:(UIImage *)theImage; - (void)startAnimating; - (void)stopAnimating; - (BOOL)isAnimating; -@property (nonatomic, retain) UIImage *highlightedImage; +@property (nonatomic, strong) UIImage *highlightedImage; @property (nonatomic, getter=isHighlighted) BOOL highlighted; -@property (nonatomic, retain) UIImage *image; +@property (nonatomic, strong) UIImage *image; @property (nonatomic, copy) NSArray *animationImages; @property (nonatomic, copy) NSArray *highlightedAnimationImages; @property (nonatomic) NSTimeInterval animationDuration; @property (nonatomic) NSInteger animationRepeatCount; - @end diff --git a/UIKit/Classes/UIImageView.m b/UIKit/Classes/UIImageView.m index 81d5cca2..50a4fafa 100644 --- a/UIKit/Classes/UIImageView.m +++ b/UIKit/Classes/UIImageView.m @@ -47,9 +47,9 @@ return CGImages; } -@implementation UIImageView -@synthesize image=_image, animationImages=_animationImages, animationDuration=_animationDuration, highlightedImage=_highlightedImage, highlighted=_highlighted; -@synthesize animationRepeatCount=_animationRepeatCount, highlightedAnimationImages=_highlightedAnimationImages; +@implementation UIImageView { + _UIImageViewDrawMode _drawMode; +} + (BOOL)_instanceImplementsDrawRect { @@ -81,14 +81,6 @@ - (id)initWithImage:(UIImage *)theImage return self; } -- (void)dealloc -{ - [_animationImages release]; - [_image release]; - [_highlightedImage release]; - [_highlightedAnimationImages release]; - [super dealloc]; -} - (CGSize)sizeThatFits:(CGSize)size { @@ -110,8 +102,7 @@ - (void)setHighlighted:(BOOL)h - (void)setImage:(UIImage *)newImage { if (_image != newImage) { - [_image release]; - _image = [newImage retain]; + _image = newImage; if (!_highlighted || !_highlightedImage) { [self setNeedsDisplay]; } @@ -121,8 +112,7 @@ - (void)setImage:(UIImage *)newImage - (void)setHighlightedImage:(UIImage *)newImage { if (_highlightedImage != newImage) { - [_highlightedImage release]; - _highlightedImage = [newImage retain]; + _highlightedImage = newImage; if (_highlighted) { [self setNeedsDisplay]; } @@ -134,7 +124,7 @@ - (BOOL)_hasResizableImage return (_image.topCapHeight > 0 || _image.leftCapWidth > 0); } -- (void)_setDrawMode:(NSInteger)drawMode +- (void)_setDrawMode:(_UIImageViewDrawMode)drawMode { if (drawMode != _drawMode) { _drawMode = drawMode; diff --git a/UIKit/Classes/UIInputController.h b/UIKit/Classes/UIInputController.h index b7e2bcb3..c606d055 100644 --- a/UIKit/Classes/UIInputController.h +++ b/UIKit/Classes/UIInputController.h @@ -27,22 +27,20 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#import +#import "UIResponder.h" +#import "UITextInput.h" @class UIView, UIWindow; -@interface UIInputController : NSObject { - UIWindow *_inputWindow; - UIView *_inputAccessoryView; - UIView *_inputView; -} +@interface UIInputController : NSObject + (UIInputController *)sharedInputController; - (void)setInputVisible:(BOOL)visible animated:(BOOL)animated; -@property (nonatomic, retain) UIView *inputAccessoryView; -@property (nonatomic, retain) UIView *inputView; +@property (nonatomic, strong) UIView *inputAccessoryView; +@property (nonatomic, strong) UIView *inputView; +@property (nonatomic, weak) UIResponder *keyInputResponder; @property (nonatomic, assign) BOOL inputVisible; diff --git a/UIKit/Classes/UIInputController.m b/UIKit/Classes/UIInputController.m index 984eef43..f18ecc7a 100644 --- a/UIKit/Classes/UIInputController.m +++ b/UIKit/Classes/UIInputController.m @@ -47,8 +47,9 @@ } -@implementation UIInputController -@synthesize inputAccessoryView=_inputAccessoryView, inputView=_inputView; +@implementation UIInputController { + UIWindow *_inputWindow; +} + (UIInputController *)sharedInputController { @@ -77,17 +78,12 @@ - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; - [_inputWindow release]; - [_inputAccessoryView release]; - [_inputView release]; - [super dealloc]; } // finds the first real UIView that the current key window's first responder "belongs" to so we know where to display the input window - (UIView *)_referenceView { - UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow; - UIResponder *firstResponder = [keyWindow _firstResponder]; + UIResponder *firstResponder = self.keyInputResponder; if (firstResponder) { UIResponder *currentResponder = firstResponder; @@ -143,11 +139,13 @@ - (void)_repositionInputWindow - (void)_viewChangedNotification:(NSNotification *)note { - UIView *view = [note object]; - UIView *referenceView = [self _referenceView]; + if (self.inputVisible) { + UIView *view = [note object]; + UIView *referenceView = [self _referenceView]; - if (self.inputVisible && (view == referenceView || [ContainerForView(referenceView) isDescendantOfView:view])) { - [self _repositionInputWindow]; + if (view == referenceView || [ContainerForView(referenceView) isDescendantOfView:view]) { + [self _repositionInputWindow]; + } } } @@ -191,9 +189,8 @@ - (void)setInputAccessoryView:(UIView *)view { if (view != _inputAccessoryView) { [_inputAccessoryView removeFromSuperview]; - [_inputAccessoryView release]; - _inputAccessoryView = [view retain]; + _inputAccessoryView = view; [_inputWindow addSubview:_inputAccessoryView]; } } @@ -202,9 +199,8 @@ - (void)setInputView:(UIView *)view { if (view != _inputView) { [_inputView removeFromSuperview]; - [_inputView release]; - _inputView = [view retain]; + _inputView = view; [_inputWindow addSubview:_inputView]; } } diff --git a/UIKit/Classes/UIInterface.h b/UIKit/Classes/UIInterface.h index acc01943..a8b7d38f 100644 --- a/UIKit/Classes/UIInterface.h +++ b/UIKit/Classes/UIInterface.h @@ -31,13 +31,17 @@ #import "UIFont.h" -typedef enum { +typedef NS_ENUM(NSInteger, UIBarStyle) { UIBarStyleDefault = 0, UIBarStyleBlack = 1, UIBarStyleBlackOpaque = 1, // Deprecated UIBarStyleBlackTranslucent = 2 // Deprecated -} UIBarStyle; +}; +typedef NS_ENUM(NSInteger, UIBarMetrics) { + UIBarMetricsDefault, + UIBarMetricsLandscapePhone, +}; @interface UIColor (UIColorSystemColors) + (UIColor *)groupTableViewBackgroundColor; diff --git a/UIKit/Classes/UIKey.h b/UIKit/Classes/UIKey.h index 019c75e1..871eb032 100644 --- a/UIKit/Classes/UIKey.h +++ b/UIKit/Classes/UIKey.h @@ -29,11 +29,13 @@ #import +@class NSEvent; + // NOTE: This does not come from Apple's UIKit and only exist to solve some current problems. // I have no idea what Apple will do with keyboard handling. If they ever expose that stuff publically, // then all of this should change to reflect the official API. -typedef enum { +typedef NS_ENUM(NSInteger, UIKeyType) { UIKeyTypeCharacter, // the catch-all/default... I wouldn't depend much on this at this point UIKeyTypeUpArrow, UIKeyTypeDownArrow, @@ -47,16 +49,11 @@ typedef enum { UIKeyTypeEnd, UIKeyTypePageUp, UIKeyTypePageDown, -} UIKeyType; + UIKeyTypeEscape, +}; -@interface UIKey : NSObject { -@private - unsigned short _keyCode; - NSString *_characters; - NSString *_charactersWithModifiers; - NSUInteger _modifierFlags; - BOOL _repeat; -} +@interface UIKey : NSObject +- (id)initWithNSEvent:(NSEvent *)event; @property (nonatomic, readonly) UIKeyType type; @property (nonatomic, readonly) unsigned short keyCode; @@ -68,5 +65,5 @@ typedef enum { @property (nonatomic, readonly, getter=isControlKeyPressed) BOOL controlKeyPressed; @property (nonatomic, readonly, getter=isOptionKeyPressed) BOOL optionKeyPressed; @property (nonatomic, readonly, getter=isCommandKeyPressed) BOOL commandKeyPressed; - +@property (nonatomic, readonly) SEL action; // an action associated with the key press, or null @end diff --git a/UIKit/Classes/UIKey.m b/UIKit/Classes/UIKey.m index 7dbed326..a5782e7b 100644 --- a/UIKit/Classes/UIKey.m +++ b/UIKit/Classes/UIKey.m @@ -27,11 +27,12 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#import "UIKey+UIPrivate.h" +#import "UIKey.h" #import -@implementation UIKey -@synthesize keyCode=_keyCode, characters=_characters, charactersWithModifiers=_charactersWithModifiers, repeat=_repeat; +@implementation UIKey { + NSUInteger _modifierFlags; +} - (id)initWithNSEvent:(NSEvent *)event { @@ -45,15 +46,13 @@ - (id)initWithNSEvent:(NSEvent *)event return self; } -- (void)dealloc -{ - [_characters release]; - [_charactersWithModifiers release]; - [super dealloc]; -} - (UIKeyType)type { + if (_keyCode == 53) { + return UIKeyTypeEscape; + } + if ([_characters length] > 0) { switch ([_characters characterAtIndex:0]) { case NSUpArrowFunctionKey: return UIKeyTypeUpArrow; @@ -99,4 +98,17 @@ - (BOOL)isCommandKeyPressed return (_modifierFlags & NSCommandKeyMask) == NSCommandKeyMask; } +- (SEL)action +{ + if (self.type == UIKeyTypeEnter || (self.type == UIKeyTypeReturn && self.commandKeyPressed)) { + return @selector(commitOperation:); + } + + if (self.type == UIKeyTypeEscape || (self.commandKeyPressed && [self.characters isEqual:@"."])) { + return @selector(cancelOperation:); + } + + return NULL; +} + @end diff --git a/UIKit/Classes/UIKit.h b/UIKit/Classes/UIKit.h index 24ab4f36..6f64d7ee 100644 --- a/UIKit/Classes/UIKit.h +++ b/UIKit/Classes/UIKit.h @@ -108,13 +108,17 @@ #import "UISwipeGestureRecognizer.h" #import "UIDatePicker.h" #import "UIAppearance.h" +#import "UITextInput.h" // non-standard imports -#import "UIKey.h" #import "UIScrollWheelGestureRecognizer.h" -// only add if core data is included on 10.6 -#import "NSFetchedResultsController.h" +// osx imports +#import +#import +#import +#import +#import // SystemConfiguration-Helper #define kSCNetworkReachabilityFlagsIsWWAN kSCNetworkReachabilityFlagsConnectionOnDemand diff --git a/UIKit/Classes/UIKitView.h b/UIKit/Classes/UIKitView.h index acd75515..7db3c32d 100644 --- a/UIKit/Classes/UIKitView.h +++ b/UIKit/Classes/UIKitView.h @@ -29,22 +29,14 @@ #import #import "UIApplicationDelegate.h" +#import "UIScreen.h" +#import "UIWindow.h" -@class UIScreen, UIWindow; +@interface UIKitView : NSView -@interface UIKitView : NSView { - UIScreen *_screen; - UIWindow *_mainWindow; - NSTrackingArea *_trackingArea; -} - -// if UIApplication's keyWindow is on the screen represented by this UIKitView, this will send -canPerformAction:withSender: to the keyWindow's -// current first responder with the given action and sender and return the result. if the keyWindow is not on this screen, it always returns NO. -- (BOOL)firstResponderCanPerformAction:(SEL)action withSender:(id)sender; - -// if UIApplication's keyWindow is on the screen represented by this UIKitView, this will send the action down the responder chain starting with -// the keyWindow's first responder. if the keyWindow is not on this screen, nothing happens. -- (void)sendActionToFirstResponder:(SEL)action from:(id)sender; +// returns the UIView (or nil) that successfully responds to a -hitTest:withEvent: at the given point. +// the point is specified in this view's coordinate system (unlike NSView's hitTest method). +- (UIView *)hitTestUIView:(NSPoint)point; // this is an optional method // it will set the sharedApplication's delegate to appDelegate. if delay is >0, it will then look in the app bundle for @@ -55,12 +47,15 @@ // ** IMPORTANT: appDelegate is *not* retained! ** - (void)launchApplicationWithDelegate:(id)appDelegate afterDelay:(NSTimeInterval)delay; +// these are sort of hacks used internally. I don't know if there's much need for them from the outside, really. +- (void)cancelTouchesInView:(UIView *)view; +- (void)sendStationaryTouches; + // this is an optional property to make it quick and easy to get a window to start adding views to. // created on-demand to be the size of the UIScreen.bounds, flexible width/height, and calls makeKeyAndVisible when it is first created -@property (nonatomic, retain, readonly) UIWindow *UIWindow; +@property (nonatomic, strong, readonly) UIWindow *UIWindow; // a UIKitView owns a single UIScreen. when the UIKitView is part of an NSWindow hierarchy, the UIScreen appears as a connected screen in // [UIScreen screens], etc. -@property (nonatomic, retain, readonly) UIScreen *UIScreen; - +@property (nonatomic, strong, readonly) UIScreen *UIScreen; @end diff --git a/UIKit/Classes/UIKitView.m b/UIKit/Classes/UIKitView.m index 9e3f1b61..471cd4d7 100644 --- a/UIKit/Classes/UIKitView.m +++ b/UIKit/Classes/UIKitView.m @@ -28,61 +28,85 @@ */ #import "UIKitView.h" -#import "UIApplication+UIPrivate.h" +#import "UIApplication.h" #import "UIScreen+UIPrivate.h" +#import "UIScreenAppKitIntegration.h" #import "UIWindow+UIPrivate.h" #import "UIImage.h" #import "UIImageView.h" #import "UIColor.h" +#import "UITouchEvent.h" +#import "UITouch+UIPrivate.h" +#import "UIKey.h" +#import "UINSResponderShim.h" +#import "UIViewControllerAppKitIntegration.h" -@implementation UIKitView -@synthesize UIScreen=_screen; +/* + An older design of Chameleon had the singlular multi-touch event living in UIApplication because that made sense at the time. + However it was needlessly awkward to send events from here to the UIApplication and then have to decode them all again, etc. + It seemingly gained nothing. Also, while I don't know how UIKit would handle this situation, I'm not sure it makes sense to + have a single multitouch sequence span multiple screens anyway. There are some cases where that might kinda make sense, but + I'm having some doubts that this is how iOS would be setup anyway. (It's hard to really know without some deep digging since + I don't know if iOS even supports touch events on any screen other than the main one anyway, but it doesn't matter right now.) + + The benefit of having it here is that this is right where the touches happen. There's no ambiguity about exactly which + screen/NSView the event occured on, and there's no need to pass that info around deep into other parts of the code, either. + It can be dealt with here and now and life can go on and things don't have to get weirdly complicated deep down the rabbit + hole. In theory. + */ -- (void)setScreenLayer -{ - [self setWantsLayer:YES]; +@interface UIKitView () +@end - CALayer *screenLayer = [_screen _layer]; - CALayer *myLayer = [self layer]; - - [myLayer addSublayer:screenLayer]; - screenLayer.frame = myLayer.bounds; - screenLayer.autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable; - myLayer.geometryFlipped = YES; +@implementation UIKitView { + UITouchEvent *_touchEvent; + UITouch *_mouseMoveTouch; + UIWindow *_UIWindow; + NSTrackingArea *_trackingArea; + UINSResponderShim *_responderShim; } - (id)initWithFrame:(NSRect)frame { if ((self = [super initWithFrame:frame])) { - _screen = [[UIScreen alloc] init]; - [self setScreenLayer]; + _mouseMoveTouch = [[UITouch alloc] init]; + _UIScreen = [[UIScreen alloc] init]; + _responderShim = [[UINSResponderShim alloc] init]; + + _responderShim.delegate = self; + + [self configureScreenLayer]; } return self; } -- (void)dealloc +- (void)awakeFromNib { - [_screen release]; - [_mainWindow release]; - [_trackingArea release]; - [super dealloc]; + [self configureScreenLayer]; } -- (void)awakeFromNib +- (void)configureScreenLayer { - [self setScreenLayer]; + [self setWantsLayer:YES]; + + CALayer *screenLayer = [_UIScreen _layer]; + CALayer *myLayer = [self layer]; + + [myLayer addSublayer:screenLayer]; + screenLayer.frame = myLayer.bounds; + screenLayer.autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable; } - (UIWindow *)UIWindow { - if (!_mainWindow) { - _mainWindow = [(UIWindow *)[UIWindow alloc] initWithFrame:_screen.bounds]; - _mainWindow.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - _mainWindow.screen = _screen; - [_mainWindow makeKeyAndVisible]; + if (!_UIWindow) { + _UIWindow = [[UIWindow alloc] initWithFrame:_UIScreen.bounds]; + _UIWindow.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + _UIWindow.screen = _UIScreen; + [_UIWindow makeKeyAndVisible]; } - return _mainWindow; + return _UIWindow; } - (BOOL)isFlipped @@ -90,9 +114,38 @@ - (BOOL)isFlipped return YES; } +- (BOOL)acceptsFirstResponder +{ + // we want to accept, but we have to make sure one of our NSView children isn't already the first responder + // because we don't want to let the mouse just steal that away here. If a pure-UIKit object gets clicked on + // and decides to become first responder, it'll take it itself and things should sort itself out from there + // (so stuff like a selected NSTextView would be resigned in the process of the new object becoming first + // responder so we don't have to let AppKit handle it here in that case and returning NO should be okay + // because by the time this is called again, the native AppKit control has already been told to resign) + + // the reason we can't just blindly accept first responder is that there are special situations like the + // inputAccessoryViews which live inside our UIKitView and are implemented as UIKit code, but are often + // used while the user has a native NSTextView as the first responder because they are typing in it. If + // we didn't do this checking here, the click outside of the NSTextView would register as a click on this + // UIKitView, and if we just returned YES here, AppKit would happily resign first responder from the text + // view and set it for this UIKitView which causes the inputAccessoryView to disappear! + + NSResponder *responder = [(NSWindow *)[self window] firstResponder]; + + while (responder) { + if (responder == self) { + return NO; + } else { + responder = [responder nextResponder]; + } + } + + return YES; +} + - (void)updateUIKitView { - [_screen _setUIKitView:(self.superview && self.window)? self : nil]; + [_UIScreen _setUIKitView:(self.superview && self.window)? self : nil]; } - (void)viewDidMoveToSuperview @@ -107,108 +160,155 @@ - (void)viewDidMoveToWindow [self updateUIKitView]; } -- (BOOL)acceptsFirstResponder +- (void)updateTrackingAreas { - // only accept first responder status if something else within our view isn't already the first responder - // and if our screen has something that can become first responder - // I have no idea if this is sane behavior or not. There's an issue with things like inputAccesoryViews - // because the NSTextView might be the real first responder (from AppKit's point of view) and any click - // outside of it could change the first responder status. This means that clicks on the inputAccessoryView - // could "steal" first responder away from the NSTextView if this always returns YES, but on the other - // hand we shouldn't always return NO here because pure-UIKit objects could be first responder, too, and - // in theory they'd expect to get keyboard events or something like that. So....... yeah.. I dunno. + [super updateTrackingAreas]; + [self removeTrackingArea:_trackingArea]; + _trackingArea = [[NSTrackingArea alloc] initWithRect:self.bounds options:NSTrackingCursorUpdate|NSTrackingMouseMoved|NSTrackingInVisibleRect|NSTrackingActiveInKeyWindow|NSTrackingMouseEnteredAndExited owner:self userInfo:nil]; + [self addTrackingArea:_trackingArea]; +} - NSResponder *responder = [(NSWindow *)[self window] firstResponder]; - BOOL accept = !responder || ([[UIApplication sharedApplication] _firstResponderForScreen:_screen] != nil); +- (UIView *)hitTestUIView:(NSPoint)point +{ + NSMutableArray *sortedWindows = [_UIScreen.windows mutableCopy]; + [sortedWindows sortUsingDescriptors:@[[[NSSortDescriptor alloc] initWithKey:@"windowLevel" ascending:NO]]]; - // if we might want to accept, lets make sure that one of our children isn't already the first responder - // because we don't want to let the mouse just steal that away here. If a pure-UIKit object gets clicked on and - // decides to become first responder, it'll take it itself and things should sort itself out from there - // (so stuff like a selected NSTextView would be resigned in the process of the new object becoming first - // responder so we don't have to let AppKit handle it in that case and returning NO here should be okay) - if (accept) { - while (responder) { - if (responder == self) { - return NO; - } else { - responder = [responder nextResponder]; - } - } + for (UIWindow *window in sortedWindows) { + const CGPoint windowPoint = [window convertPoint:point fromWindow:nil]; + UIView *hitView = [window hitTest:windowPoint withEvent:nil]; + if (hitView) return hitView; + } + + return nil; +} + +- (void)launchApplicationWithDefaultWindow:(UIWindow *)defaultWindow +{ + UIApplication *app = [UIApplication sharedApplication]; + id appDelegate = app.delegate; + + if ([appDelegate respondsToSelector:@selector(application:didFinishLaunchingWithOptions:)]) { + [appDelegate application:app didFinishLaunchingWithOptions:nil]; + } else if ([appDelegate respondsToSelector:@selector(applicationDidFinishLaunching:)]) { + [appDelegate applicationDidFinishLaunching:app]; + } + + [[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationDidFinishLaunchingNotification object:app]; + + if ([appDelegate respondsToSelector:@selector(applicationDidBecomeActive:)]) { + [appDelegate applicationDidBecomeActive:app]; } - return accept; + [[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationDidBecomeActiveNotification object:app]; + + defaultWindow.hidden = YES; } -- (BOOL)firstResponderCanPerformAction:(SEL)action withSender:(id)sender +- (void)launchApplicationWithDelegate:(id)appDelegate afterDelay:(NSTimeInterval)delay { - return [[UIApplication sharedApplication] _firstResponderCanPerformAction:action withSender:sender fromScreen:_screen]; + [[UIApplication sharedApplication] setDelegate:appDelegate]; + + if (delay) { + UIImage *defaultImage = [UIImage imageNamed:@"Default-Landscape.png"]; + UIImageView *defaultImageView = [[UIImageView alloc] initWithImage:defaultImage]; + defaultImageView.contentMode = UIViewContentModeCenter; + + UIWindow *defaultWindow = [(UIWindow *)[UIWindow alloc] initWithFrame:_UIScreen.bounds]; + defaultWindow.userInteractionEnabled = NO; + defaultWindow.screen = _UIScreen; + defaultWindow.backgroundColor = [UIColor blackColor]; // dunno.. + defaultWindow.opaque = YES; + [defaultWindow addSubview:defaultImageView]; + [defaultWindow makeKeyAndVisible]; + [self performSelector:@selector(launchApplicationWithDefaultWindow:) withObject:defaultWindow afterDelay:delay]; + } else { + [self launchApplicationWithDefaultWindow:nil]; + } } -- (void)sendActionToFirstResponder:(SEL)action from:(id)sender +#pragma mark responder chain muckery + +- (void)setNextResponder:(NSResponder *)aResponder { - [[UIApplication sharedApplication] _sendActionToFirstResponder:action withSender:sender fromScreen:_screen]; + [super setNextResponder:_responderShim]; + [_responderShim setNextResponder:aResponder]; } -- (BOOL)respondsToSelector:(SEL)cmd +- (UIResponder *)responderForResponderShim:(UINSResponderShim *)shim { - if (cmd == @selector(copy:) || - cmd == @selector(cut:) || - cmd == @selector(delete:) || - cmd == @selector(paste:) || - cmd == @selector(select:) || - cmd == @selector(selectAll:) || - cmd == @selector(commit:) || - cmd == @selector(cancel:)) { - return [self firstResponderCanPerformAction:cmd withSender:nil]; - } else if (cmd == @selector(cancelOperation:)) { - return [self firstResponderCanPerformAction:@selector(cancel:) withSender:nil]; - } else { - return [super respondsToSelector:cmd]; + UIWindow *keyWindow = _UIScreen.keyWindow; + UIResponder *responder = [keyWindow _firstResponder]; + + if (!responder) { + UIViewController *controller = keyWindow.rootViewController; + + while (controller) { + // for the sake of completeness, we check the controller's presentedViewController first, because such things are + // supposed to kind of supercede the view controller itself - however we don't currently support them so it just + // returns nil all the time anyway, but what the heck, eh? + if (controller.presentedViewController) { + controller = controller.presentedViewController; + } else { + UIViewController *childController = [controller defaultResponderChildViewController]; + + if (childController) { + controller = childController; + } else { + break; + } + } + } + + responder = [controller defaultResponder]; } + + return responder; } -- (void)copy:(id)sender { [self sendActionToFirstResponder:_cmd from:sender]; } -- (void)cut:(id)sender { [self sendActionToFirstResponder:_cmd from:sender]; } -- (void)delete:(id)sender { [self sendActionToFirstResponder:_cmd from:sender]; } -- (void)paste:(id)sender { [self sendActionToFirstResponder:_cmd from:sender]; } -- (void)select:(id)sender { [self sendActionToFirstResponder:_cmd from:sender]; } -- (void)selectAll:(id)sender { [self sendActionToFirstResponder:_cmd from:sender]; } +#pragma mark touch utilities -// these are special additions -- (void)cancel:(id)sender { [self sendActionToFirstResponder:_cmd from:sender]; } -- (void)commit:(id)sender { [self sendActionToFirstResponder:_cmd from:sender]; } - -// this is a special case, UIKit doesn't normally send anything like this. -// if a UIKit first responder can't handle it, then we'll pass it through to the next responder -// because something else might want to deal with it somewhere else. -- (void)cancelOperation:(id)sender +- (UITouch *)touchForEvent:(NSEvent *)theEvent { - [self sendActionToFirstResponder:@selector(cancel:) from:sender]; + const NSPoint location = [self convertPoint:[theEvent locationInWindow] fromView:nil]; + + UITouch *touch = [[UITouch alloc] init]; + touch.view = [self hitTestUIView:location]; + touch.locationOnScreen = NSPointToCGPoint(location); + touch.timestamp = [theEvent timestamp]; + + return touch; } -// capture the key presses here and turn them into key events which are sent down the UIKit responder chain -// if they come back as unhandled, pass them along the AppKit responder chain. -- (void)keyDown:(NSEvent *)theEvent +- (void)updateTouchLocation:(UITouch *)touch withEvent:(NSEvent *)theEvent { - if (![[UIApplication sharedApplication] _sendKeyboardNSEvent:theEvent fromScreen:_screen]) { - [super keyDown:theEvent]; - } + _touchEvent.touch.locationOnScreen = NSPointToCGPoint([self convertPoint:[theEvent locationInWindow] fromView:nil]); + _touchEvent.touch.timestamp = [theEvent timestamp]; } -- (void)updateTrackingAreas +- (void)cancelTouchesInView:(UIView *)view { - [super updateTrackingAreas]; - [self removeTrackingArea:_trackingArea]; - [_trackingArea release]; - _trackingArea = [[NSTrackingArea alloc] initWithRect:self.bounds options:NSTrackingCursorUpdate|NSTrackingMouseMoved|NSTrackingInVisibleRect|NSTrackingActiveInKeyWindow|NSTrackingMouseEnteredAndExited owner:self userInfo:nil]; - [self addTrackingArea:_trackingArea]; + if (_touchEvent && _touchEvent.touch.phase != UITouchPhaseEnded && _touchEvent.touch.phase != UITouchPhaseCancelled) { + if (!view || [view isDescendantOfView:_touchEvent.touch.view]) { + _touchEvent.touch.phase = UITouchPhaseCancelled; + _touchEvent.touch.timestamp = [NSDate timeIntervalSinceReferenceDate]; + [[UIApplication sharedApplication] sendEvent:_touchEvent]; + [_touchEvent endTouchEvent]; + _touchEvent = nil; + } + } } -- (void)mouseMoved:(NSEvent *)theEvent +- (void)sendStationaryTouches { - [[UIApplication sharedApplication] _sendMouseNSEvent:theEvent fromScreen:_screen]; + if (_touchEvent && _touchEvent.touch.phase != UITouchPhaseEnded && _touchEvent.touch.phase != UITouchPhaseCancelled) { + _touchEvent.touch.phase = UITouchPhaseStationary; + _touchEvent.touch.timestamp = [NSDate timeIntervalSinceReferenceDate]; + [[UIApplication sharedApplication] sendEvent:_touchEvent]; + } } +#pragma mark pseudo touch handling + - (void)mouseDown:(NSEvent *)theEvent { if ([theEvent modifierFlags] & NSControlKeyMask) { @@ -217,110 +317,271 @@ - (void)mouseDown:(NSEvent *)theEvent // really win anything by overriding that since I'd still need a check in here to prevent that mouseDown: from being // sent to UIKit as a touch. That seems really wrong, IMO. A right click should be independent of a touch event. // soooo.... here we are. Whatever. Seems to work. Don't really like it. - NSEvent *newEvent = [NSEvent mouseEventWithType:NSRightMouseDown location:[theEvent locationInWindow] modifierFlags:0 timestamp:[theEvent timestamp] windowNumber:[theEvent windowNumber] context:[theEvent context] eventNumber:[theEvent eventNumber] clickCount:[theEvent clickCount] pressure:[theEvent pressure]]; - [self rightMouseDown:newEvent]; - } else { - [[UIApplication sharedApplication] _sendMouseNSEvent:theEvent fromScreen:_screen]; + [self rightMouseDown:[NSEvent mouseEventWithType:NSRightMouseDown location:[theEvent locationInWindow] modifierFlags:0 timestamp:[theEvent timestamp] windowNumber:[theEvent windowNumber] context:[theEvent context] eventNumber:[theEvent eventNumber] clickCount:[theEvent clickCount] pressure:[theEvent pressure]]]; + return; + } + + // this is a special case to cancel any existing touches (as far as the client code is concerned) if the left + // mouse button is pressed mid-gesture. the reason is that sometimes when using a magic mouse a user will intend + // to click but if their finger moves against the surface ever so slightly, it will trigger a touch gesture to + // begin instead. without this, the fact that we're in a touch gesture phase effectively overrules everything + // else and clicks end up not getting registered. I don't think it's right to allow clicks to pass through when + // we're in a gesture state since that'd be somewhat like a multitouch scenerio on an actual iOS device and we + // are not really supporting anything like that at the moment. + if (_touchEvent) { + _touchEvent.touch.phase = UITouchPhaseCancelled; + [self updateTouchLocation:_touchEvent.touch withEvent:theEvent]; + + [[UIApplication sharedApplication] sendEvent:_touchEvent]; + + [_touchEvent endTouchEvent]; + _touchEvent = nil; + } + + if (!_touchEvent) { + _touchEvent = [[UITouchEvent alloc] initWithTouch:[self touchForEvent:theEvent]]; + _touchEvent.touchEventGesture = UITouchEventGestureNone; + _touchEvent.touch.tapCount = [theEvent clickCount]; + + [[UIApplication sharedApplication] sendEvent:_touchEvent]; } } - (void)mouseUp:(NSEvent *)theEvent { - [[UIApplication sharedApplication] _sendMouseNSEvent:theEvent fromScreen:_screen]; -} + if (_touchEvent && _touchEvent.touchEventGesture == UITouchEventGestureNone) { + _touchEvent.touch.phase = UITouchPhaseEnded; + [self updateTouchLocation:_touchEvent.touch withEvent:theEvent]; -- (void)mouseDragged:(NSEvent *)theEvent -{ - [[UIApplication sharedApplication] _sendMouseNSEvent:theEvent fromScreen:_screen]; -} - -- (void)rightMouseDown:(NSEvent *)theEvent -{ - [[UIApplication sharedApplication] _sendMouseNSEvent:theEvent fromScreen:_screen]; + [[UIApplication sharedApplication] sendEvent:_touchEvent]; + + [_touchEvent endTouchEvent]; + _touchEvent = nil; + } } -- (void)scrollWheel:(NSEvent *)theEvent +- (void)mouseDragged:(NSEvent *)theEvent { - [[UIApplication sharedApplication] _sendMouseNSEvent:theEvent fromScreen:_screen]; -} + if (_touchEvent && _touchEvent.touchEventGesture == UITouchEventGestureNone) { + _touchEvent.touch.phase = UITouchPhaseMoved; + [self updateTouchLocation:_touchEvent.touch withEvent:theEvent]; -- (void)mouseEntered:(NSEvent *)theEvent -{ - [[UIApplication sharedApplication] _sendMouseNSEvent:theEvent fromScreen:_screen]; + [[UIApplication sharedApplication] sendEvent:_touchEvent]; + } } -- (void)mouseExited:(NSEvent *)theEvent -{ - [[UIApplication sharedApplication] _sendMouseNSEvent:theEvent fromScreen:_screen]; -} +#pragma mark touch gestures - (void)beginGestureWithEvent:(NSEvent *)theEvent { - [[UIApplication sharedApplication] _sendMouseNSEvent:theEvent fromScreen:_screen]; + if (!_touchEvent) { + _touchEvent = [[UITouchEvent alloc] initWithTouch:[self touchForEvent:theEvent]]; + _touchEvent.touchEventGesture = UITouchEventGestureBegin; + + [[UIApplication sharedApplication] sendEvent:_touchEvent]; + } } - (void)endGestureWithEvent:(NSEvent *)theEvent { - [[UIApplication sharedApplication] _sendMouseNSEvent:theEvent fromScreen:_screen]; + if (_touchEvent && _touchEvent.touchEventGesture != UITouchEventGestureNone) { + _touchEvent.touch.phase = UITouchPhaseEnded; + [self updateTouchLocation:_touchEvent.touch withEvent:theEvent]; + + [[UIApplication sharedApplication] sendEvent:_touchEvent]; + + [_touchEvent endTouchEvent]; + _touchEvent = nil; + } } - (void)rotateWithEvent:(NSEvent *)theEvent { - [[UIApplication sharedApplication] _sendMouseNSEvent:theEvent fromScreen:_screen]; + if (_touchEvent && (_touchEvent.touchEventGesture == UITouchEventGestureBegin || _touchEvent.touchEventGesture == UITouchEventGestureRotate)) { + _touchEvent.touch.phase = UITouchPhaseMoved; + [self updateTouchLocation:_touchEvent.touch withEvent:theEvent]; + + _touchEvent.touchEventGesture = UITouchEventGestureRotate; + _touchEvent.rotation = [theEvent rotation]; + + [[UIApplication sharedApplication] sendEvent:_touchEvent]; + } } - (void)magnifyWithEvent:(NSEvent *)theEvent { - [[UIApplication sharedApplication] _sendMouseNSEvent:theEvent fromScreen:_screen]; + if (_touchEvent && (_touchEvent.touchEventGesture == UITouchEventGestureBegin || _touchEvent.touchEventGesture == UITouchEventGesturePinch)) { + _touchEvent.touch.phase = UITouchPhaseMoved; + [self updateTouchLocation:_touchEvent.touch withEvent:theEvent]; + + _touchEvent.touchEventGesture = UITouchEventGesturePinch; + _touchEvent.magnification = [theEvent magnification]; + + [[UIApplication sharedApplication] sendEvent:_touchEvent]; + } } - (void)swipeWithEvent:(NSEvent *)theEvent { - [[UIApplication sharedApplication] _sendMouseNSEvent:theEvent fromScreen:_screen]; + // it seems as if the swipe gesture actually is discrete as far as OSX is concerned and does not occur between gesture begin/end messages + // which is sort of different.. but.. here we go. :) As a result, I'll require there to not be an existing touchEvent in play before a + // swipe gesture is recognized. + + if (!_touchEvent) { + UITouchEvent *swipeEvent = [[UITouchEvent alloc] initWithTouch:[self touchForEvent:theEvent]]; + swipeEvent.touchEventGesture = UITouchEventGestureSwipe; + swipeEvent.translation = CGPointMake([theEvent deltaX], [theEvent deltaY]); + [[UIApplication sharedApplication] sendEvent:swipeEvent]; + [swipeEvent endTouchEvent]; + } } -- (void)_launchApplicationWithDefaultWindow:(UIWindow *)defaultWindow +#pragma mark scroll/pan gesture + +- (void)scrollWheel:(NSEvent *)theEvent { - UIApplication *app = [UIApplication sharedApplication]; - id appDelegate = app.delegate; + double dx, dy; - if ([appDelegate respondsToSelector:@selector(application:didFinishLaunchingWithOptions:)]) { - [appDelegate application:app didFinishLaunchingWithOptions:nil]; - } else if ([appDelegate respondsToSelector:@selector(applicationDidFinishLaunching:)]) { - [appDelegate applicationDidFinishLaunching:app]; - } - - [[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationDidFinishLaunchingNotification object:app]; + CGEventRef cgEvent = [theEvent CGEvent]; + const int64_t isContinious = CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventIsContinuous); - if ([appDelegate respondsToSelector:@selector(applicationDidBecomeActive:)]) { - [appDelegate applicationDidBecomeActive:app]; + if (isContinious == 0) { + CGEventSourceRef source = CGEventCreateSourceFromEvent(cgEvent); + double pixelsPerLine; + + if (source) { + pixelsPerLine = CGEventSourceGetPixelsPerLine(source); + CFRelease(source); + } else { + // docs often say things like, "the default is near 10" so it seems reasonable that if the source doesn't work + // for some reason to fetch the pixels per line, then 10 is probably a decent fallback value. :) + pixelsPerLine = 10; + } + + dx = CGEventGetDoubleValueField(cgEvent, kCGScrollWheelEventFixedPtDeltaAxis2) * pixelsPerLine; + dy = CGEventGetDoubleValueField(cgEvent, kCGScrollWheelEventFixedPtDeltaAxis1) * pixelsPerLine; + } else { + dx = CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis2); + dy = CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis1); } - [[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationDidBecomeActiveNotification object:app]; + CGPoint translation = CGPointMake(-dx, -dy); + + // if this happens within an actual OSX gesture sequence, it is a pan touch gesture event + // if it happens outside of a gesture, it is a normal mouse event instead + // if it somehow happens during any other touch sequence, ignore it (someone might be click-dragging with the mouse and also using a wheel) - defaultWindow.hidden = YES; + if (_touchEvent) { + if (_touchEvent.touchEventGesture == UITouchEventGestureBegin || _touchEvent.touchEventGesture == UITouchEventGesturePan) { + _touchEvent.touch.phase = UITouchPhaseMoved; + [self updateTouchLocation:_touchEvent.touch withEvent:theEvent]; + + _touchEvent.touchEventGesture = UITouchEventGesturePan; + _touchEvent.translation = translation; + + [[UIApplication sharedApplication] sendEvent:_touchEvent]; + } + } else { + UITouchEvent *mouseEvent = [[UITouchEvent alloc] initWithTouch:[self touchForEvent:theEvent]]; + mouseEvent.touchEventGesture = UITouchEventGestureScrollWheel; + mouseEvent.translation = translation; + [[UIApplication sharedApplication] sendEvent:mouseEvent]; + [mouseEvent endTouchEvent]; + } } -- (void)launchApplicationWithDelegate:(id)appDelegate afterDelay:(NSTimeInterval)delay +#pragma mark discrete mouse events + +- (void)rightMouseDown:(NSEvent *)theEvent { - [[UIApplication sharedApplication] setDelegate:appDelegate]; + if (!_touchEvent) { + UITouchEvent *mouseEvent = [[UITouchEvent alloc] initWithTouch:[self touchForEvent:theEvent]]; + mouseEvent.touchEventGesture = UITouchEventGestureRightClick; + mouseEvent.touch.tapCount = [theEvent clickCount]; + [[UIApplication sharedApplication] sendEvent:mouseEvent]; + [mouseEvent endTouchEvent]; + } +} - if (delay) { - UIImage *defaultImage = [UIImage imageNamed:@"Default-Landscape.png"]; - UIImageView *defaultImageView = [[[UIImageView alloc] initWithImage:defaultImage] autorelease]; - defaultImageView.contentMode = UIViewContentModeCenter; +- (void)mouseMoved:(NSEvent *)theEvent +{ + if (!_touchEvent) { + const NSPoint location = [self convertPoint:[theEvent locationInWindow] fromView:nil]; + UIView *currentView = [self hitTestUIView:location]; + UIView *previousView = _mouseMoveTouch.view; - UIWindow *defaultWindow = [(UIWindow *)[UIWindow alloc] initWithFrame:_screen.bounds]; - defaultWindow.userInteractionEnabled = NO; - defaultWindow.screen = _screen; - defaultWindow.backgroundColor = [UIColor blackColor]; // dunno.. - defaultWindow.opaque = YES; - [defaultWindow addSubview:defaultImageView]; - [defaultWindow makeKeyAndVisible]; - [self performSelector:@selector(_launchApplicationWithDefaultWindow:) withObject:defaultWindow afterDelay:delay]; - [defaultWindow release]; + _mouseMoveTouch.timestamp = [theEvent timestamp]; + _mouseMoveTouch.locationOnScreen = NSPointToCGPoint(location); + _mouseMoveTouch.phase = UITouchPhaseMoved; + + if (previousView && previousView != currentView) { + UITouchEvent *moveEvent = [[UITouchEvent alloc] initWithTouch:_mouseMoveTouch]; + moveEvent.touchEventGesture = UITouchEventGestureMouseMove; + [[UIApplication sharedApplication] sendEvent:moveEvent]; + [moveEvent endTouchEvent]; + + UITouchEvent *exitEvent = [[UITouchEvent alloc] initWithTouch:_mouseMoveTouch]; + exitEvent.touchEventGesture = UITouchEventGestureMouseExited; + [[UIApplication sharedApplication] sendEvent:exitEvent]; + [exitEvent endTouchEvent]; + } + + _mouseMoveTouch.view = currentView; + + if (currentView) { + if (currentView != previousView) { + UITouchEvent *enterEvent = [[UITouchEvent alloc] initWithTouch:_mouseMoveTouch]; + enterEvent.touchEventGesture = UITouchEventGestureMouseEntered; + [[UIApplication sharedApplication] sendEvent:enterEvent]; + [enterEvent endTouchEvent]; + } + + UITouchEvent *moveEvent = [[UITouchEvent alloc] initWithTouch:_mouseMoveTouch]; + moveEvent.touchEventGesture = UITouchEventGestureMouseMove; + [[UIApplication sharedApplication] sendEvent:moveEvent]; + [moveEvent endTouchEvent]; + } + } +} + +- (void)mouseEntered:(NSEvent *)theEvent +{ + [self mouseMoved:theEvent]; +} + +- (void)mouseExited:(NSEvent *)theEvent +{ + if (!_touchEvent) { + _mouseMoveTouch.phase = UITouchPhaseMoved; + [self updateTouchLocation:_mouseMoveTouch withEvent:theEvent]; + + UITouchEvent *moveEvent = [[UITouchEvent alloc] initWithTouch:_mouseMoveTouch]; + moveEvent.touchEventGesture = UITouchEventGestureMouseMove; + [[UIApplication sharedApplication] sendEvent:moveEvent]; + [moveEvent endTouchEvent]; + + UITouchEvent *exitEvent = [[UITouchEvent alloc] initWithTouch:_mouseMoveTouch]; + exitEvent.touchEventGesture = UITouchEventGestureMouseExited; + [[UIApplication sharedApplication] sendEvent:exitEvent]; + [exitEvent endTouchEvent]; + + _mouseMoveTouch.view = nil; + } +} + +#pragma keyboard events + +- (void)keyDown:(NSEvent *)theEvent +{ + UIKey *key = [[UIKey alloc] initWithNSEvent:theEvent]; + + // this is not the correct way to handle keys.. iOS 7 finally added a way to handle key commands + // but this was implemented well before that. for now, this gets what we want to happen to happen. + + if (key.action) { + [self doCommandBySelector:key.action]; } else { - [self _launchApplicationWithDefaultWindow:nil]; + [super keyDown:theEvent]; } } diff --git a/UIKit/Classes/UILabel.h b/UIKit/Classes/UILabel.h index 14673cf9..bd76adca 100644 --- a/UIKit/Classes/UILabel.h +++ b/UIKit/Classes/UILabel.h @@ -32,29 +32,15 @@ @class UIFont, UIColor; -@interface UILabel : UIView { -@private - NSString *_text; - UIFont *_font; - UIColor *_textColor; - UIColor *_highlightedTextColor; - UIColor *_shadowColor; - CGSize _shadowOffset; - UITextAlignment _textAlignment; - UILineBreakMode _lineBreakMode; - BOOL _enabled; - NSInteger _numberOfLines; - UIBaselineAdjustment _baselineAdjustment; - BOOL _adjustsFontSizeToFitWidth; - CGFloat _minimumFontSize; - BOOL _highlighted; -} +@interface UILabel : UIView +- (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines; +- (void)drawTextInRect:(CGRect)rect; @property (nonatomic, copy) NSString *text; -@property (nonatomic, retain) UIFont *font; -@property (nonatomic, retain) UIColor *textColor; -@property (nonatomic, retain) UIColor *highlightedTextColor; -@property (nonatomic, retain) UIColor *shadowColor; +@property (nonatomic, strong) UIFont *font; +@property (nonatomic, strong) UIColor *textColor; +@property (nonatomic, strong) UIColor *highlightedTextColor; +@property (nonatomic, strong) UIColor *shadowColor; @property (nonatomic) CGSize shadowOffset; @property (nonatomic) UITextAlignment textAlignment; @property (nonatomic) UILineBreakMode lineBreakMode; @@ -64,9 +50,4 @@ @property (nonatomic) BOOL adjustsFontSizeToFitWidth; // not implemented @property (nonatomic) CGFloat minimumFontSize; // not implemented @property (nonatomic, getter=isHighlighted) BOOL highlighted; - - -- (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines; -- (void)drawTextInRect:(CGRect)rect; - @end diff --git a/UIKit/Classes/UILabel.m b/UIKit/Classes/UILabel.m index e930cb1c..9c3d26d7 100644 --- a/UIKit/Classes/UILabel.m +++ b/UIKit/Classes/UILabel.m @@ -34,10 +34,6 @@ #import @implementation UILabel -@synthesize text=_text, font=_font, textColor=_textColor, textAlignment=_textAlignment, lineBreakMode=_lineBreakMode, enabled=_enabled; -@synthesize numberOfLines=_numberOfLines, shadowColor=_shadowColor, shadowOffset=_shadowOffset; -@synthesize baselineAdjustment=_baselineAdjustment, adjustsFontSizeToFitWidth=_adjustsFontSizeToFitWidth; -@synthesize highlightedTextColor=_highlightedTextColor, minimumFontSize=_minimumFontSize, highlighted=_highlighted; - (id)initWithFrame:(CGRect)frame { @@ -58,20 +54,10 @@ - (id)initWithFrame:(CGRect)frame return self; } -- (void)dealloc -{ - [_text release]; - [_font release]; - [_textColor release]; - [_shadowColor release]; - [_highlightedTextColor release]; - [super dealloc]; -} - (void)setText:(NSString *)newText { if (_text != newText) { - [_text release]; _text = [newText copy]; [self setNeedsDisplay]; } @@ -82,8 +68,7 @@ - (void)setFont:(UIFont *)newFont assert(newFont != nil); if (newFont != _font) { - [_font release]; - _font = [newFont retain]; + _font = newFont; [self setNeedsDisplay]; } } @@ -91,8 +76,7 @@ - (void)setFont:(UIFont *)newFont - (void)setTextColor:(UIColor *)newColor { if (newColor != _textColor) { - [_textColor release]; - _textColor = [newColor retain]; + _textColor = newColor; [self setNeedsDisplay]; } } @@ -100,8 +84,7 @@ - (void)setTextColor:(UIColor *)newColor - (void)setShadowColor:(UIColor *)newColor { if (newColor != _shadowColor) { - [_shadowColor release]; - _shadowColor = [newColor retain]; + _shadowColor = newColor; [self setNeedsDisplay]; } } diff --git a/UIKit/Classes/UILongPressGestureRecognizer.h b/UIKit/Classes/UILongPressGestureRecognizer.h index 52cfc1ca..be106126 100644 --- a/UIKit/Classes/UILongPressGestureRecognizer.h +++ b/UIKit/Classes/UILongPressGestureRecognizer.h @@ -34,19 +34,16 @@ // and it doesn't worry about allowableMovement and the other parameters that the regular long // press would normally need to be worried about. -@interface UILongPressGestureRecognizer : UIGestureRecognizer { -@private - CFTimeInterval _minimumPressDuration; - CGFloat _allowableMovement; - NSUInteger _numberOfTapsRequired; - NSInteger _numberOfTouchesRequired; - CGPoint _beginLocation; - BOOL _waiting; -} +// Note that technically the long press gesture is continuous but a right click is discrete in Chameleon, +// so this is sort of a hack as it immediately switches to UIGestureRecognizerStateBegan in that case and +// ends up never switching to UIGestureRecognizerStateEnded. Since the right click "gesture" is discrete, +// it ends up getting aborted/reset before that happens. So if you want your long press recognizer to work +// with right clicks, make sure you take action when the state switches to UIGestureRecognizerStateBegan +// instead of UIGestureRecognizerStateEnded. +@interface UILongPressGestureRecognizer : UIGestureRecognizer @property (nonatomic) CFTimeInterval minimumPressDuration; @property (nonatomic) CGFloat allowableMovement; @property (nonatomic) NSUInteger numberOfTapsRequired; @property (nonatomic) NSInteger numberOfTouchesRequired; - @end diff --git a/UIKit/Classes/UILongPressGestureRecognizer.m b/UIKit/Classes/UILongPressGestureRecognizer.m index 6eabf1a4..069af03c 100644 --- a/UIKit/Classes/UILongPressGestureRecognizer.m +++ b/UIKit/Classes/UILongPressGestureRecognizer.m @@ -29,8 +29,9 @@ #import "UILongPressGestureRecognizer.h" #import "UIGestureRecognizerSubclass.h" -#import "UITouch+UIPrivate.h" -#import "UIEvent.h" +#import "UITouchEvent.h" +#import "UITouch.h" +#import "UIApplicationAppKitIntegration.h" static CGFloat DistanceBetweenTwoPoints(CGPoint A, CGPoint B) { @@ -39,9 +40,10 @@ static CGFloat DistanceBetweenTwoPoints(CGPoint A, CGPoint B) return sqrtf((a*a) + (b*b)); } -@implementation UILongPressGestureRecognizer -@synthesize minimumPressDuration=_minimumPressDuration, allowableMovement=_allowableMovement, numberOfTapsRequired=_numberOfTapsRequired; -@synthesize numberOfTouchesRequired=_numberOfTouchesRequired; +@implementation UILongPressGestureRecognizer { + CGPoint _beginLocation; + BOOL _waiting; +} - (id)initWithTarget:(id)target action:(SEL)action { @@ -54,28 +56,12 @@ - (id)initWithTarget:(id)target action:(SEL)action return self; } -- (void)_discreteGestures:(NSSet *)touches withEvent:(UIEvent *)event -{ - UITouch *touch = [[event touchesForGestureRecognizer:self] anyObject]; - - if (self.state == UIGestureRecognizerStatePossible && [touch _gesture] == _UITouchDiscreteGestureRightClick) { - self.state = UIGestureRecognizerStateBegan; - [self performSelector:@selector(_endFakeContinuousGesture) withObject:nil afterDelay:0]; - } -} - -- (void)_endFakeContinuousGesture -{ - if (self.state == UIGestureRecognizerStateBegan || self.state == UIGestureRecognizerStateChanged) { - self.state = UIGestureRecognizerStateEnded; - } -} - - (void)_beginGesture { _waiting = NO; if (self.state == UIGestureRecognizerStatePossible) { self.state = UIGestureRecognizerStateBegan; + UIApplicationSendStationaryTouches(); } } @@ -83,32 +69,42 @@ - (void)_cancelWaiting { if (_waiting) { _waiting = NO; - [isa cancelPreviousPerformRequestsWithTarget:self selector:@selector(_beginGesture) object:nil]; + [[self class] cancelPreviousPerformRequestsWithTarget:self selector:@selector(_beginGesture) object:nil]; } } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { - UITouch *touch = [[event touchesForGestureRecognizer:self] anyObject]; - - if (!_waiting && self.state == UIGestureRecognizerStatePossible && touch.tapCount >= self.numberOfTapsRequired) { - _beginLocation = [touch locationInView:self.view]; - _waiting = YES; - [self performSelector:@selector(_beginGesture) withObject:nil afterDelay:self.minimumPressDuration]; + if ([event isKindOfClass:[UITouchEvent class]]) { + UITouchEvent *touchEvent = (UITouchEvent *)event; + + if (touchEvent.touchEventGesture == UITouchEventGestureRightClick) { + self.state = UIGestureRecognizerStateBegan; + } else if (touchEvent.touchEventGesture == UITouchEventGestureNone) { + if (!_waiting && self.state == UIGestureRecognizerStatePossible && touchEvent.touch.tapCount >= self.numberOfTapsRequired) { + _beginLocation = [touchEvent.touch locationInView:self.view]; + _waiting = YES; + [self performSelector:@selector(_beginGesture) withObject:nil afterDelay:self.minimumPressDuration]; + } + } else { + self.state = UIGestureRecognizerStateFailed; + } } } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { + UITouch *touch = [touches anyObject]; + const CGFloat distance = DistanceBetweenTwoPoints([touch locationInView:self.view], _beginLocation); + if (self.state == UIGestureRecognizerStateBegan || self.state == UIGestureRecognizerStateChanged) { - UITouch *touch = [[event touchesForGestureRecognizer:self] anyObject]; - const CGFloat distance = DistanceBetweenTwoPoints([touch locationInView:self.view], _beginLocation); - if (distance <= self.allowableMovement) { self.state = UIGestureRecognizerStateChanged; } else { self.state = UIGestureRecognizerStateCancelled; } + } else if (self.state == UIGestureRecognizerStatePossible && distance > self.allowableMovement) { + self.state = UIGestureRecognizerStateFailed; } } @@ -130,4 +126,10 @@ - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event } } +- (void)reset +{ + [self _cancelWaiting]; + [super reset]; +} + @end diff --git a/UIKit/Classes/UIMenuController.h b/UIKit/Classes/UIMenuController.h index db536736..5130390c 100644 --- a/UIKit/Classes/UIMenuController.h +++ b/UIKit/Classes/UIMenuController.h @@ -35,19 +35,9 @@ extern NSString *const UIMenuControllerWillHideMenuNotification; extern NSString *const UIMenuControllerDidHideMenuNotification; extern NSString *const UIMenuControllerMenuFrameDidChangeNotification; -@class UIView, UIWindow; - -@interface UIMenuController : NSObject { -@private - NSArray *_menuItems; - NSMutableArray *_enabledMenuItems; - id _menu; - CGRect _menuFrame; - CGPoint _menuLocation; - BOOL _rightAlignMenu; - UIWindow *_window; -} +@class UIView; +@interface UIMenuController : NSObject + (UIMenuController *)sharedMenuController; - (void)setMenuVisible:(BOOL)menuVisible animated:(BOOL)animated; @@ -62,5 +52,4 @@ extern NSString *const UIMenuControllerMenuFrameDidChangeNotification; // the menu is made visible. I have no intenstively tested what the real UIKit does in all the possible // situations. You have been warned. @property (nonatomic, readonly) CGRect menuFrame; - @end diff --git a/UIKit/Classes/UIMenuController.m b/UIKit/Classes/UIMenuController.m index d5c0637c..410f50d8 100644 --- a/UIKit/Classes/UIMenuController.m +++ b/UIKit/Classes/UIMenuController.m @@ -28,7 +28,7 @@ */ #import "UIMenuController.h" -#import "UIApplication+UIPrivate.h" +#import "UIApplicationAppKitIntegration.h" #import "UIWindow+UIPrivate.h" #import "UIScreenAppKitIntegration.h" #import "UIKitView.h" @@ -46,8 +46,13 @@ @interface UIMenuController () @end -@implementation UIMenuController -@synthesize menuItems=_menuItems, menuFrame=_menuFrame; +@implementation UIMenuController { + NSMutableArray *_enabledMenuItems; + NSMenu *_menu; + CGPoint _menuLocation; + BOOL _rightAlignMenu; + UIWindow *_window; +} + (UIMenuController *)sharedMenuController { @@ -61,12 +66,12 @@ + (NSArray *)_defaultMenuItems if (!items) { items = [[NSArray alloc] initWithObjects: - [[[UIMenuItem alloc] initWithTitle:@"Cut" action:@selector(cut:)] autorelease], - [[[UIMenuItem alloc] initWithTitle:@"Copy" action:@selector(copy:)] autorelease], - [[[UIMenuItem alloc] initWithTitle:@"Paste" action:@selector(paste:)] autorelease], - [[[UIMenuItem alloc] initWithTitle:@"Delete" action:@selector(delete:)] autorelease], - [[[UIMenuItem alloc] initWithTitle:@"Select" action:@selector(select:)] autorelease], - [[[UIMenuItem alloc] initWithTitle:@"Select All" action:@selector(selectAll:)] autorelease], + [[UIMenuItem alloc] initWithTitle:@"Cut" action:@selector(cut:)], + [[UIMenuItem alloc] initWithTitle:@"Copy" action:@selector(copy:)], + [[UIMenuItem alloc] initWithTitle:@"Paste" action:@selector(paste:)], + [[UIMenuItem alloc] initWithTitle:@"Delete" action:@selector(delete:)], + [[UIMenuItem alloc] initWithTitle:@"Select" action:@selector(select:)], + [[UIMenuItem alloc] initWithTitle:@"Select All" action:@selector(selectAll:)], nil]; } @@ -84,11 +89,7 @@ - (id)init - (void)dealloc { - [_menuItems release]; - [_enabledMenuItems release]; [_menu cancelTracking]; // this should never really happen since the controller is pretty much always a singleton, but... whatever. - [_menu release]; - [super dealloc]; } - (BOOL)isMenuVisible @@ -114,7 +115,6 @@ - (void)setMenuVisible:(BOOL)menuVisible animated:(BOOL)animated [theItem setTarget:self]; [theItem setRepresentedObject:item]; [_menu addItem:theItem]; - [theItem release]; } _menuFrame.size = NSSizeToCGSize([_menu size]); @@ -141,7 +141,6 @@ - (void)setMenuVisible:(BOOL)menuVisible animated:(BOOL)animated } else { [_menu cancelTrackingWithoutAnimation]; } - [_menu release]; _menu = nil; } } @@ -194,7 +193,7 @@ - (void)update { UIApplication *app = [UIApplication sharedApplication]; UIResponder *firstResponder = [app.keyWindow _firstResponder]; - NSArray *allItems = [[isa _defaultMenuItems] arrayByAddingObjectsFromArray:_menuItems]; + NSArray *allItems = [[[self class] _defaultMenuItems] arrayByAddingObjectsFromArray:_menuItems]; [_enabledMenuItems removeAllObjects]; @@ -210,10 +209,10 @@ - (void)update - (void)_presentMenu { if (_menu && _window) { - NSView *theNSView = [_window.screen UIKitView]; + NSView *theNSView = _window.screen.UIKitView; if (theNSView) { [_menu popUpMenuPositioningItem:nil atLocation:NSPointFromCGPoint(_menuFrame.origin) inView:theNSView]; - [[UIApplication sharedApplication] _cancelTouches]; + UIApplicationInterruptTouchesInView(nil); } } } @@ -244,7 +243,6 @@ - (void)_didSelectMenuItem:(NSMenuItem *)sender - (void)menuDidClose:(NSMenu *)menu { if (menu == _menu) { - [_menu release]; _menu = nil; } } diff --git a/UIKit/Classes/UIMenuItem.h b/UIKit/Classes/UIMenuItem.h index 81b35639..841a1dea 100644 --- a/UIKit/Classes/UIMenuItem.h +++ b/UIKit/Classes/UIMenuItem.h @@ -29,15 +29,9 @@ #import -@interface UIMenuItem : NSObject { -@private - SEL _action; - NSString *_title; -} - +@interface UIMenuItem : NSObject - (id)initWithTitle:(NSString *)title action:(SEL)action; @property SEL action; @property (copy) NSString *title; - @end diff --git a/UIKit/Classes/UIMenuItem.m b/UIKit/Classes/UIMenuItem.m index 7fbfe9a0..4ee3ab8c 100644 --- a/UIKit/Classes/UIMenuItem.m +++ b/UIKit/Classes/UIMenuItem.m @@ -30,7 +30,6 @@ #import "UIMenuItem.h" @implementation UIMenuItem -@synthesize action=_action, title=_title; - (id)initWithTitle:(NSString *)title action:(SEL)action { @@ -41,10 +40,4 @@ - (id)initWithTitle:(NSString *)title action:(SEL)action return self; } -- (void)dealloc -{ - [_title release]; - [super dealloc]; -} - @end diff --git a/UIKit/Classes/UIViewController+UIPrivate.h b/UIKit/Classes/UINSApplicationDelegate.h similarity index 88% rename from UIKit/Classes/UIViewController+UIPrivate.h rename to UIKit/Classes/UINSApplicationDelegate.h index 6b26e8bd..6f4addd5 100644 --- a/UIKit/Classes/UIViewController+UIPrivate.h +++ b/UIKit/Classes/UINSApplicationDelegate.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, The Iconfactory. All rights reserved. + * Copyright (c) 2013, The Iconfactory. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -27,8 +27,7 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#import "UIViewController.h" +#import -@interface UIViewController (UIPrivate) -- (void)_setParentViewController:(UIViewController *)controller; +@interface UINSApplicationDelegate : NSObject @end diff --git a/UIKit/Classes/UIViewBlockAnimationDelegate.h b/UIKit/Classes/UINSApplicationDelegate.m similarity index 60% rename from UIKit/Classes/UIViewBlockAnimationDelegate.h rename to UIKit/Classes/UINSApplicationDelegate.m index c410a6aa..c0a832de 100644 --- a/UIKit/Classes/UIViewBlockAnimationDelegate.h +++ b/UIKit/Classes/UINSApplicationDelegate.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, The Iconfactory. All rights reserved. + * Copyright (c) 2013, The Iconfactory. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -27,16 +27,27 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#import +#import "UINSApplicationDelegate.h" +#import "UIApplicationAppKitIntegration.h" -@interface UIViewBlockAnimationDelegate : NSObject { - void (^_completion)(BOOL finished); - BOOL _ignoreInteractionEvents; +@implementation UINSApplicationDelegate + +- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender +{ + return [[UIApplication sharedApplication] terminateApplicationBeforeDate:[NSDate dateWithTimeIntervalSinceNow:30]]; } -@property (nonatomic, copy) void (^completion)(BOOL finished); -@property (nonatomic, assign) BOOL ignoreInteractionEvents; +- (void)applicationDidFinishLaunching:(NSNotification *)notification +{ + [[NSAppleEventManager sharedAppleEventManager] setEventHandler:self andSelector:@selector(handleURLEvent:withReplyEvent:) forEventClass:kInternetEventClass andEventID:kAEGetURL]; +} -- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished; +- (void)handleURLEvent:(NSAppleEventDescriptor*)event withReplyEvent:(NSAppleEventDescriptor*)replyEvent +{ + NSURL* url = [NSURL URLWithString:[[event paramDescriptorForKeyword:keyDirectObject] stringValue]]; + UIApplication *app = [UIApplication sharedApplication]; + + [app.delegate application:app openURL:url sourceApplication:nil annotation:nil]; +} @end diff --git a/UIKit/Classes/UINSClipView.h b/UIKit/Classes/UINSClipView.h index 619c5cd1..5d30546c 100644 --- a/UIKit/Classes/UINSClipView.h +++ b/UIKit/Classes/UINSClipView.h @@ -31,9 +31,7 @@ @class UIScrollView; -@interface UINSClipView : NSClipView { - UIScrollView *parentView; -} +@interface UINSClipView : NSClipView - (id)initWithFrame:(NSRect)frame parentView:(UIScrollView *)aView; diff --git a/UIKit/Classes/UINSClipView.m b/UIKit/Classes/UINSClipView.m index f9100af0..53fa8e4a 100644 --- a/UIKit/Classes/UINSClipView.m +++ b/UIKit/Classes/UINSClipView.m @@ -30,18 +30,19 @@ #import "UINSClipView.h" #import "UIScrollView+UIPrivate.h" #import "UIWindow.h" -#import "UIScreen+UIPrivate.h" #import "UIScreenAppKitIntegration.h" #import "UIKitView.h" #import -@implementation UINSClipView +@implementation UINSClipView { + UIScrollView *_parentView; +} - (id)initWithFrame:(NSRect)frame parentView:(UIScrollView *)aView { if ((self=[super initWithFrame:frame])) { - parentView = aView; + _parentView = aView; [self setDrawsBackground:NO]; [self setCopiesOnScroll:NO]; [self setWantsLayer:YES]; @@ -62,13 +63,13 @@ - (BOOL)isOpaque - (void)scrollWheel:(NSEvent *)event { - if (parentView.scrollEnabled) { + if (_parentView.scrollEnabled) { NSPoint offset = [self bounds].origin; offset.x -= [event deltaX]; offset.y -= [event deltaY]; - [parentView _quickFlashScrollIndicators]; - [parentView setContentOffset:NSPointToCGPoint(offset) animated:NO]; + [_parentView _quickFlashScrollIndicators]; + [_parentView setContentOffset:NSPointToCGPoint(offset) animated:NO]; } else { [super scrollWheel:event]; } @@ -77,19 +78,19 @@ - (void)scrollWheel:(NSEvent *)event - (void)viewDidMoveToSuperview { [super viewDidMoveToSuperview]; - [parentView setNeedsLayout]; + [_parentView setNeedsLayout]; } - (void)viewWillDraw { - [parentView setNeedsLayout]; + [_parentView setNeedsLayout]; [super viewWillDraw]; } - (void)setFrame:(NSRect)frame { [super setFrame:frame]; - [parentView setNeedsLayout]; + [_parentView setNeedsLayout]; } // this is used to fake out AppKit when the UIView that "owns" this NSView's layer is actually *behind* another UIView. Since the NSViews are @@ -100,15 +101,11 @@ - (NSView *)hitTest:(NSPoint)aPoint NSView *hitNSView = [super hitTest:aPoint]; if (hitNSView) { - UIScreen *screen = parentView.window.screen; + UIScreen *screen = _parentView.window.screen; BOOL didHitUIView = NO; if (screen) { - if (![[screen UIKitView] isFlipped]) { - aPoint.y = screen.bounds.size.height - aPoint.y - 1; - } - - didHitUIView = (parentView == [screen _hitTest:NSPointToCGPoint(aPoint) event:nil]); + didHitUIView = (_parentView == [screen.UIKitView hitTestUIView:aPoint]); } if (!didHitUIView) { diff --git a/UIKit/Classes/UINavigationBar+UIPrivate.h b/UIKit/Classes/UINSResponderShim.h similarity index 54% rename from UIKit/Classes/UINavigationBar+UIPrivate.h rename to UIKit/Classes/UINSResponderShim.h index ebb74e6b..5b352572 100644 --- a/UIKit/Classes/UINavigationBar+UIPrivate.h +++ b/UIKit/Classes/UINSResponderShim.h @@ -1,11 +1,5 @@ -// -// UINavigationBar+UIPrivate.h -// UIKit -// -// Created by Jim Dovey on 11-03-22. -// /* - * Copyright (c) 2011, The Iconfactory. All rights reserved. + * Copyright (c) 2013, The Iconfactory. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -33,8 +27,26 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#import "UINavigationBar.h" +#import +#import + +// when the shim gets asked if it can respond to a method, it asks the delegate's responder if it can respond +// to it or not +// +// if the shim is sent a message that it needs to forward, it uses the delegate's responder as a starting point +// and walks the responder chain until it finds the responder to send it to. if it turns out the responder +// returned cannot respond to the selector, it eventually ends up with a doesNotRecognizeSelector exception. +// +// the shim also implements NSUserInterfaceValidations by sending it's responder -canPerformAction:withSender: +// messages for proposed actions. if the responder says it can perform the action, it validates. this allows +// native OSX menus and toolbars to reach down into the UIKit responder chain and enable/disable accordingly. + +@class UINSResponderShim, UIResponder; + +@protocol UINSResponderShimDelegate +- (UIResponder *)responderForResponderShim:(UINSResponderShim *)shim; +@end -@interface UINavigationBar (UIPrivate) -- (void)_updateNavigationItem:(UINavigationItem *)item animated:(BOOL)animated; -@end \ No newline at end of file +@interface UINSResponderShim : NSResponder +@property (nonatomic, assign) id delegate; +@end diff --git a/UIKit/Classes/UINSResponderShim.m b/UIKit/Classes/UINSResponderShim.m new file mode 100644 index 00000000..54f63d2d --- /dev/null +++ b/UIKit/Classes/UINSResponderShim.m @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2013, The Iconfactory. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of The Iconfactory nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE ICONFACTORY BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "UINSResponderShim.h" +#import "UIResponder.h" + +@implementation UINSResponderShim + +- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector withResponder:(UIResponder *)responder +{ + for (; responder != nil; responder = [responder nextResponder]) { + NSMethodSignature *sig = [responder methodSignatureForSelector:aSelector]; + + if (sig) { + return sig; + } + } + + return nil; +} + +- (BOOL)respondsToSelector:(SEL)aSelector +{ + if ([super respondsToSelector:aSelector]) { + return YES; + } + + return ([self methodSignatureForSelector:aSelector withResponder:[self.delegate responderForResponderShim:self]] != nil); +} + +- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector +{ + NSMethodSignature *sig = [super methodSignatureForSelector:aSelector]; + + if (!sig) { + sig = [self methodSignatureForSelector:aSelector withResponder:[self.delegate responderForResponderShim:self]]; + } + + return sig; +} + +- (void)forwardInvocation:(NSInvocation *)anInvocation +{ + for (UIResponder *responder = [self.delegate responderForResponderShim:self]; responder != nil; responder = [responder nextResponder]) { + if ([responder respondsToSelector:[anInvocation selector]]) { + [anInvocation invokeWithTarget:responder]; + return; + } + } + + [super forwardInvocation:anInvocation]; +} + +- (BOOL)validateUserInterfaceItem:(id < NSValidatedUserInterfaceItem >)anItem +{ + return [[self.delegate responderForResponderShim:self] canPerformAction:[anItem action] withSender:nil]; +} + +@end diff --git a/UIKit/Classes/UINavigationBar.h b/UIKit/Classes/UINavigationBar.h index f7b7d5a1..30be78a5 100644 --- a/UIKit/Classes/UINavigationBar.h +++ b/UIKit/Classes/UINavigationBar.h @@ -40,39 +40,21 @@ - (void)navigationBar:(UINavigationBar *)navigationBar didPopItem:(UINavigationItem *)item; @end -@interface UINavigationBar : UIView { -@private - NSMutableArray *_navStack; - UIColor *_tintColor; - __unsafe_unretained id _delegate; - - UIView *_leftView; - UIView *_centerView; - UIView *_rightView; - - struct { - unsigned shouldPushItem : 1; - unsigned didPushItem : 1; - unsigned shouldPopItem : 1; - unsigned didPopItem : 1; - } _delegateHas; - - // ideally this should share the same memory as the above flags structure... - struct { - unsigned reloadItem : 1; - unsigned __RESERVED__ : 31; - } _navigationBarFlags; -} - +@interface UINavigationBar : UIView - (void)setItems:(NSArray *)items animated:(BOOL)animated; - (void)pushNavigationItem:(UINavigationItem *)item animated:(BOOL)animated; - (UINavigationItem *)popNavigationItemAnimated:(BOOL)animated; -@property (nonatomic, assign) UIBarStyle barStyle; -@property (nonatomic, retain) UIColor *tintColor; -@property (nonatomic, readonly, retain) UINavigationItem *topItem; -@property (nonatomic, readonly, retain) UINavigationItem *backItem; -@property (nonatomic, copy) NSArray *items; -@property (nonatomic, assign) id delegate; +- (void)setBackgroundImage:(UIImage *)backgroundImage forBarMetrics:(UIBarMetrics)barMetrics; +- (UIImage *)backgroundImageForBarMetrics:(UIBarMetrics)barMetrics; +- (void)setTitleVerticalPositionAdjustment:(CGFloat)adjustment forBarMetrics:(UIBarMetrics)barMetrics; +- (CGFloat)titleVerticalPositionAdjustmentForBarMetrics:(UIBarMetrics)barMetrics; +@property (nonatomic, assign) id delegate; +@property (nonatomic, copy) NSArray *items; +@property (nonatomic, assign) UIBarStyle barStyle; +@property (nonatomic, readonly, strong) UINavigationItem *topItem; +@property (nonatomic, readonly, strong) UINavigationItem *backItem; +@property (nonatomic, strong) UIColor *tintColor; +@property (nonatomic, copy) NSDictionary *titleTextAttributes; @end diff --git a/UIKit/Classes/UINavigationBar.m b/UIKit/Classes/UINavigationBar.m index 226deeb4..e79a13f7 100644 --- a/UIKit/Classes/UINavigationBar.m +++ b/UIKit/Classes/UINavigationBar.m @@ -28,32 +28,43 @@ */ #import "UINavigationBar.h" -#import "UINavigationBar+UIPrivate.h" #import "UIGraphics.h" #import "UIColor.h" #import "UILabel.h" -#import "UINavigationItem.h" #import "UINavigationItem+UIPrivate.h" #import "UIFont.h" #import "UIImage+UIPrivate.h" #import "UIBarButtonItem.h" #import "UIButton.h" -static const UIEdgeInsets kButtonEdgeInsets = {0,0,0,0}; +static const UIEdgeInsets kButtonEdgeInsets = {2,2,2,2}; static const CGFloat kMinButtonWidth = 30; static const CGFloat kMaxButtonWidth = 200; static const CGFloat kMaxButtonHeight = 24; +static const CGFloat kBarHeight = 28; static const NSTimeInterval kAnimationDuration = 0.33; -typedef enum { +typedef NS_ENUM(NSInteger, _UINavigationBarTransition) { + _UINavigationBarTransitionNone = 0, _UINavigationBarTransitionPush, _UINavigationBarTransitionPop, - _UINavigationBarTransitionReload // explicitly tag reloads from changed UINavigationItem data -} _UINavigationBarTransition; +}; -@implementation UINavigationBar -@synthesize tintColor=_tintColor, delegate=_delegate, items=_navStack; +@implementation UINavigationBar { + NSMutableArray *_navStack; + + UIView *_leftView; + UIView *_centerView; + UIView *_rightView; + + struct { + unsigned shouldPushItem : 1; + unsigned didPushItem : 1; + unsigned shouldPopItem : 1; + unsigned didPopItem : 1; + } _delegateHas; +} + (void)_setBarButtonSize:(UIView *)view { @@ -64,14 +75,12 @@ + (void)_setBarButtonSize:(UIView *)view view.frame = frame; } -+ (UIButton *)_backButtonWithBarButtonItem:(UIBarButtonItem *)item ++ (UIButton *)_backButtonWithTitle:(NSString *)title { - if (!item) return nil; - UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom]; [backButton setBackgroundImage:[UIImage _backButtonImage] forState:UIControlStateNormal]; [backButton setBackgroundImage:[UIImage _highlightedBackButtonImage] forState:UIControlStateHighlighted]; - [backButton setTitle:item.title forState:UIControlStateNormal]; + [backButton setTitle:(title ?: @"Back") forState:UIControlStateNormal]; backButton.titleLabel.font = [UIFont systemFontOfSize:11]; backButton.contentEdgeInsets = UIEdgeInsetsMake(0,15,0,7); [backButton addTarget:nil action:@selector(_backButtonTapped:) forControlEvents:UIControlEventTouchUpInside]; @@ -102,19 +111,21 @@ + (UIView *)_viewWithBarButtonItem:(UIBarButtonItem *)item - (id)initWithFrame:(CGRect)frame { + frame.size.height = kBarHeight; + if ((self=[super initWithFrame:frame])) { _navStack = [[NSMutableArray alloc] init]; - self.tintColor = [UIColor colorWithRed:21/255.f green:21/255.f blue:25/255.f alpha:1]; + _barStyle = UIBarStyleDefault; + _tintColor = [UIColor colorWithRed:21/255.f green:21/255.f blue:25/255.f alpha:1]; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_navigationItemDidChange:) name:UINavigationItemDidChange object:nil]; } return self; } - (void)dealloc { - [self.topItem _setNavigationBar: nil]; - [_navStack release]; - [_tintColor release]; - [super dealloc]; + [[NSNotificationCenter defaultCenter] removeObserver:self]; } - (void)setDelegate:(id)newDelegate @@ -141,11 +152,6 @@ - (void)_backButtonTapped:(id)sender [self popNavigationItemAnimated:YES]; } -- (void)_removeAnimatedViews:(NSArray *)views -{ - [views makeObjectsPerformSelector:@selector(removeFromSuperview)]; -} - - (void)_setViewsWithTransition:(_UINavigationBarTransition)transition animated:(BOOL)animated { { @@ -164,12 +170,6 @@ - (void)_setViewsWithTransition:(_UINavigationBarTransition)transition animated: moveLeftBy *= -1.f; } - [UIView animateWithDuration:kAnimationDuration - animations:^(void) { - if (_leftView) _leftView.frame = CGRectOffset(_leftView.frame, moveLeftBy, 0); - if (_centerView) _centerView.frame = CGRectOffset(_centerView.frame, moveCenterBy, 0); - }]; - [UIView animateWithDuration:kAnimationDuration * 0.8 delay:kAnimationDuration * 0.2 options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionTransitionNone @@ -180,12 +180,17 @@ - (void)_setViewsWithTransition:(_UINavigationBarTransition)transition animated: } completion:NULL]; - [self performSelector:@selector(_removeAnimatedViews:) withObject:previousViews afterDelay:kAnimationDuration]; + [UIView animateWithDuration:kAnimationDuration + animations:^(void) { + if (_leftView) _leftView.frame = CGRectOffset(_leftView.frame, moveLeftBy, 0); + if (_centerView) _centerView.frame = CGRectOffset(_centerView.frame, moveCenterBy, 0); + } + completion:^(BOOL finished) { + [previousViews makeObjectsPerformSelector:@selector(removeFromSuperview)]; + }]; } else { - [self _removeAnimatedViews:previousViews]; + [previousViews makeObjectsPerformSelector:@selector(removeFromSuperview)]; } - - [previousViews release]; } UINavigationItem *topItem = self.topItem; @@ -193,17 +198,13 @@ - (void)_setViewsWithTransition:(_UINavigationBarTransition)transition animated: if (topItem) { UINavigationItem *backItem = self.backItem; - // update weak references - [backItem _setNavigationBar: nil]; - [topItem _setNavigationBar: self]; - CGRect leftFrame = CGRectZero; CGRect rightFrame = CGRectZero; if (backItem) { - _leftView = [isa _backButtonWithBarButtonItem:backItem.backBarButtonItem]; + _leftView = [[self class] _backButtonWithTitle:backItem.backBarButtonItem.title ?: backItem.title]; } else { - _leftView = [isa _viewWithBarButtonItem:topItem.leftBarButtonItem]; + _leftView = [[self class] _viewWithBarButtonItem:topItem.leftBarButtonItem]; } if (_leftView) { @@ -213,7 +214,7 @@ - (void)_setViewsWithTransition:(_UINavigationBarTransition)transition animated: [self addSubview:_leftView]; } - _rightView = [isa _viewWithBarButtonItem:topItem.rightBarButtonItem]; + _rightView = [[self class] _viewWithBarButtonItem:topItem.rightBarButtonItem]; if (_rightView) { _rightView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin; @@ -227,7 +228,7 @@ - (void)_setViewsWithTransition:(_UINavigationBarTransition)transition animated: _centerView = topItem.titleView; if (!_centerView) { - UILabel *titleLabel = [[[UILabel alloc] init] autorelease]; + UILabel *titleLabel = [[UILabel alloc] init]; titleLabel.text = topItem.title; titleLabel.textAlignment = UITextAlignmentCenter; titleLabel.backgroundColor = [UIColor clearColor]; @@ -236,10 +237,28 @@ - (void)_setViewsWithTransition:(_UINavigationBarTransition)transition animated: _centerView = titleLabel; } - const CGFloat centerPadding = MAX(leftFrame.size.width, rightFrame.size.width); + CGRect centerFrame = CGRectZero; + + centerFrame.origin.y = kButtonEdgeInsets.top; + centerFrame.size.height = kMaxButtonHeight; + + if (_leftView && _rightView) { + centerFrame.origin.x = CGRectGetMaxX(leftFrame) + kButtonEdgeInsets.left; + centerFrame.size.width = CGRectGetMinX(rightFrame) - kButtonEdgeInsets.right - centerFrame.origin.x; + } else if (_leftView) { + centerFrame.origin.x = CGRectGetMaxX(leftFrame) + kButtonEdgeInsets.left; + centerFrame.size.width = CGRectGetWidth(self.bounds) - centerFrame.origin.x - CGRectGetWidth(leftFrame) - kButtonEdgeInsets.right - kButtonEdgeInsets.right; + } else if (_rightView) { + centerFrame.origin.x = CGRectGetWidth(rightFrame) + kButtonEdgeInsets.left + kButtonEdgeInsets.left; + centerFrame.size.width = CGRectGetWidth(self.bounds) - centerFrame.origin.x - CGRectGetWidth(rightFrame) - kButtonEdgeInsets.right - kButtonEdgeInsets.right; + } else { + centerFrame.origin.x = kButtonEdgeInsets.left; + centerFrame.size.width = CGRectGetWidth(self.bounds) - kButtonEdgeInsets.left - kButtonEdgeInsets.right; + } + _centerView.autoresizingMask = UIViewAutoresizingFlexibleWidth; - _centerView.frame = CGRectMake(kButtonEdgeInsets.left+centerPadding,kButtonEdgeInsets.top,self.bounds.size.width-kButtonEdgeInsets.right-kButtonEdgeInsets.left-centerPadding-centerPadding,kMaxButtonHeight); - [self addSubview:_centerView]; + _centerView.frame = centerFrame; + [self insertSubview:_centerView atIndex:0]; if (animated) { CGFloat moveCenterBy = self.bounds.size.width - ((_centerView)? _centerView.frame.origin.x : 0); @@ -284,8 +303,7 @@ - (void)_setViewsWithTransition:(_UINavigationBarTransition)transition animated: - (void)setTintColor:(UIColor *)newColor { if (newColor != _tintColor) { - [_tintColor release]; - _tintColor = [newColor retain]; + _tintColor = newColor; [self setNeedsDisplay]; } } @@ -304,15 +322,6 @@ - (void)setItems:(NSArray *)items [self setItems:items animated:NO]; } -- (UIBarStyle)barStyle -{ - return UIBarStyleDefault; -} - -- (void)setBarStyle:(UIBarStyle)barStyle -{ -} - - (void)pushNavigationItem:(UINavigationItem *)item animated:(BOOL)animated { BOOL shouldPush = YES; @@ -343,7 +352,6 @@ - (UINavigationItem *)popNavigationItemAnimated:(BOOL)animated } if (shouldPop) { - [previousItem retain]; [_navStack removeObject:previousItem]; [self _setViewsWithTransition:_UINavigationBarTransitionPop animated:animated]; @@ -351,39 +359,21 @@ - (UINavigationItem *)popNavigationItemAnimated:(BOOL)animated [_delegate navigationBar:self didPopItem:previousItem]; } - return [previousItem autorelease]; + return previousItem; } } return nil; } -- (void)_updateNavigationItem:(UINavigationItem *)item animated:(BOOL)animated // ignored for now +- (void)_navigationItemDidChange:(NSNotification *)note { - // let's sanity-check that the item is supposed to be talking to us - if (item != self.topItem) { - [item _setNavigationBar:nil]; - return; - } - - // this is going to remove & re-add all the item views. Not ideal, but simple enough that it's worth profiling. - // next step is to add animation support-- that will require changing _setViewsWithTransition:animated: - // such that it won't perform any coordinate translations, only fade in/out - - // don't just fire the damned thing-- set a flag & mark as needing layout - if (_navigationBarFlags.reloadItem == 0) { - _navigationBarFlags.reloadItem = 1; - [self setNeedsLayout]; - } -} - -- (void)layoutSubviews -{ - [super layoutSubviews]; - - if (_navigationBarFlags.reloadItem) { - _navigationBarFlags.reloadItem = 0; - [self _setViewsWithTransition:_UINavigationBarTransitionReload animated:NO]; + if ([note object] == self.topItem || [note object] == self.backItem) { + // this is going to remove & re-add all the item views. Not ideal, but simple enough that it's worth profiling. + // next step is to add animation support-- that will require changing _setViewsWithTransition:animated: + // such that it won't perform any coordinate translations, only fade in/out + + [self _setViewsWithTransition:_UINavigationBarTransitionNone animated:NO]; } } @@ -395,8 +385,32 @@ - (void)drawRect:(CGRect)rect // so that it actually doesn "tint" the image instead of define it. That'd probably work better with the bottom line coloring and stuff, too, but // for now hardcoding stuff works well enough. - [_tintColor setFill]; + [self.tintColor setFill]; UIRectFill(bounds); } +- (void)setBackgroundImage:(UIImage *)backgroundImage forBarMetrics:(UIBarMetrics)barMetrics +{ +} + +- (UIImage *)backgroundImageForBarMetrics:(UIBarMetrics)barMetrics +{ + return nil; +} + +- (void)setTitleVerticalPositionAdjustment:(CGFloat)adjustment forBarMetrics:(UIBarMetrics)barMetrics +{ +} + +- (CGFloat)titleVerticalPositionAdjustmentForBarMetrics:(UIBarMetrics)barMetrics +{ + return 0; +} + +- (CGSize)sizeThatFits:(CGSize)size +{ + size.height = kBarHeight; + return size; +} + @end diff --git a/UIKit/Classes/UINavigationController.h b/UIKit/Classes/UINavigationController.h index fb9813c5..882a4a6f 100644 --- a/UIKit/Classes/UINavigationController.h +++ b/UIKit/Classes/UINavigationController.h @@ -37,51 +37,22 @@ - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated; @end -typedef enum { - _UINavigationControllerVisibleControllerTransitionNone = 0, - _UINavigationControllerVisibleControllerTransitionPushAnimated, - _UINavigationControllerVisibleControllerTransitionPopAnimated -} _UINavigationControllerVisibleControllerTransition; - -@interface UINavigationController : UIViewController { -@private - UINavigationBar *_navigationBar; - UIToolbar *_toolbar; - NSMutableArray *_viewControllers; - __unsafe_unretained id _delegate; - BOOL _toolbarHidden; - BOOL _navigationBarHidden; - - BOOL _visibleViewControllerNeedsUpdate; - _UINavigationControllerVisibleControllerTransition _visibleViewControllerTransition; - UIViewController *_visibleViewController; - - struct { - unsigned didShowViewController : 1; - unsigned willShowViewController : 1; - } _delegateHas; -} - +@interface UINavigationController : UIViewController - (id)initWithRootViewController:(UIViewController *)rootViewController; - - (void)setViewControllers:(NSArray *)newViewControllers animated:(BOOL)animated; - - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated; - (UIViewController *)popViewControllerAnimated:(BOOL)animated; - (NSArray *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated; - (NSArray *)popToRootViewControllerAnimated:(BOOL)animated; - - (void)setToolbarHidden:(BOOL)hidden animated:(BOOL)animated; // toolbar support is not really implemented yet - - (void)setNavigationBarHidden:(BOOL)navigationBarHidden animated:(BOOL)animated; // doesn't animate yet @property (nonatomic, copy) NSArray *viewControllers; -@property (nonatomic, readonly, retain) UIViewController *visibleViewController; +@property (nonatomic, readonly, strong) UIViewController *visibleViewController; @property (nonatomic, readonly) UINavigationBar *navigationBar; @property (nonatomic, readonly) UIToolbar *toolbar; // toolbar support is not really implemented yet @property (nonatomic, assign) id delegate; -@property (nonatomic, readonly, retain) UIViewController *topViewController; -@property (nonatomic,getter=isNavigationBarHidden) BOOL navigationBarHidden; -@property (nonatomic,getter=isToolbarHidden) BOOL toolbarHidden; // toolbar support is not really implemented yet - +@property (nonatomic, readonly, strong) UIViewController *topViewController; +@property (nonatomic, getter=isNavigationBarHidden) BOOL navigationBarHidden; +@property (nonatomic, getter=isToolbarHidden) BOOL toolbarHidden; // toolbar support is not really implemented yet @end diff --git a/UIKit/Classes/UINavigationController.m b/UIKit/Classes/UINavigationController.m index 0f333e79..fcd7a23c 100644 --- a/UIKit/Classes/UINavigationController.m +++ b/UIKit/Classes/UINavigationController.m @@ -28,36 +28,31 @@ */ #import "UINavigationController.h" -#import "UIViewController+UIPrivate.h" #import "UITabBarController.h" #import "UINavigationBar.h" #import "UIToolbar.h" -static const NSTimeInterval kAnimationDuration = 0.33; -static const CGFloat NavBarHeight = 28; -static const CGFloat ToolbarHeight = 28; +@interface UIViewController (UIPrivate) +- (void)_removeFromParentViewController; +@end -@implementation UINavigationController -@synthesize viewControllers=_viewControllers, delegate=_delegate, navigationBar=_navigationBar; -@synthesize toolbar=_toolbar, toolbarHidden=_toolbarHidden, navigationBarHidden=_navigationBarHidden; -@synthesize visibleViewController=_visibleViewController; +@implementation UINavigationController { + UIViewController *_visibleViewController; + BOOL _needsDeferredUpdate; + BOOL _isUpdating; + BOOL _toolbarHidden; +} -- (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)bundle +- (id)initWithRootViewController:(UIViewController *)rootViewController { - if ((self=[super initWithNibName:nibName bundle:bundle])) { - _viewControllers = [[NSMutableArray alloc] initWithCapacity:1]; - _navigationBar = [[UINavigationBar alloc] init]; + if ((self=[super initWithNibName:nil bundle:nil])) { + _navigationBar = [UINavigationBar new]; _navigationBar.delegate = self; - _toolbar = [[UIToolbar alloc] init]; + + _toolbar = [UIToolbar new]; _toolbarHidden = YES; - } - return self; -} -- (id)initWithRootViewController:(UIViewController *)rootViewController -{ - if ((self=[self initWithNibName:nil bundle:nil])) { - self.viewControllers = [NSArray arrayWithObject:rootViewController]; + self.viewControllers = @[rootViewController]; } return self; } @@ -65,178 +60,186 @@ - (id)initWithRootViewController:(UIViewController *)rootViewController - (void)dealloc { _navigationBar.delegate = nil; - [_viewControllers release]; - [_visibleViewController release]; - [_navigationBar release]; - [_toolbar release]; - [super dealloc]; } -- (void)setDelegate:(id)newDelegate +- (void)loadView { - _delegate = newDelegate; - _delegateHas.didShowViewController = [_delegate respondsToSelector:@selector(navigationController:didShowViewController:animated:)]; - _delegateHas.willShowViewController = [_delegate respondsToSelector:@selector(navigationController:willShowViewController:animated:)]; + self.view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)]; + self.view.clipsToBounds = YES; + + CGRect navbarRect; + CGRect contentRect; + CGRect toolbarRect; + [self _getNavbarRect:&navbarRect contentRect:&contentRect toolbarRect:&toolbarRect forBounds:self.view.bounds]; + + _toolbar.frame = toolbarRect; + _navigationBar.frame = navbarRect; + _visibleViewController.view.frame = contentRect; + + _toolbar.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin; + _navigationBar.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin; + _visibleViewController.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + + [self.view addSubview:_visibleViewController.view]; + [self.view addSubview:_navigationBar]; + [self.view addSubview:_toolbar]; } -- (CGRect)_navigationBarFrame +- (BOOL)shouldAutomaticallyForwardAppearanceMethods { - CGRect navBarFrame = self.view.bounds; - navBarFrame.size.height = NavBarHeight; - return navBarFrame; + return NO; } -- (CGRect)_toolbarFrame +- (void)_setNeedsDeferredUpdate { - CGRect toolbarRect = self.view.bounds; - toolbarRect.origin.y = toolbarRect.origin.y + toolbarRect.size.height - ToolbarHeight; - toolbarRect.size.height = ToolbarHeight; - return toolbarRect; + _needsDeferredUpdate = YES; + [self.view setNeedsLayout]; } -- (CGRect)_controllerFrameForTransition:(_UINavigationControllerVisibleControllerTransition)transition +- (void)_getNavbarRect:(CGRect *)navbarRect contentRect:(CGRect *)contentRect toolbarRect:(CGRect *)toolbarRect forBounds:(CGRect)bounds { - CGRect controllerFrame = self.view.bounds; + const CGRect navbar = CGRectMake(CGRectGetMinX(bounds), CGRectGetMinY(bounds), CGRectGetWidth(bounds), _navigationBar.frame.size.height); + const CGRect toolbar = CGRectMake(CGRectGetMinX(bounds), CGRectGetMaxY(bounds)-_toolbar.frame.size.height, CGRectGetWidth(bounds), _toolbar.frame.size.height); + CGRect content = bounds; - // adjust for the nav bar if (!self.navigationBarHidden) { - controllerFrame.origin.y += NavBarHeight; - controllerFrame.size.height -= NavBarHeight; + content.origin.y += CGRectGetHeight(navbar); + content.size.height -= CGRectGetHeight(navbar); } - - // adjust for toolbar (if there is one) + if (!self.toolbarHidden) { - controllerFrame.size.height -= ToolbarHeight; - } - - if (transition == _UINavigationControllerVisibleControllerTransitionPushAnimated) { - controllerFrame = CGRectOffset(controllerFrame, controllerFrame.size.width, 0); - } else if (transition == _UINavigationControllerVisibleControllerTransitionPopAnimated) { - controllerFrame = CGRectOffset(controllerFrame, -controllerFrame.size.width, 0); + content.size.height -= CGRectGetHeight(toolbar); } - return controllerFrame; + if (navbarRect) *navbarRect = navbar; + if (toolbarRect) *toolbarRect = toolbar; + if (contentRect) *contentRect = content; } -- (void)_setVisibleViewControllerNeedsUpdate +- (void)_updateVisibleViewController:(BOOL)animated { - // schedules a deferred method to run - if (!_visibleViewControllerNeedsUpdate) { - _visibleViewControllerNeedsUpdate = YES; - [self performSelector:@selector(_updateVisibleViewController) withObject:nil afterDelay:0]; - } -} - -- (void)_updateVisibleViewController -{ - // do some bookkeeping - _visibleViewControllerNeedsUpdate = NO; - UIViewController *topViewController = [self.topViewController retain]; + _isUpdating = YES; - // make sure the new top view is both loaded and set to appear in the correct place - topViewController.view.frame = [self _controllerFrameForTransition:_visibleViewControllerTransition]; + UIViewController *newVisibleViewController = self.topViewController; + UIViewController *oldVisibleViewController = _visibleViewController; - if (_visibleViewControllerTransition == _UINavigationControllerVisibleControllerTransitionNone) { - [_visibleViewController viewWillDisappear:NO]; - [topViewController viewWillAppear:NO]; - - if (_delegateHas.willShowViewController) { - [_delegate navigationController:self willShowViewController:topViewController animated:NO]; - } + const BOOL isPushing = (oldVisibleViewController.parentViewController != nil); + const BOOL wasToolbarHidden = self.toolbarHidden; + const BOOL wasNavbarHidden = self.navigationBarHidden; - [_visibleViewController.view removeFromSuperview]; - [self.view insertSubview:topViewController.view atIndex:0]; - - [_visibleViewController viewDidDisappear:NO]; - [topViewController viewDidAppear:NO]; + [oldVisibleViewController beginAppearanceTransition:NO animated:animated]; + [newVisibleViewController beginAppearanceTransition:YES animated:animated]; + + [self.delegate navigationController:self willShowViewController:newVisibleViewController animated:animated]; - if (_delegateHas.didShowViewController) { - [_delegate navigationController:self didShowViewController:topViewController animated:NO]; - } - } else { - const CGRect visibleControllerFrame = (_visibleViewControllerTransition == _UINavigationControllerVisibleControllerTransitionPushAnimated) - ? [self _controllerFrameForTransition:_UINavigationControllerVisibleControllerTransitionPopAnimated] - : [self _controllerFrameForTransition:_UINavigationControllerVisibleControllerTransitionPushAnimated]; + _visibleViewController = newVisibleViewController; - const CGRect topControllerFrame = [self _controllerFrameForTransition:_UINavigationControllerVisibleControllerTransitionNone]; - - UIViewController *previouslyVisibleViewController = _visibleViewController; - - [UIView animateWithDuration:kAnimationDuration - animations:^(void) { - previouslyVisibleViewController.view.frame = visibleControllerFrame; - topViewController.view.frame = topControllerFrame; - } - completion:^(BOOL finished) { - [previouslyVisibleViewController.view removeFromSuperview]; - [previouslyVisibleViewController viewDidDisappear:YES]; - [topViewController viewDidAppear:YES]; - - if (_delegateHas.didShowViewController) { - [_delegate navigationController:self didShowViewController:topViewController animated:YES]; - } - }]; - } - - [_visibleViewController release]; - _visibleViewController = [topViewController retain]; + const CGRect bounds = self.view.bounds; + + CGRect navbarRect; + CGRect contentRect; + CGRect toolbarRect; + [self _getNavbarRect:&navbarRect contentRect:&contentRect toolbarRect:&toolbarRect forBounds:bounds]; - [topViewController release]; -} + _toolbar.transform = CGAffineTransformIdentity; + _toolbar.frame = toolbarRect; -- (void)loadView -{ - self.view = [[[UIView alloc] initWithFrame:CGRectMake(0,0,320,480)] autorelease]; - self.view.clipsToBounds = YES; + _navigationBar.transform = CGAffineTransformIdentity; + _navigationBar.frame = navbarRect; + + newVisibleViewController.view.transform = CGAffineTransformIdentity; + newVisibleViewController.view.frame = contentRect; - UIViewController *viewController = self.visibleViewController; - viewController.view.frame = [self _controllerFrameForTransition:_UINavigationControllerVisibleControllerTransitionNone]; - viewController.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - [self.view addSubview:viewController.view]; + const CGAffineTransform inStartTransform = isPushing? CGAffineTransformMakeTranslation(bounds.size.width, 0) : CGAffineTransformMakeTranslation(-bounds.size.width, 0); + const CGAffineTransform outEndTransform = isPushing? CGAffineTransformMakeTranslation(-bounds.size.width, 0) : CGAffineTransformMakeTranslation(bounds.size.width, 0); + + CGAffineTransform toolbarEndTransform = CGAffineTransformIdentity; + CGAffineTransform navbarEndTransform = CGAffineTransformIdentity; - _navigationBar.frame = [self _navigationBarFrame]; - _navigationBar.autoresizingMask = UIViewAutoresizingFlexibleWidth; - _navigationBar.hidden = self.navigationBarHidden; - [self.view addSubview:_navigationBar]; + if (wasToolbarHidden && !_toolbarHidden) { + _toolbar.transform = inStartTransform; + _toolbar.hidden = NO; + _toolbar.items = newVisibleViewController.toolbarItems; + } else if (!wasToolbarHidden && _toolbarHidden) { + toolbarEndTransform = outEndTransform; + _toolbar.transform = CGAffineTransformIdentity; + _toolbar.hidden = NO; + } else { + [_toolbar setItems:newVisibleViewController.toolbarItems animated:animated]; + } - _toolbar.frame = [self _toolbarFrame]; - _toolbar.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin; - _toolbar.hidden = self.toolbarHidden; - [self.view addSubview:_toolbar]; -} + if (wasNavbarHidden && !_navigationBarHidden) { + _navigationBar.transform = inStartTransform; + _navigationBar.hidden = NO; + } else if (!wasNavbarHidden && _navigationBarHidden) { + navbarEndTransform = outEndTransform; + _navigationBar.transform = CGAffineTransformIdentity; + _navigationBar.hidden = NO; + } -- (void)viewWillAppear:(BOOL)animated -{ - [super viewWillAppear:animated]; - [self.visibleViewController viewWillAppear:animated]; -} + newVisibleViewController.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + [self.view insertSubview:newVisibleViewController.view atIndex:0]; + newVisibleViewController.view.transform = inStartTransform; + + [UIView animateWithDuration:animated? 0.33 : 0 + animations:^{ + oldVisibleViewController.view.transform = outEndTransform; + newVisibleViewController.view.transform = CGAffineTransformIdentity; + _toolbar.transform = toolbarEndTransform; + _navigationBar.transform = navbarEndTransform; + } + completion:^(BOOL finished) { + [oldVisibleViewController.view removeFromSuperview]; + + _toolbar.hidden = _toolbarHidden; + _navigationBar.hidden = _navigationBarHidden; + + [oldVisibleViewController endAppearanceTransition]; + [newVisibleViewController endAppearanceTransition]; + + // not sure if this is safe or not, really, but the real one must do something along these lines? + // it could perform this check in a variety of ways, though, with subtly different results so I'm + // not sure what's best. this seemed generally safest. + if (oldVisibleViewController && isPushing) { + [oldVisibleViewController didMoveToParentViewController:nil]; + } else { + [newVisibleViewController didMoveToParentViewController:self]; + } + + [self.delegate navigationController:self didShowViewController:newVisibleViewController animated:animated]; + }]; -- (void)viewDidAppear:(BOOL)animated -{ - [super viewDidAppear:animated]; - [self.visibleViewController viewDidAppear:animated]; + _isUpdating = NO; } -- (void)viewWillDisappear:(BOOL)animated +- (void)viewWillLayoutSubviews { - [super viewWillDisappear:animated]; - [self.visibleViewController viewWillDisappear:animated]; + if (_needsDeferredUpdate) { + _needsDeferredUpdate = NO; + [self _updateVisibleViewController:NO]; + } } -- (void)viewDidDisappear:(BOOL)animated +- (NSArray *)viewControllers { - [super viewDidDisappear:animated]; - [self.visibleViewController viewDidDisappear:animated]; + return [self.childViewControllers copy]; } - (void)setViewControllers:(NSArray *)newViewControllers animated:(BOOL)animated { assert([newViewControllers count] >= 1); - if (![newViewControllers isEqualToArray:_viewControllers]) { - // remove them all in bulk - [_viewControllers makeObjectsPerformSelector:@selector(_setParentViewController:) withObject:nil]; - [_viewControllers removeAllObjects]; + if (![newViewControllers isEqualToArray:self.viewControllers]) { + // find the controllers we used to have that we won't be using anymore + NSMutableArray *removeViewControllers = [self.viewControllers mutableCopy]; + [removeViewControllers removeObjectsInArray:newViewControllers]; + + // these view controllers are not in the new collection, so we must remove them as children + // I'm pretty sure the real UIKit doesn't attempt to be so clever.. + for (UIViewController *controller in removeViewControllers) { + [controller willMoveToParentViewController:nil]; + [controller removeFromParentViewController]; + } // reset the nav bar _navigationBar.items = nil; @@ -255,59 +258,60 @@ - (void)setViewControllers:(NSArray *)newViewControllers - (UIViewController *)topViewController { - return [_viewControllers lastObject]; + return [self.childViewControllers lastObject]; } - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated { assert(![viewController isKindOfClass:[UITabBarController class]]); - assert(![_viewControllers containsObject:viewController]); - - // override the animated property based on current state - animated = animated && _visibleViewController && self.view.window; - - // push on to controllers stack - [_viewControllers addObject:viewController]; - [_navigationBar pushNavigationItem:viewController.navigationItem animated:animated]; - - // take ownership responsibility - [viewController _setParentViewController:self]; - - // if animated and on screen, begin part of the transition immediately, specifically, get the new view - // on screen asap and tell the new controller it's about to be made visible in an animated fashion - if (animated) { - _visibleViewControllerTransition = _UINavigationControllerVisibleControllerTransitionPushAnimated; + assert(![self.viewControllers containsObject:viewController]); + assert(viewController.parentViewController == nil || viewController.parentViewController == self); - viewController.view.frame = [self _controllerFrameForTransition:_visibleViewControllerTransition]; + // this logic matches with the cleverness in setViewControllers which the real UIKit probably doens't do + // and probably isn't necessary :) + if (viewController.parentViewController != self) { - [_visibleViewController viewWillDisappear:YES]; - [viewController viewWillAppear:YES]; - - if (_delegateHas.willShowViewController) { - [_delegate navigationController:self willShowViewController:viewController animated:YES]; - } - - [self.view insertSubview:viewController.view atIndex:0]; - } + // note that -addChildViewController will call -willMoveToParentViewController: and that + // there's no matching call to -didMoveToParentViewController: here which is usually + // required. In my tests, it seems like the real UIKit hardly ever correctly calls the + // -didMoveToParentViewController: method on it's navigation controller children which + // makes me slightly crazy inside. I blame legacy (since child containment wasn't added + // until iOS 5), but it's still stupid. + [self addChildViewController:viewController]; + } - [self _setVisibleViewControllerNeedsUpdate]; + if (animated) { + [self _updateVisibleViewController:animated]; + } else { + [self _setNeedsDeferredUpdate]; + } + + [_navigationBar pushNavigationItem:viewController.navigationItem animated:animated]; } - (UIViewController *)popViewControllerAnimated:(BOOL)animated { // don't allow popping the rootViewController - if ([_viewControllers count] <= 1) { + if ([self.viewControllers count] <= 1) { return nil; } - - UIViewController *formerTopViewController = [self.topViewController retain]; - - // adjust the animate property - animated = animated && self.view.window; - // pop the controller stack - [_viewControllers removeLastObject]; + UIViewController *formerTopViewController = self.topViewController; + // the real thing seems to only bother calling -willMoveToParentViewController: + // here if the popped controller is the currently visible one. I have no idea why. + // if you pop several in a row, the ones buried in the stack don't seem to get called. + // it is possible that the real implementation is fancier and tracks if a child has + // been fully ever added or not before making this determination, but I haven't + // tried to test for that case yet since this was an easy thing to do to replicate + // the real world behavior I was seeing at the time of this writing. + if (formerTopViewController == _visibleViewController) { + [formerTopViewController willMoveToParentViewController:nil]; + } + + // the real thing seems to cheat here and removes the parent immediately even if animated + [formerTopViewController _removeFromParentViewController]; + // pop the nav bar - note that it's setting the delegate to nil and back because we use the nav bar's // -navigationBar:shouldPopItem: delegate method to determine when the user clicks the back button // but that method is also called when we do an animated pop like this, so this works around the cycle. @@ -316,49 +320,20 @@ - (UIViewController *)popViewControllerAnimated:(BOOL)animated [_navigationBar popNavigationItemAnimated:animated]; _navigationBar.delegate = self; - // give up ownership of the view controller - [formerTopViewController _setParentViewController:nil]; - - // if animated, begin part of the transition immediately, specifically, get the new top view on screen asap - // and tell the old visible controller it's about to be disappeared in an animated fashion - if (animated && self.view.window) { - // note the new top here so we don't have to use the accessor method all the time - UIViewController *topController = [self.topViewController retain]; - - _visibleViewControllerTransition = _UINavigationControllerVisibleControllerTransitionPopAnimated; - - // if we never updated the visible controller, we need to add the formerTopViewController - // on to the screen so we can see it disappear since we're attempting to animate this - if (!_visibleViewController) { - _visibleViewController = [formerTopViewController retain]; - _visibleViewController.view.frame = [self _controllerFrameForTransition:_UINavigationControllerVisibleControllerTransitionNone]; - [self.view insertSubview:_visibleViewController.view atIndex:0]; - } - - topController.view.frame = [self _controllerFrameForTransition:_visibleViewControllerTransition]; - - [_visibleViewController viewWillDisappear:YES]; - [topController viewWillAppear:YES]; - - if (_delegateHas.willShowViewController) { - [_delegate navigationController:self willShowViewController:topController animated:YES]; - } - - [self.view insertSubview:topController.view atIndex:0]; - - [topController release]; - } - - [self _setVisibleViewControllerNeedsUpdate]; + if (animated) { + [self _updateVisibleViewController:animated]; + } else { + [self _setNeedsDeferredUpdate]; + } - return [formerTopViewController autorelease]; + return formerTopViewController; } - (NSArray *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated { NSMutableArray *popped = [[NSMutableArray alloc] init]; - if ([_viewControllers containsObject:viewController]) { + if ([self.viewControllers containsObject:viewController]) { while (self.topViewController != viewController) { UIViewController *poppedController = [self popViewControllerAnimated:animated]; if (poppedController) { @@ -369,12 +344,12 @@ - (NSArray *)popToViewController:(UIViewController *)viewController animated:(BO } } - return [popped autorelease]; + return popped; } - (NSArray *)popToRootViewControllerAnimated:(BOOL)animated { - return [self popToViewController:[_viewControllers objectAtIndex:0] animated:animated]; + return [self popToViewController:[self.viewControllers objectAtIndex:0] animated:animated]; } - (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item @@ -385,10 +360,34 @@ - (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigati return NO; } -- (void)setToolbarHidden:(BOOL)hidden animated:(BOOL)animated +- (void)setToolbarHidden:(BOOL)hide animated:(BOOL)animated { - _toolbarHidden = hidden; - _toolbar.hidden = hidden; + if (hide != _toolbarHidden) { + _toolbarHidden = hide; + + if (animated && !_isUpdating) { + CGAffineTransform startTransform = hide? CGAffineTransformIdentity : CGAffineTransformMakeTranslation(0, _toolbar.frame.size.height); + CGAffineTransform endTransform = hide? CGAffineTransformMakeTranslation(0, _toolbar.frame.size.height) : CGAffineTransformIdentity; + + CGRect contentRect; + [self _getNavbarRect:NULL contentRect:&contentRect toolbarRect:NULL forBounds:self.view.bounds]; + + _toolbar.transform = startTransform; + _toolbar.hidden = NO; + + [UIView animateWithDuration:0.15 + animations:^{ + _visibleViewController.view.frame = contentRect; + _toolbar.transform = endTransform; + } + completion:^(BOOL finished) { + _toolbar.transform = CGAffineTransformIdentity; + _toolbar.hidden = _toolbarHidden; + }]; + } else { + _toolbar.hidden = _toolbarHidden; + } + } } - (void)setToolbarHidden:(BOOL)hidden @@ -411,13 +410,34 @@ - (CGSize)contentSizeForViewInPopover return self.topViewController.contentSizeForViewInPopover; } -- (void)setNavigationBarHidden:(BOOL)navigationBarHidden animated:(BOOL)animated; // doesn't yet animate +- (void)setNavigationBarHidden:(BOOL)hide animated:(BOOL)animated; { - _navigationBarHidden = navigationBarHidden; - - // this shouldn't just hide it, but should animate it out of view (if animated==YES) and then adjust the layout - // so the main view fills the whole space, etc. - _navigationBar.hidden = navigationBarHidden; + if (hide != _navigationBarHidden) { + _navigationBarHidden = hide; + + if (animated && !_isUpdating) { + CGAffineTransform startTransform = hide? CGAffineTransformIdentity : CGAffineTransformMakeTranslation(0, -_navigationBar.frame.size.height); + CGAffineTransform endTransform = hide? CGAffineTransformMakeTranslation(0, -_navigationBar.frame.size.height) : CGAffineTransformIdentity; + + CGRect contentRect; + [self _getNavbarRect:NULL contentRect:&contentRect toolbarRect:NULL forBounds:self.view.bounds]; + + _navigationBar.transform = startTransform; + _navigationBar.hidden = NO; + + [UIView animateWithDuration:0.15 + animations:^{ + _visibleViewController.view.frame = contentRect; + _navigationBar.transform = endTransform; + } + completion:^(BOOL finished) { + _navigationBar.transform = CGAffineTransformIdentity; + _navigationBar.hidden = _navigationBarHidden; + }]; + } else { + _navigationBar.hidden = _navigationBarHidden; + } + } } - (void)setNavigationBarHidden:(BOOL)navigationBarHidden @@ -425,4 +445,9 @@ - (void)setNavigationBarHidden:(BOOL)navigationBarHidden [self setNavigationBarHidden:navigationBarHidden animated:NO]; } +- (UIViewController *)defaultResponderChildViewController +{ + return self.topViewController; +} + @end diff --git a/UIKit/Classes/UINavigationItem+UIPrivate.h b/UIKit/Classes/UINavigationItem+UIPrivate.h index 43e80e94..884865a7 100644 --- a/UIKit/Classes/UINavigationItem+UIPrivate.h +++ b/UIKit/Classes/UINavigationItem+UIPrivate.h @@ -1,11 +1,5 @@ -// -// UINavigationItem+UIPrivate.h -// UIKit -// -// Created by Jim Dovey on 11-03-22. -// /* - * Copyright (c) 2011, The Iconfactory. All rights reserved. + * Copyright (c) 2013, The Iconfactory. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -35,9 +29,4 @@ #import "UINavigationItem.h" -@class UINavigationBar; - -@interface UINavigationItem (UIPrivate) -- (void)_setNavigationBar:(UINavigationBar *)navigationBar; -- (UINavigationBar *)_navigationBar; -@end +extern NSString *const UINavigationItemDidChange; diff --git a/UIKit/Classes/UINavigationItem.h b/UIKit/Classes/UINavigationItem.h index 60a91fef..bf797046 100644 --- a/UIKit/Classes/UINavigationItem.h +++ b/UIKit/Classes/UINavigationItem.h @@ -29,20 +29,9 @@ #import -@class UIBarButtonItem, UIView, UINavigationBar; - -@interface UINavigationItem : NSObject { -@private - NSString *_title; - NSString *_prompt; - UIBarButtonItem *_backBarButtonItem; - UIBarButtonItem *_leftBarButtonItem; - UIBarButtonItem *_rightBarButtonItem; - UIView *_titleView; - BOOL _hidesBackButton; - UINavigationBar *_navigationBar; -} +@class UIBarButtonItem, UIView; +@interface UINavigationItem : NSObject - (id)initWithTitle:(NSString *)title; - (void)setLeftBarButtonItem:(UIBarButtonItem *)item animated:(BOOL)animated; - (void)setRightBarButtonItem:(UIBarButtonItem *)item animated:(BOOL)animated; @@ -50,10 +39,9 @@ @property (nonatomic, copy) NSString *title; @property (nonatomic, copy) NSString *prompt; -@property (nonatomic, retain) UIBarButtonItem *backBarButtonItem; -@property (nonatomic, retain) UIBarButtonItem *leftBarButtonItem; -@property (nonatomic, retain) UIBarButtonItem *rightBarButtonItem; -@property (nonatomic, retain) UIView *titleView; +@property (nonatomic, strong) UIBarButtonItem *backBarButtonItem; +@property (nonatomic, strong) UIBarButtonItem *leftBarButtonItem; +@property (nonatomic, strong) UIBarButtonItem *rightBarButtonItem; +@property (nonatomic, strong) UIView *titleView; @property (nonatomic, assign) BOOL hidesBackButton; - @end diff --git a/UIKit/Classes/UINavigationItem.m b/UIKit/Classes/UINavigationItem.m index 13157ea2..38ab3f15 100644 --- a/UIKit/Classes/UINavigationItem.m +++ b/UIKit/Classes/UINavigationItem.m @@ -27,95 +27,33 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#import "UINavigationItem.h" -#import "UIBarButtonItem.h" #import "UINavigationItem+UIPrivate.h" -#import "UINavigationBar.h" -#import "UINavigationBar+UIPrivate.h" -static void * const UINavigationItemContext = "UINavigationItemContext"; +NSString *const UINavigationItemDidChange = @"UINavigationItemDidChange"; @implementation UINavigationItem -@synthesize title=_title, rightBarButtonItem=_rightBarButtonItem, titleView=_titleView, hidesBackButton=_hidesBackButton; -@synthesize leftBarButtonItem=_leftBarButtonItem, backBarButtonItem=_backBarButtonItem, prompt=_prompt; - -+ (NSSet *)_keyPathsTriggeringUIUpdates -{ - static NSSet * __keyPaths = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - __keyPaths = [[NSSet alloc] initWithObjects:@"title", @"prompt", @"backBarButtonItem", @"leftBarButtonItem", @"rightBarButtonItem", @"titleView", @"hidesBackButton", nil]; - }); - return __keyPaths; -} - (id)initWithTitle:(NSString *)theTitle { if ((self=[super init])) { - self.title = theTitle; + _title = [theTitle copy]; } return self; } -- (void)dealloc -{ - // removes automatic observation - [self _setNavigationBar:nil]; - - [_backBarButtonItem release]; - [_leftBarButtonItem release]; - [_rightBarButtonItem release]; - [_title release]; - [_titleView release]; - [_prompt release]; - [super dealloc]; -} - -- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context +- (void)setBackBarButtonItem:(UIBarButtonItem *)backBarButtonItem { - if (context != UINavigationItemContext) { - if ([[self superclass] instancesRespondToSelector:_cmd]) - [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; - return; + if (_backBarButtonItem != backBarButtonItem) { + _backBarButtonItem = backBarButtonItem; + [[NSNotificationCenter defaultCenter] postNotificationName:UINavigationItemDidChange object:self]; } - - [[self _navigationBar] _updateNavigationItem:self animated:NO]; -} - -- (void)_setNavigationBar:(UINavigationBar *)navigationBar -{ - // weak reference - if (_navigationBar == navigationBar) - return; - - if (_navigationBar != nil && navigationBar == nil) { - // remove observation - for (NSString * keyPath in [isa _keyPathsTriggeringUIUpdates]) { - [self removeObserver:self forKeyPath:keyPath]; - } - } - else if (navigationBar != nil) { - // observe property changes to notify UI element - for (NSString * keyPath in [isa _keyPathsTriggeringUIUpdates]) { - [self addObserver:self forKeyPath:keyPath options:NSKeyValueObservingOptionNew context:UINavigationItemContext]; - } - } - - _navigationBar = navigationBar; -} - -- (UINavigationBar *)_navigationBar -{ - return _navigationBar; } - (void)setLeftBarButtonItem:(UIBarButtonItem *)item animated:(BOOL)animated { - if (item != _leftBarButtonItem) { - [self willChangeValueForKey: @"leftBarButtonItem"]; - [_leftBarButtonItem release]; - _leftBarButtonItem = [item retain]; - [self didChangeValueForKey: @"leftBarButtonItem"]; + if (_leftBarButtonItem != item) { + _leftBarButtonItem = item; + [[NSNotificationCenter defaultCenter] postNotificationName:UINavigationItemDidChange object:self]; } } @@ -126,11 +64,9 @@ - (void)setLeftBarButtonItem:(UIBarButtonItem *)item - (void)setRightBarButtonItem:(UIBarButtonItem *)item animated:(BOOL)animated { - if (item != _rightBarButtonItem) { - [self willChangeValueForKey: @"rightBarButtonItem"]; - [_rightBarButtonItem release]; - _rightBarButtonItem = [item retain]; - [self didChangeValueForKey: @"rightBarButtonItem"]; + if (_rightBarButtonItem != item) { + _rightBarButtonItem = item; + [[NSNotificationCenter defaultCenter] postNotificationName:UINavigationItemDidChange object:self]; } } @@ -141,9 +77,10 @@ - (void)setRightBarButtonItem:(UIBarButtonItem *)item - (void)setHidesBackButton:(BOOL)hidesBackButton animated:(BOOL)animated { - [self willChangeValueForKey: @"hidesBackButton"]; - _hidesBackButton = hidesBackButton; - [self didChangeValueForKey: @"hidesBackButton"]; + if (_hidesBackButton != hidesBackButton) { + _hidesBackButton = hidesBackButton; + [[NSNotificationCenter defaultCenter] postNotificationName:UINavigationItemDidChange object:self]; + } } - (void)setHidesBackButton:(BOOL)hidesBackButton @@ -151,12 +88,27 @@ - (void)setHidesBackButton:(BOOL)hidesBackButton [self setHidesBackButton:hidesBackButton animated:NO]; } -- (UIBarButtonItem *)backBarButtonItem +- (void)setTitle:(NSString *)title +{ + if (![_title isEqual:title]) { + _title = [title copy]; + [[NSNotificationCenter defaultCenter] postNotificationName:UINavigationItemDidChange object:self]; + } +} + +- (void)setPrompt:(NSString *)prompt +{ + if (![_prompt isEqual:prompt]) { + _prompt = [prompt copy]; + [[NSNotificationCenter defaultCenter] postNotificationName:UINavigationItemDidChange object:self]; + } +} + +- (void)setTitleView:(UIView *)titleView { - if (_backBarButtonItem) { - return _backBarButtonItem; - } else { - return [[[UIBarButtonItem alloc] initWithTitle:(self.title ?: @"Back") style:UIBarButtonItemStylePlain target:nil action:nil] autorelease]; + if (_titleView != titleView) { + _titleView = titleView; + [[NSNotificationCenter defaultCenter] postNotificationName:UINavigationItemDidChange object:self]; } } diff --git a/UIKit/Classes/UINinePartImage.h b/UIKit/Classes/UINinePartImage.h index 3f650105..d8dd9097 100644 --- a/UIKit/Classes/UINinePartImage.h +++ b/UIKit/Classes/UINinePartImage.h @@ -29,11 +29,7 @@ #import "UIImage+UIPrivate.h" -@interface UINinePartImage : UIImage { -@private - NSInteger _leftCapWidth; - NSInteger _topCapHeight; -} +@interface UINinePartImage : UIImage - (id)initWithRepresentations:(NSArray *)reps leftCapWidth:(NSInteger)leftCapWidth topCapHeight:(NSInteger)topCapHeight; diff --git a/UIKit/Classes/UINinePartImage.m b/UIKit/Classes/UINinePartImage.m index ada6e5ef..1170accf 100644 --- a/UIKit/Classes/UINinePartImage.m +++ b/UIKit/Classes/UINinePartImage.m @@ -30,7 +30,10 @@ #import "UINinePartImage.h" #import "UIImageRep.h" -@implementation UINinePartImage +@implementation UINinePartImage { + NSInteger _leftCapWidth; + NSInteger _topCapHeight; +} - (id)initWithRepresentations:(NSArray *)reps leftCapWidth:(NSInteger)leftCapWidth topCapHeight:(NSInteger)topCapHeight { diff --git a/UIKit/Classes/UIPageControl.h b/UIKit/Classes/UIPageControl.h index b47dc48b..b868e19a 100644 --- a/UIKit/Classes/UIPageControl.h +++ b/UIKit/Classes/UIPageControl.h @@ -30,12 +30,7 @@ #import "UIControl.h" -@interface UIPageControl : UIControl { - NSInteger _currentPage; - NSInteger _numberOfPages; -} - +@interface UIPageControl : UIControl @property (nonatomic) NSInteger currentPage; @property (nonatomic) NSInteger numberOfPages; - @end diff --git a/UIKit/Classes/UIPageControl.m b/UIKit/Classes/UIPageControl.m index d0b4eadf..e13ef0a1 100644 --- a/UIKit/Classes/UIPageControl.m +++ b/UIKit/Classes/UIPageControl.m @@ -30,7 +30,6 @@ #import "UIPageControl.h" @implementation UIPageControl -@synthesize currentPage=_currentPage, numberOfPages=_numberOfPages; - (void)setCurrentPage:(NSInteger)page { diff --git a/UIKit/Classes/UIPanGestureRecognizer.h b/UIKit/Classes/UIPanGestureRecognizer.h index 40a70dc8..92708d7c 100644 --- a/UIKit/Classes/UIPanGestureRecognizer.h +++ b/UIKit/Classes/UIPanGestureRecognizer.h @@ -38,19 +38,11 @@ // for UIScrollView but it certainly might make using the gesture recognizer in // a standalone setting somewhat more annoying. We'll have to see how it plays out. -@interface UIPanGestureRecognizer : UIGestureRecognizer { - NSUInteger _maximumNumberOfTouches; - NSUInteger _minimumNumberOfTouches; - CGPoint _translation; - CGPoint _velocity; - NSTimeInterval _lastMovementTime; -} - +@interface UIPanGestureRecognizer : UIGestureRecognizer - (CGPoint)translationInView:(UIView *)view; - (void)setTranslation:(CGPoint)translation inView:(UIView *)view; - (CGPoint)velocityInView:(UIView *)view; @property (nonatomic) NSUInteger maximumNumberOfTouches; @property (nonatomic) NSUInteger minimumNumberOfTouches; - @end diff --git a/UIKit/Classes/UIPanGestureRecognizer.m b/UIKit/Classes/UIPanGestureRecognizer.m index 98f2f20b..641f9014 100644 --- a/UIKit/Classes/UIPanGestureRecognizer.m +++ b/UIKit/Classes/UIPanGestureRecognizer.m @@ -29,22 +29,15 @@ #import "UIPanGestureRecognizer.h" #import "UIGestureRecognizerSubclass.h" -#import "UITouch+UIPrivate.h" -#import "UIEvent.h" +#import "UITouchEvent.h" +#import "UITouch.h" -static UITouch *PanTouch(NSSet *touches) -{ - for (UITouch *touch in touches) { - if ([touch _gesture] == _UITouchGesturePan) { - return touch; - } - } - return nil; +@implementation UIPanGestureRecognizer { + CGPoint _translation; + CGPoint _velocity; + NSTimeInterval _lastMovementTime; } -@implementation UIPanGestureRecognizer -@synthesize maximumNumberOfTouches=_maximumNumberOfTouches, minimumNumberOfTouches=_minimumNumberOfTouches; - - (id)initWithTarget:(id)target action:(SEL)action { if ((self=[super initWithTarget:target action:action])) { @@ -95,35 +88,42 @@ - (CGPoint)velocityInView:(UIView *)view return _velocity; } -- (void)_gesturesMoved:(NSSet *)touches withEvent:(UIEvent *)event +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { - UITouch *touch = PanTouch([event touchesForGestureRecognizer:self]); + if (self.state == UIGestureRecognizerStatePossible) { + if ([event isKindOfClass:[UITouchEvent class]]) { + UITouchEvent *touchEvent = (UITouchEvent *)event; + + if (touchEvent.touchEventGesture != UITouchEventGestureBegin) { + self.state = UIGestureRecognizerStateFailed; + } + } + } +} - // note that we being the gesture here in the _gesturesMoved:withEvent: method instead of the _gesturesBegan:withEvent: - // method because the pan gesture cannot be recognized until the user moves their fingers a bit and OSX won't tag the - // gesture as a pan until that movement has actually happened so we have to do the checking here. - if (self.state == UIGestureRecognizerStatePossible && touch) { - [self setTranslation:[touch _delta] inView:touch.view]; - _lastMovementTime = event.timestamp; - self.state = UIGestureRecognizerStateBegan; - } else if (self.state == UIGestureRecognizerStateBegan || self.state == UIGestureRecognizerStateChanged) { - if (touch) { - if ([self _translate:[touch _delta] withEvent:event]) { +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event +{ + if ([event isKindOfClass:[UITouchEvent class]]) { + UITouchEvent *touchEvent = (UITouchEvent *)event; + + if (touchEvent.touchEventGesture == UITouchEventGesturePan) { + if (self.state == UIGestureRecognizerStatePossible) { + _lastMovementTime = touchEvent.timestamp; + [self setTranslation:touchEvent.translation inView:touchEvent.touch.view]; + self.state = UIGestureRecognizerStateBegan; + } else if ([self _translate:touchEvent.translation withEvent:event]) { self.state = UIGestureRecognizerStateChanged; } - } else { - self.state = UIGestureRecognizerStateCancelled; } } } -- (void)_gesturesEnded:(NSSet *)touches withEvent:(UIEvent *)event +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { if (self.state == UIGestureRecognizerStateBegan || self.state == UIGestureRecognizerStateChanged) { - UITouch *touch = PanTouch([event touchesForGestureRecognizer:self]); - - if (touch) { - [self _translate:[touch _delta] withEvent:event]; + if ([event isKindOfClass:[UITouchEvent class]]) { + UITouchEvent *touchEvent = (UITouchEvent *)event; + [self _translate:touchEvent.translation withEvent:touchEvent]; self.state = UIGestureRecognizerStateEnded; } else { self.state = UIGestureRecognizerStateCancelled; @@ -131,4 +131,11 @@ - (void)_gesturesEnded:(NSSet *)touches withEvent:(UIEvent *)event } } +- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event +{ + if (self.state == UIGestureRecognizerStateBegan || self.state == UIGestureRecognizerStateChanged) { + self.state = UIGestureRecognizerStateCancelled; + } +} + @end diff --git a/UIKit/Classes/UIPasteboard.h b/UIKit/Classes/UIPasteboard.h index f7969329..5e10cdce 100644 --- a/UIKit/Classes/UIPasteboard.h +++ b/UIKit/Classes/UIPasteboard.h @@ -29,14 +29,15 @@ #import -@class UIImage, UIColor, NSPasteboard; - -@interface UIPasteboard : NSObject { - NSPasteboard *pasteboard; -} +@class UIImage, UIColor; +@interface UIPasteboard : NSObject + (UIPasteboard *)generalPasteboard; +- (void)addItems:(NSArray *)items; +- (void)setData:(NSData *)data forPasteboardType:(NSString *)pasteboardType; +- (void)setValue:(id)value forPasteboardType:(NSString *)pasteboardType; + @property (nonatomic,copy) NSURL *URL; @property (nonatomic,copy) NSArray *URLs; @property (nonatomic,copy) NSString *string; @@ -46,9 +47,4 @@ @property (nonatomic, copy) UIColor *color; @property (nonatomic, copy) NSArray *colors; @property (nonatomic, copy) NSArray *items; - -- (void)addItems:(NSArray *)items; -- (void)setData:(NSData *)data forPasteboardType:(NSString *)pasteboardType; -- (void)setValue:(id)value forPasteboardType:(NSString *)pasteboardType; - @end diff --git a/UIKit/Classes/UIPasteboard.m b/UIKit/Classes/UIPasteboard.m index f54d9627..8071c85e 100644 --- a/UIKit/Classes/UIPasteboard.m +++ b/UIKit/Classes/UIPasteboard.m @@ -64,14 +64,12 @@ static BOOL IsUIPasteboardPropertyListType(id object) // seemed to be the quickest way to get the job done at the time. Copying raw GIF NSData to the // pasteboard on iOS and tagging it as kUTTypeGIF seems to work just fine in the few places that // accept animated GIFs that I've tested so far on iOS so...... yeah. - if (UTTypeEqual((CFStringRef)type, kUTTypeGIF)) { + if (UTTypeEqual((__bridge CFStringRef)type, kUTTypeGIF)) { NSFileWrapper *fileWrapper = [[NSFileWrapper alloc] initRegularFileWithContents:object]; [fileWrapper setPreferredFilename:@"image.gif"]; NSTextAttachment *attachment = [[NSTextAttachment alloc] initWithFileWrapper:fileWrapper]; NSAttributedString *str = [NSAttributedString attributedStringWithAttachment:attachment]; [pasteboardItem setData:[str RTFDFromRange:NSMakeRange(0, [str length]) documentAttributes:nil] forType:(NSString *)kUTTypeFlatRTFD]; - [attachment release]; - [fileWrapper release]; } [pasteboardItem setData:object forType:type]; } else if ([object isKindOfClass:[NSURL class]]) { @@ -81,25 +79,21 @@ static BOOL IsUIPasteboardPropertyListType(id object) } } - return [pasteboardItem autorelease]; + return pasteboardItem; } -@implementation UIPasteboard +@implementation UIPasteboard { + NSPasteboard *_pasteboard; +} - (id)initWithPasteboard:(NSPasteboard *)aPasteboard { if ((self=[super init])) { - pasteboard = [aPasteboard retain]; + _pasteboard = aPasteboard; } return self; } -- (void)dealloc -{ - [pasteboard release]; - [super dealloc]; -} - + (UIPasteboard *)generalPasteboard { static UIPasteboard *aPasteboard = nil; @@ -113,14 +107,14 @@ + (UIPasteboard *)generalPasteboard - (void)_writeObjects:(NSArray *)objects { - [pasteboard clearContents]; - [pasteboard writeObjects:objects]; + [_pasteboard clearContents]; + [_pasteboard writeObjects:objects]; } - (id)_objectsWithClasses:(NSArray *)types { NSDictionary *options = [NSDictionary dictionary]; - return [pasteboard readObjectsForClasses:types options:options]; + return [_pasteboard readObjectsForClasses:types options:options]; } - (void)setStrings:(NSArray *)strings @@ -180,7 +174,7 @@ - (NSArray *)images NSMutableArray *images = [NSMutableArray arrayWithCapacity:[rawImages count]]; for (NSImage *image in rawImages) { - [images addObject:[[[UIImage alloc] initWithNSImage:image] autorelease]]; + [images addObject:[[UIImage alloc] initWithNSImage:image]]; } return images; @@ -213,7 +207,7 @@ - (NSArray *)colors NSMutableArray *colors = [NSMutableArray arrayWithCapacity:[rawColors count]]; for (NSColor *color in rawColors) { - [colors addObject:[[[UIColor alloc] initWithNSColor:color] autorelease]]; + [colors addObject:[[UIColor alloc] initWithNSColor:color]]; } return colors; @@ -237,12 +231,12 @@ - (void)addItems:(NSArray *)items [objects addObject:PasteBoardItemWithDictionary(item)]; } - [pasteboard writeObjects:objects]; + [_pasteboard writeObjects:objects]; } - (void)setItems:(NSArray *)items { - [pasteboard clearContents]; + [_pasteboard clearContents]; [self addItems:items]; } @@ -251,13 +245,13 @@ - (NSArray *)items { NSMutableArray *items = [NSMutableArray arrayWithCapacity:0]; - for (NSPasteboardItem *item in [pasteboard pasteboardItems]) { + for (NSPasteboardItem *item in [_pasteboard pasteboardItems]) { NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:0]; for (NSString *type in [item types]) { id object = nil; - if (UTTypeConformsTo((CFStringRef)type, kUTTypeURL)) { + if (UTTypeConformsTo((__bridge CFStringRef)type, kUTTypeURL)) { object = [NSURL URLWithString:[item stringForType:type]]; } else { object = [item propertyListForType:type] ?: [item dataForType:type]; @@ -279,16 +273,16 @@ - (NSArray *)items - (void)setData:(NSData *)data forPasteboardType:(NSString *)pasteboardType { if (data && pasteboardType) { - [pasteboard clearContents]; - [pasteboard writeObjects:[NSArray arrayWithObject:PasteBoardItemWithDictionary([NSDictionary dictionaryWithObject:data forKey:pasteboardType])]]; + [_pasteboard clearContents]; + [_pasteboard writeObjects:[NSArray arrayWithObject:PasteBoardItemWithDictionary([NSDictionary dictionaryWithObject:data forKey:pasteboardType])]]; } } - (void)setValue:(id)value forPasteboardType:(NSString *)pasteboardType { if (pasteboardType && IsUIPasteboardPropertyListType(value)) { - [pasteboard clearContents]; - [pasteboard writeObjects:[NSArray arrayWithObject:PasteBoardItemWithDictionary([NSDictionary dictionaryWithObject:value forKey:pasteboardType])]]; + [_pasteboard clearContents]; + [_pasteboard writeObjects:[NSArray arrayWithObject:PasteBoardItemWithDictionary([NSDictionary dictionaryWithObject:value forKey:pasteboardType])]]; } } diff --git a/UIKit/Classes/UIPhotosAlbum.m b/UIKit/Classes/UIPhotosAlbum.m index 3a6ae18c..f42d0ed4 100644 --- a/UIKit/Classes/UIPhotosAlbum.m +++ b/UIKit/Classes/UIPhotosAlbum.m @@ -69,14 +69,9 @@ - (void)_writeImageWithInfo:(NSDictionary *)info if (target) { SEL action = NSSelectorFromString([info objectForKey:@"action"]); void *context = [[info objectForKey:@"context"] pointerValue]; - - NSMethodSignature *signature = [target methodSignatureForSelector:action]; - NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; - [invocation setSelector:action]; - [invocation setArgument:&image atIndex:2]; - [invocation setArgument:&error atIndex:3]; - [invocation setArgument:&context atIndex:4]; - [invocation invokeWithTarget:target]; + typedef void(*ActionMethod)(id, SEL, id, NSError *, void *); + ActionMethod method = (ActionMethod)[target methodForSelector:action]; + method(target, action, image, error, context); } } diff --git a/UIKit/Classes/UIPickerView.h b/UIKit/Classes/UIPickerView.h index 35c78786..cf743f5f 100644 --- a/UIKit/Classes/UIPickerView.h +++ b/UIKit/Classes/UIPickerView.h @@ -37,17 +37,7 @@ @protocol UIPickerViewDataSource, UIPickerViewDelegate; -@interface UIPickerView : UIView { - __unsafe_unretained id _dataSource; - __unsafe_unretained id _delegate; - BOOL _showsSelectionIndicator; -} - -@property (nonatomic, assign) id dataSource; -@property (nonatomic, assign) id delegate; -@property (nonatomic, assign) BOOL showsSelectionIndicator; -@property (nonatomic, readonly) NSInteger numberOfComponents; - +@interface UIPickerView : UIView - (NSInteger) numberOfRowsInComponent: (NSInteger) component; // stub - (void) reloadAllComponents; // stub - (void) reloadComponent: (NSInteger) component; // stub @@ -56,6 +46,10 @@ - (void)selectRow:(NSInteger)row inComponent:(NSInteger)component animated:(BOOL)animated; // stub - (UIView *) viewForRow: (NSInteger) row inComponent: (NSInteger) component; // stub +@property (nonatomic, assign) id dataSource; +@property (nonatomic, assign) id delegate; +@property (nonatomic, assign) BOOL showsSelectionIndicator; +@property (nonatomic, readonly) NSInteger numberOfComponents; @end diff --git a/UIKit/Classes/UIPickerView.m b/UIKit/Classes/UIPickerView.m index 294236e9..3c0ad853 100644 --- a/UIKit/Classes/UIPickerView.m +++ b/UIKit/Classes/UIPickerView.m @@ -37,10 +37,6 @@ @implementation UIPickerView -@synthesize showsSelectionIndicator = _showsSelectionIndicator; -@synthesize dataSource = _dataSource; -@synthesize delegate = _delegate; - - (id)initWithFrame:(CGRect)frame { if ((self = [super initWithFrame:frame])) { @@ -52,7 +48,6 @@ - (void)dealloc { _dataSource = nil; _delegate = nil; - [super dealloc]; } - (NSInteger) numberOfComponents diff --git a/UIKit/Classes/UIPinchGestureRecognizer.h b/UIKit/Classes/UIPinchGestureRecognizer.h index 65ef6da6..0d90f91f 100644 --- a/UIKit/Classes/UIPinchGestureRecognizer.h +++ b/UIKit/Classes/UIPinchGestureRecognizer.h @@ -29,11 +29,7 @@ #import "UIGestureRecognizer.h" -@interface UIPinchGestureRecognizer : UIGestureRecognizer { - CGFloat _scale; -} - +@interface UIPinchGestureRecognizer : UIGestureRecognizer @property (nonatomic) CGFloat scale; @property (nonatomic, readonly) CGFloat velocity; - @end diff --git a/UIKit/Classes/UIPinchGestureRecognizer.m b/UIKit/Classes/UIPinchGestureRecognizer.m index d1d85db7..1c339b21 100644 --- a/UIKit/Classes/UIPinchGestureRecognizer.m +++ b/UIKit/Classes/UIPinchGestureRecognizer.m @@ -29,9 +29,9 @@ #import "UIPinchGestureRecognizer.h" #import "UIGestureRecognizerSubclass.h" +#import "UITouchEvent.h" @implementation UIPinchGestureRecognizer -@synthesize scale=_scale; - (id)initWithTarget:(id)target action:(SEL)action { @@ -46,4 +46,54 @@ - (CGFloat)velocity return 0; } +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event +{ + if (self.state == UIGestureRecognizerStatePossible) { + if ([event isKindOfClass:[UITouchEvent class]]) { + UITouchEvent *touchEvent = (UITouchEvent *)event; + + if (touchEvent.touchEventGesture != UITouchEventGestureBegin) { + self.state = UIGestureRecognizerStateFailed; + } + } + } +} + +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event +{ + if ([event isKindOfClass:[UITouchEvent class]]) { + UITouchEvent *touchEvent = (UITouchEvent *)event; + + if (touchEvent.touchEventGesture == UITouchEventGesturePinch) { + if (self.state == UIGestureRecognizerStatePossible) { + _scale = touchEvent.magnification; + self.state = UIGestureRecognizerStateBegan; + } else { + _scale = touchEvent.magnification; + self.state = UIGestureRecognizerStateChanged; + } + } + } +} + +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event +{ + if (self.state == UIGestureRecognizerStateBegan || self.state == UIGestureRecognizerStateChanged) { + if ([event isKindOfClass:[UITouchEvent class]]) { + UITouchEvent *touchEvent = (UITouchEvent *)event; + _scale = touchEvent.magnification; + self.state = UIGestureRecognizerStateEnded; + } else { + self.state = UIGestureRecognizerStateCancelled; + } + } +} + +- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event +{ + if (self.state == UIGestureRecognizerStateBegan || self.state == UIGestureRecognizerStateChanged) { + self.state = UIGestureRecognizerStateCancelled; + } +} + @end diff --git a/UIKit/Classes/UIPopoverController.h b/UIKit/Classes/UIPopoverController.h index 9df164b9..22662c2a 100644 --- a/UIKit/Classes/UIPopoverController.h +++ b/UIKit/Classes/UIPopoverController.h @@ -29,7 +29,7 @@ #import -enum { +typedef NS_OPTIONS(NSUInteger, UIPopoverArrowDirection) { UIPopoverArrowDirectionUp = 1UL << 0, UIPopoverArrowDirectionDown = 1UL << 1, UIPopoverArrowDirectionLeft = 1UL << 2, @@ -38,7 +38,6 @@ enum { UIPopoverArrowDirectionLeft | UIPopoverArrowDirectionRight, UIPopoverArrowDirectionUnknown = NSUIntegerMax }; -typedef NSUInteger UIPopoverArrowDirection; @class UIView, UIViewController, UIPopoverController, UIBarButtonItem, UIPopoverView; @@ -48,37 +47,20 @@ typedef NSUInteger UIPopoverArrowDirection; - (BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController; @end -@interface UIPopoverController : NSObject { -@private - UIViewController *_contentViewController; - NSArray *_passthroughViews; - UIPopoverArrowDirection _popoverArrowDirection; - - UIPopoverView *_popoverView; - id _popoverWindow; - id _overlayWindow; - - BOOL _isDismissing; - - __unsafe_unretained id _delegate; - struct { - unsigned popoverControllerDidDismissPopover : 1; - unsigned popoverControllerShouldDismissPopover : 1; - } _delegateHas; -} - +@interface UIPopoverController : NSObject - (id)initWithContentViewController:(UIViewController *)viewController; - (void)setContentViewController:(UIViewController *)controller animated:(BOOL)animated; +- (void)setPopoverContentSize:(CGSize)size animated:(BOOL)animated; - (void)presentPopoverFromRect:(CGRect)rect inView:(UIView *)view permittedArrowDirections:(UIPopoverArrowDirection)arrowDirections animated:(BOOL)animated; - (void)presentPopoverFromBarButtonItem:(UIBarButtonItem *)item permittedArrowDirections:(UIPopoverArrowDirection)arrowDirections animated:(BOOL)animated; - (void)dismissPopoverAnimated:(BOOL)animated; @property (nonatomic, assign) id delegate; -@property (nonatomic, retain) UIViewController *contentViewController; +@property (nonatomic, strong) UIViewController *contentViewController; @property (nonatomic, readonly, getter=isPopoverVisible) BOOL popoverVisible; @property (nonatomic, copy) NSArray *passthroughViews; @property (nonatomic, readonly) UIPopoverArrowDirection popoverArrowDirection; - +@property (nonatomic) CGSize popoverContentSize; @end diff --git a/UIKit/Classes/UIPopoverController.m b/UIKit/Classes/UIPopoverController.m index c47ebfe2..c53ddde2 100644 --- a/UIKit/Classes/UIPopoverController.m +++ b/UIKit/Classes/UIPopoverController.m @@ -34,7 +34,7 @@ #import "UIScreenAppKitIntegration.h" #import "UIKitView.h" #import "UITouch.h" -#import "UIApplication+UIPrivate.h" +#import "UIApplicationAppKitIntegration.h" #import "UIPopoverView.h" #import "UIPopoverNSWindow.h" #import "UIPopoverOverlayNSView.h" @@ -119,13 +119,18 @@ static NSPoint PopoverWindowOrigin(NSWindow *inWindow, NSRect fromRect, NSSize p return windowRect.origin; } -@interface UIPopoverController () -- (void)_destroyPopover; -@end - -@implementation UIPopoverController -@synthesize delegate=_delegate, contentViewController=_contentViewController, passthroughViews=_passthroughViews; -@synthesize popoverArrowDirection=_popoverArrowDirection; +@implementation UIPopoverController { + UIPopoverView *_popoverView; + UIPopoverNSWindow *_popoverWindow; + NSWindow *_overlayWindow; + + BOOL _isDismissing; + + struct { + unsigned popoverControllerDidDismissPopover : 1; + unsigned popoverControllerShouldDismissPopover : 1; + } _delegateHas; +} - (id)init { @@ -147,9 +152,6 @@ - (id)initWithContentViewController:(UIViewController *)viewController - (void)dealloc { [self _destroyPopover]; - [_passthroughViews release]; - [_contentViewController release]; - [super dealloc]; } - (void)setDelegate:(id)newDelegate @@ -165,8 +167,7 @@ - (void)setContentViewController:(UIViewController *)controller animated:(BOOL)a if ([self isPopoverVisible]) { [_popoverView setContentView:controller.view animated:animated]; } - [_contentViewController release]; - _contentViewController = [controller retain]; + _contentViewController = controller; } } @@ -175,6 +176,16 @@ - (void)setContentViewController:(UIViewController *)viewController [self setContentViewController:viewController animated:NO]; } +- (void)setPopoverContentSize:(CGSize)size animated:(BOOL)animated +{ + _popoverContentSize = size; +} + +- (void)setPopoverContentSize:(CGSize)size +{ + [self setPopoverContentSize:size animated:NO]; +} + - (void)presentPopoverFromRect:(CGRect)rect inView:(UIView *)view permittedArrowDirections:(UIPopoverArrowDirection)arrowDirections animated:(BOOL)animated { assert(_isDismissing == NO); @@ -182,9 +193,9 @@ - (void)presentPopoverFromRect:(CGRect)rect inView:(UIView *)view permittedArrow assert(arrowDirections != UIPopoverArrowDirectionUnknown); assert(!CGRectIsNull(rect)); assert(!CGRectEqualToRect(rect,CGRectZero)); - assert([[view.window.screen UIKitView] window] != nil); + assert([view.window.screen.UIKitView window] != nil); - NSWindow *viewNSWindow = [[view.window.screen UIKitView] window]; + NSWindow *viewNSWindow = [view.window.screen.UIKitView window]; // only create new stuff if the popover isn't already visible if (![self isPopoverVisible]) { @@ -198,48 +209,39 @@ - (void)presentPopoverFromRect:(CGRect)rect inView:(UIView *)view permittedArrow NSRect windowFrame = [viewNSWindow frame]; NSRect overlayContentRect = NSMakeRect(0,0,windowFrame.size.width,windowFrame.size.height); - UIPopoverOverlayNSView *popoverOverlayNSView = [[UIPopoverOverlayNSView alloc] initWithFrame:overlayContentRect popoverController:self]; - _overlayWindow = [[NSWindow alloc] initWithContentRect:overlayContentRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES]; - [_overlayWindow setContentView:popoverOverlayNSView]; + [_overlayWindow setReleasedWhenClosed:NO]; + [_overlayWindow setContentView:[[UIPopoverOverlayNSView alloc] initWithFrame:overlayContentRect popoverController:self]]; [_overlayWindow setIgnoresMouseEvents:NO]; [_overlayWindow setOpaque:NO]; - [(NSWindow *)_overlayWindow setBackgroundColor:[NSColor clearColor]]; + [_overlayWindow setBackgroundColor:[NSColor clearColor]]; [_overlayWindow setFrameOrigin:windowFrame.origin]; [viewNSWindow addChildWindow:_overlayWindow ordered:NSWindowAbove]; // now build the actual popover view which represents the popover's chrome, and since it's a UIView, we need to build a UIKitView // as well to put it in our NSWindow... _popoverView = [[UIPopoverView alloc] initWithContentView:_contentViewController.view size:_contentViewController.contentSizeForViewInPopover]; + [_popoverView setHidden:YES]; - // this prevents a visible flash from sometimes occuring due to the fact that the window is created and added as a child before it has the - // proper origin set. this means it it ends up flashing at the bottom left corner of the screen sometimes before it - // gets down farther in this method where the actual origin is calculated and set. since the window is transparent, simply setting the UIView - // hidden gets around the problem since you then can't see any of the actual content that's in the window :) - _popoverView.hidden = YES; - - UIKitView *hostingView = [(UIKitView *)[UIKitView alloc] initWithFrame:NSRectFromCGRect([_popoverView bounds])]; - [[hostingView UIScreen] _setPopoverController:self]; + UIKitView *hostingView = [[UIKitView alloc] initWithFrame:NSRectFromCGRect([_popoverView bounds])]; [[hostingView UIWindow] addSubview:_popoverView]; // now finally make the actual popover window itself and attach it to the overlay window _popoverWindow = [[UIPopoverNSWindow alloc] initWithContentRect:[hostingView bounds] styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES]; - [(UIPopoverNSWindow *)_popoverWindow setContentView:hostingView]; - [(UIPopoverNSWindow *)_popoverWindow setPopoverController:self]; - [(UIPopoverNSWindow *)_popoverWindow setOpaque:NO]; - [(UIPopoverNSWindow *)_popoverWindow setBackgroundColor:[NSColor clearColor]]; + [_popoverWindow setReleasedWhenClosed:NO]; + [_popoverWindow setAlphaValue:0]; // prevents a flash as the window moves from the wrong position into the right position + [_popoverWindow setContentView:hostingView]; + [_popoverWindow setPopoverController:self]; + [_popoverWindow setOpaque:NO]; + [_popoverWindow setBackgroundColor:[NSColor clearColor]]; [_overlayWindow addChildWindow:_popoverWindow ordered:NSWindowAbove]; - [(UIPopoverNSWindow *)_popoverWindow makeFirstResponder:hostingView]; - - [hostingView release]; - [popoverOverlayNSView release]; } // cancel current touches (if any) to prevent the main window from losing track of events (such as if the user was holding down the mouse // button and a timer triggered the appearance of this popover. the window would possibly then not receive the mouseUp depending on how // all this works out... I first ran into this problem with NSMenus. A NSWindow is a bit different, but I think this makes sense here // too so premptively doing it to avoid potential problems.) - [[UIApplication sharedApplication] _cancelTouches]; + UIApplicationInterruptTouchesInView(nil); // now position the popover window according to the passed in parameters. CGRect windowRect = [view convertRect:rect toView:nil]; @@ -249,7 +251,9 @@ - (void)presentPopoverFromRect:(CGRect)rect inView:(UIView *)view permittedArrow // finally, let's show it! [_popoverWindow setFrameOrigin:PopoverWindowOrigin(_overlayWindow, NSRectFromCGRect(desktopScreenRect), NSSizeFromCGSize(_popoverView.frame.size), arrowDirections, &pointTo, &_popoverArrowDirection)]; - _popoverView.hidden = NO; + [_popoverWindow setAlphaValue:1]; + [_popoverView setHidden:NO]; + [_popoverWindow makeFirstResponder:[_popoverWindow contentView]]; [_popoverWindow makeKeyWindow]; // the window has to be visible before these coordinate conversions will work correctly (otherwise the UIScreen isn't attached to anything @@ -287,24 +291,21 @@ - (BOOL)isPopoverVisible - (void)_destroyPopover { - NSWindow *parentWindow = [[_overlayWindow parentWindow] retain]; + NSWindow *parentWindow = [_overlayWindow parentWindow]; [_overlayWindow removeChildWindow:_popoverWindow]; [parentWindow removeChildWindow:_overlayWindow]; - [_popoverView release]; - _popoverView = nil; - [_popoverWindow close]; - _popoverWindow = nil; - [_overlayWindow close]; + + _popoverWindow = nil; _overlayWindow = nil; + _popoverView = nil; _popoverArrowDirection = UIPopoverArrowDirectionUnknown; [parentWindow makeKeyAndOrderFront:self]; - [parentWindow release]; _isDismissing = NO; } diff --git a/UIKit/Classes/UIPopoverNSWindow.h b/UIKit/Classes/UIPopoverNSWindow.h index 31f737fb..54f88cec 100644 --- a/UIKit/Classes/UIPopoverNSWindow.h +++ b/UIKit/Classes/UIPopoverNSWindow.h @@ -31,9 +31,7 @@ @class UIPopoverController; -@interface UIPopoverNSWindow : NSWindow { - __unsafe_unretained UIPopoverController *_popoverController; -} +@interface UIPopoverNSWindow : NSWindow - (void)setPopoverController:(UIPopoverController *)controller; diff --git a/UIKit/Classes/UIPopoverNSWindow.m b/UIKit/Classes/UIPopoverNSWindow.m index 388ed271..522f1700 100644 --- a/UIKit/Classes/UIPopoverNSWindow.m +++ b/UIKit/Classes/UIPopoverNSWindow.m @@ -30,7 +30,9 @@ #import "UIPopoverNSWindow.h" #import "UIPopoverController+UIPrivate.h" -@implementation UIPopoverNSWindow +@implementation UIPopoverNSWindow { + __unsafe_unretained UIPopoverController *_popoverController; +} - (void)setPopoverController:(UIPopoverController *)controller { diff --git a/UIKit/Classes/UIPopoverOverlayNSView.h b/UIKit/Classes/UIPopoverOverlayNSView.h index 731e97a7..9119e61c 100644 --- a/UIKit/Classes/UIPopoverOverlayNSView.h +++ b/UIKit/Classes/UIPopoverOverlayNSView.h @@ -31,9 +31,7 @@ @class UIPopoverController; -@interface UIPopoverOverlayNSView : NSView { - UIPopoverController *_popoverController; -} +@interface UIPopoverOverlayNSView : NSView - (id)initWithFrame:(NSRect)frame popoverController:(UIPopoverController *)controller; diff --git a/UIKit/Classes/UIPopoverOverlayNSView.m b/UIKit/Classes/UIPopoverOverlayNSView.m index 58f425ff..528ae6ce 100644 --- a/UIKit/Classes/UIPopoverOverlayNSView.m +++ b/UIKit/Classes/UIPopoverOverlayNSView.m @@ -30,7 +30,9 @@ #import "UIPopoverOverlayNSView.h" #import "UIPopoverController+UIPrivate.h" -@implementation UIPopoverOverlayNSView +@implementation UIPopoverOverlayNSView { + __unsafe_unretained UIPopoverController *_popoverController; +} - (id)initWithFrame:(NSRect)frame popoverController:(UIPopoverController *)controller { diff --git a/UIKit/Classes/UIPopoverView.h b/UIKit/Classes/UIPopoverView.h index 6b7047ad..9ddf7cf0 100644 --- a/UIKit/Classes/UIPopoverView.h +++ b/UIKit/Classes/UIPopoverView.h @@ -31,12 +31,7 @@ @class UIImageView; -@interface UIPopoverView : UIView { - UIImageView *_backgroundView; - UIImageView *_arrowView; - UIView *_contentView; - UIView *_contentContainerView; -} +@interface UIPopoverView : UIView - (id)initWithContentView:(UIView *)aView size:(CGSize)aSize; @@ -44,7 +39,7 @@ - (void)setContentView:(UIView *)aView animated:(BOOL)animated; - (void)setContentSize:(CGSize)aSize animated:(BOOL)animated; -@property (nonatomic, retain) UIView *contentView; +@property (nonatomic, strong) UIView *contentView; @property (nonatomic, assign) CGSize contentSize; @end diff --git a/UIKit/Classes/UIPopoverView.m b/UIKit/Classes/UIPopoverView.m index c10444a7..5cf8581f 100644 --- a/UIKit/Classes/UIPopoverView.m +++ b/UIKit/Classes/UIPopoverView.m @@ -95,8 +95,11 @@ static CGFloat DistanceBetweenTwoPoints(CGPoint A, CGPoint B) return sqrtf((a*a) + (b*b)); } -@implementation UIPopoverView -@synthesize contentView=_contentView; +@implementation UIPopoverView { + UIImageView *_backgroundView; + UIImageView *_arrowView; + UIView *_contentContainerView; +} + (UIEdgeInsets)insetForArrows { @@ -129,7 +132,7 @@ + (CGSize)frameSizeForContentSize:(CGSize)contentSize withNavigationBar:(BOOL)ha - (id)initWithContentView:(UIView *)aView size:(CGSize)aSize { if ((self=[super initWithFrame:CGRectMake(0,0,320,480)])) { - _contentView = [aView retain]; + _contentView = aView; UIImage *backgroundImage = [UIImage _popoverBackgroundImage]; _backgroundView = [[UIImageView alloc] initWithImage:backgroundImage]; @@ -150,22 +153,14 @@ - (id)initWithContentView:(UIView *)aView size:(CGSize)aSize return self; } -- (void)dealloc -{ - [_backgroundView release]; - [_arrowView release]; - [_contentContainerView release]; - [_contentView release]; - [super dealloc]; -} - (void)layoutSubviews { [super layoutSubviews]; const CGRect bounds = self.bounds; - _backgroundView.frame = [isa backgroundRectForBounds:bounds]; - _contentContainerView.frame = [isa contentRectForBounds:bounds withNavigationBar:NO]; + _backgroundView.frame = [[self class] backgroundRectForBounds:bounds]; + _contentContainerView.frame = [[self class] contentRectForBounds:bounds withNavigationBar:NO]; _contentView.frame = _contentContainerView.bounds; } @@ -298,8 +293,7 @@ - (void)setContentView:(UIView *)aView animated:(BOOL)animated { if (aView != _contentView) { [_contentView removeFromSuperview]; - [_contentView release]; - _contentView = [aView retain]; + _contentView = aView; [self addSubview:_contentView]; } } @@ -312,7 +306,7 @@ - (void)setContentView:(UIView *)aView - (void)setContentSize:(CGSize)aSize animated:(BOOL)animated { CGRect frame = self.frame; - frame.size = [isa frameSizeForContentSize:aSize withNavigationBar:NO]; + frame.size = [[self class] frameSizeForContentSize:aSize withNavigationBar:NO]; [UIView animateWithDuration:animated? 0.2 : 0 animations:^(void) { diff --git a/UIKit/Classes/UIProgressView.h b/UIKit/Classes/UIProgressView.h index 15f359b4..fc6e98cd 100644 --- a/UIKit/Classes/UIProgressView.h +++ b/UIKit/Classes/UIProgressView.h @@ -28,20 +28,20 @@ */ #import "UIView.h" +#import "UIImage.h" -typedef enum { +typedef NS_ENUM(NSInteger, UIProgressViewStyle) { UIProgressViewStyleDefault, UIProgressViewStyleBar, -} UIProgressViewStyle; - -@interface UIProgressView : UIView { - UIProgressViewStyle _progressViewStyle; - float _progress; -} +}; +@interface UIProgressView : UIView - (id)initWithProgressViewStyle:(UIProgressViewStyle)style; +- (void)setProgress:(float)progress animated:(BOOL)animated; @property (nonatomic) UIProgressViewStyle progressViewStyle; @property (nonatomic) float progress; +@property (nonatomic, strong) UIImage *progressImage; +@property (nonatomic, strong) UIImage *trackImage; @end diff --git a/UIKit/Classes/UIProgressView.m b/UIKit/Classes/UIProgressView.m index 514f8b74..7778ad58 100644 --- a/UIKit/Classes/UIProgressView.m +++ b/UIKit/Classes/UIProgressView.m @@ -30,7 +30,6 @@ #import "UIProgressView.h" @implementation UIProgressView -@synthesize progressViewStyle=_progressViewStyle, progress=_progress; - (id)initWithProgressViewStyle:(UIProgressViewStyle)style { @@ -48,10 +47,15 @@ - (void)setProgressViewStyle:(UIProgressViewStyle)style } } -- (void)setProgress:(float)p +- (void)setProgress:(float)progress { - if (p != _progress) { - _progress = MIN(1,MAX(0,p)); + [self setProgress:progress animated:NO]; +} + +- (void)setProgress:(float)progress animated:(BOOL)animated +{ + if (progress != _progress) { + _progress = MIN(1,MAX(0,progress)); [self setNeedsDisplay]; } } diff --git a/UIKit/Classes/UIResponder.h b/UIKit/Classes/UIResponder.h index b7904d9e..245cb76d 100644 --- a/UIKit/Classes/UIResponder.h +++ b/UIKit/Classes/UIResponder.h @@ -30,7 +30,6 @@ #import "UIEvent.h" @interface UIResponder : NSObject - - (UIResponder *)nextResponder; - (BOOL)isFirstResponder; - (BOOL)canBecomeFirstResponder; @@ -49,12 +48,33 @@ - (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event; - (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event; -@property (readonly, retain) UIView *inputAccessoryView; -@property (readonly, retain) UIView *inputView; -@property (readonly) NSUndoManager *undoManager; +@property (nonatomic, readonly) NSArray *keyCommands; +@property (readonly, strong) UIView *inputAccessoryView; +@property (readonly, strong) UIView *inputView; +@property (readonly) NSUndoManager *undoManager; @end +typedef NS_OPTIONS(NSInteger, UIKeyModifierFlags) { + UIKeyModifierAlphaShift = 1 << 16, // capslock + UIKeyModifierShift = 1 << 17, + UIKeyModifierControl = 1 << 18, + UIKeyModifierAlternate = 1 << 19, + UIKeyModifierCommand = 1 << 20, + UIKeyModifierNumericPad = 1 << 21, +}; + +extern NSString *const UIKeyInputUpArrow; +extern NSString *const UIKeyInputDownArrow; +extern NSString *const UIKeyInputLeftArrow; +extern NSString *const UIKeyInputRightArrow; +extern NSString *const UIKeyInputEscape; + +@interface UIKeyCommand : NSObject ++ (UIKeyCommand *)keyCommandWithInput:(NSString *)input modifierFlags:(UIKeyModifierFlags)modifierFlags action:(SEL)action; +@property (nonatomic,readonly) NSString *input; +@property (nonatomic,readonly) UIKeyModifierFlags modifierFlags; +@end @interface NSObject (UIResponderStandardEditActions) - (void)copy:(id)sender; @@ -63,4 +83,13 @@ - (void)paste:(id)sender; - (void)select:(id)sender; - (void)selectAll:(id)sender; + +- (void)makeTextWritingDirectionLeftToRight:(id)sender; +- (void)makeTextWritingDirectionRightToLeft:(id)sender; +- (void)toggleBoldface:(id)sender; +- (void)toggleItalics:(id)sender; +- (void)toggleUnderline:(id)sender; + +- (void)increaseSize:(id)sender; +- (void)decreaseSize:(id)sender; @end diff --git a/UIKit/Classes/UIResponder.m b/UIKit/Classes/UIResponder.m index 55ece95e..88fed091 100644 --- a/UIKit/Classes/UIResponder.m +++ b/UIKit/Classes/UIResponder.m @@ -75,19 +75,24 @@ - (BOOL)becomeFirstResponder } if (didResign) { - [window makeKeyWindow]; // not sure about this :/ [window _setFirstResponder:self]; - // I have no idea how iOS manages this stuff, but here I'm modeling UIMenuController since it also uses the first - // responder to do its work. My thinking is that if there were an on-screen keyboard, something here could detect - // if self conforms to UITextInputTraits and UIKeyInput and/or UITextInput and then build/fetch the correct keyboard - // and assign that to the inputView property which would seperate the keyboard and inputs themselves from the stuff - // that actually displays them on screen. Of course on the Mac we don't need an on-screen keyboard, but there's - // possibly an argument to be made for supporting custom inputViews anyway. - UIInputController *controller = [UIInputController sharedInputController]; - controller.inputAccessoryView = self.inputAccessoryView; - controller.inputView = self.inputView; - [controller setInputVisible:YES animated:YES]; + if ([self conformsToProtocol:@protocol(UIKeyInput)]) { + // I have no idea how iOS manages this stuff, but here I'm modeling UIMenuController since it also uses the first + // responder to do its work. My thinking is that if there were an on-screen keyboard, something here could detect + // if self conforms to UITextInputTraits and UIKeyInput and/or UITextInput and then build/fetch the correct keyboard + // and assign that to the inputView property which would seperate the keyboard and inputs themselves from the stuff + // that actually displays them on screen. Of course on the Mac we don't need an on-screen keyboard, but there's + // possibly an argument to be made for supporting custom inputViews anyway. + UIInputController *controller = [UIInputController sharedInputController]; + controller.inputAccessoryView = self.inputAccessoryView; + controller.inputView = self.inputView; + controller.keyInputResponder = (UIResponder *)self; + [controller setInputVisible:YES animated:YES]; + + // key input won't very well work without this + [window makeKeyWindow]; + } return YES; } @@ -114,13 +119,39 @@ - (BOOL)resignFirstResponder - (BOOL)canPerformAction:(SEL)action withSender:(id)sender { - if ([isa instancesRespondToSelector:action]) { + if ([[self class] instancesRespondToSelector:action]) { return YES; } else { return [[self nextResponder] canPerformAction:action withSender:sender]; } } +- (NSArray *)keyCommands +{ + return nil; +} + +- (UIView *)inputAccessoryView +{ + return nil; +} + +- (UIView *)inputView +{ + return nil; +} + +- (NSUndoManager *)undoManager +{ + return [[self nextResponder] undoManager]; +} + +// curiously, the documentation states that all of the following methods do nothing by default but that +// "immediate UIKit subclasses of UIResponder, particularly UIView, forward the message up the responder chain." +// oddly, though, if I use class_getInstanceMethod() to print the address of the actual C function being used +// by UIView, UIViewController, and UIResponder, they all point to the same function. So.... someone is wrong. +// I'm going to leave it like this for now because this is a lot simpler, IMO, and seems nicely logical. + - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [[self nextResponder] touchesBegan:touches withEvent:event]; @@ -141,23 +172,61 @@ - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event [[self nextResponder] touchesCancelled:touches withEvent:event]; } -- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event {} -- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event {} -- (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event {} +- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event +{ + [[self nextResponder] motionBegan:motion withEvent:event]; +} -- (UIView *)inputAccessoryView +- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event { - return nil; + [[self nextResponder] motionEnded:motion withEvent:event]; } -- (UIView *)inputView +- (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event +{ + [[self nextResponder] motionCancelled:motion withEvent:event]; +} + +@end + + +@implementation UIKeyCommand + ++ (UIKeyCommand *)keyCommandWithInput:(NSString *)input modifierFlags:(UIKeyModifierFlags)modifierFlags action:(SEL)action { + // TODO return nil; } -- (NSUndoManager *)undoManager ++ (BOOL)supportsSecureCoding { - return [[self nextResponder] undoManager]; + return YES; +} + +- (id)initWithCoder:(NSCoder *)decoder +{ + // note, this requires NSSecureCoding, so you have to do something like this: + //id obj = [decoder decodeObjectOfClass:[MyClass class] forKey:@"myKey"]; + + // TODO + return [self init]; +} + +- (void)encodeWithCoder:(NSCoder *)encoder +{ + // TODO +} + +- (id)copyWithZone:(NSZone *)zone +{ + // this should be okay, because this is an immutable object + return self; } @end + +NSString *const UIKeyInputUpArrow = @"UIKeyInputUpArrow"; +NSString *const UIKeyInputDownArrow = @"UIKeyInputDownArrow"; +NSString *const UIKeyInputLeftArrow = @"UIKeyInputLeftArrow"; +NSString *const UIKeyInputRightArrow = @"UIKeyInputRightArrow"; +NSString *const UIKeyInputEscape = @"UIKeyInputEscape"; diff --git a/UIKit/Classes/UIResponderAppKitIntegration.h b/UIKit/Classes/UIResponderAppKitIntegration.h index 91a677fe..62f5f064 100644 --- a/UIKit/Classes/UIResponderAppKitIntegration.h +++ b/UIKit/Classes/UIResponderAppKitIntegration.h @@ -29,47 +29,38 @@ #import "UIResponder.h" -@class UIKey; +@class UIKey, UITouch; @interface UIResponder (AppKitIntegration) -// This message is sent up the responder chain so that views behind other views can make use of the scroll wheel (such as UIScrollView). +// Sent when the mouse scroll wheel changes. - (void)scrollWheelMoved:(CGPoint)delta withEvent:(UIEvent *)event; -// This is sent up the responder chain when the app gets a rightMouseDown-like event from OSX. There is no rightMouseDragged or rightMouseUp. +// Sent when the app gets a rightMouseDown-like event from OSX. There is no rightMouseDragged or rightMouseUp. - (void)rightClick:(UITouch *)touch withEvent:(UIEvent *)event; -// This message is sent up (down?) the responder chain. You may get these often - especially when the mouse moves over a view that has a lot -// of smaller subviews in it as the messages will be sent each time the view under the cursor changes. These only happen during normal mouse -// movement - not when clicking, click-dragging, etc so it won't happen in all possible cases that might maybe make sense. Also, due to the -// bolted-on nature of this, I'm not entirely convinced it is delivered from the best spot - but in practice, it'll probably be okay. -// NOTE: You might get this message twice since the message is sent both to the view being left and the one being exited and they could -// ultimately share the same superview or controller or something. -// If the mouse came in from outside the hosting UIKitView, the enteredView is nil. If the mouse left the UIKitView, the exitedView is nil. -- (void)mouseExitedView:(UIView *)exited enteredView:(UIView *)entered withEvent:(UIEvent *)event; - -// This passed along the responder chain like everything else. -- (void)mouseMoved:(CGPoint)delta withEvent:(UIEvent *)event; +// These message are sent often, but only during hover mouse movements - not when clicking, click-dragging, in a gesture, etc. +// NOTE: You might get these messages more than once if you are capturing it in superview as messages are generated based on the subview +// that is hit. -mouseMoved:withEvent: may send you a touch that is outside of your view in some cases (such as when the mouse is leaving +// your view's bounds), however that behavior is not always reliable depending on arrangement of views or if the view is near the edge of +// the UIKitView's bounds, etc. +- (void)mouseEntered:(UIView *)view withEvent:(UIEvent *)event; +- (void)mouseMoved:(UITouch *)touch withEvent:(UIEvent *)event; +- (void)mouseExited:(UIView *)view withEvent:(UIEvent *)event; // Return an NSCursor if you want to modify it or nil to use the default arrow. Follows responder chain. - (id)mouseCursorForEvent:(UIEvent *)event; // return an NSCursor if you want to modify it, return nil to use default -// This is a rough guess as to what might be coming in the future with UIKit. I suspect it'll be similar but perhaps more detailed. UIKey -// may or may not exist, etc. This will work for now in case it is needed. This is only triggered by keyDown: events and is not extensively -// implemented or tested at this point. This is sent to the firstResponder in the keyWindow. -// Note, that the UIEvent here will be an empty non-touch one and has no real purpose in the present implementation :) -- (void)keyPressed:(UIKey *)key withEvent:(UIEvent *)event; - @end @interface NSObject (UIResponderAppKitIntegrationKeyboardActions) // This is triggered from AppKit's cancelOperation: so it should be sent in largely the same circumstances. Generally you can think of it as mapping // to the ESC key, but CMD-. (period) also maps to it. -- (void)cancel:(id)sender; +- (void)cancelOperation:(id)sender; // This is mapped to CMD-Return and Enter and does not come from AppKit since it has no such convention as far as I've found. However it seemed like // a useful thing to define, really, so that's what I'm doing. :) -- (void)commit:(id)sender; +- (void)commitOperation:(id)sender; @end diff --git a/UIKit/Classes/UIResponderAppKitIntegration.m b/UIKit/Classes/UIResponderAppKitIntegration.m index 72fe6dce..01132a02 100644 --- a/UIKit/Classes/UIResponderAppKitIntegration.m +++ b/UIKit/Classes/UIResponderAppKitIntegration.m @@ -28,7 +28,6 @@ */ #import "UIResponderAppKitIntegration.h" -#import "UIEvent+UIPrivate.h" @implementation UIResponder (AppKitIntegration) @@ -42,29 +41,24 @@ - (void)rightClick:(UITouch *)touch withEvent:(UIEvent *)event [[self nextResponder] rightClick:touch withEvent:event]; } -- (void)mouseExitedView:(UIView *)exited enteredView:(UIView *)entered withEvent:(UIEvent *)event +- (void)mouseEntered:(UIView *)view withEvent:(UIEvent *)event { - [[self nextResponder] mouseExitedView:exited enteredView:entered withEvent:event]; + [[self nextResponder] mouseEntered:view withEvent:event]; } -- (void)mouseMoved:(CGPoint)delta withEvent:(UIEvent *)event +- (void)mouseMoved:(UITouch *)touch withEvent:(UIEvent *)event { - [[self nextResponder] mouseMoved:delta withEvent:event]; + [[self nextResponder] mouseMoved:touch withEvent:event]; } -- (id)mouseCursorForEvent:(UIEvent *)event +- (void)mouseExited:(UIView *)view withEvent:(UIEvent *)event { - return [[self nextResponder] mouseCursorForEvent:event]; + [[self nextResponder] mouseExited:view withEvent:event]; } -- (void)keyPressed:(UIKey *)key withEvent:(UIEvent *)event +- (id)mouseCursorForEvent:(UIEvent *)event { - UIResponder *responder = [self nextResponder]; - if (responder) { - [responder keyPressed:key withEvent:event]; - } else { - [event _setUnhandledKeyPressEvent]; - } + return [[self nextResponder] mouseCursorForEvent:event]; } @end diff --git a/UIKit/Classes/UIRotationGestureRecognizer.h b/UIKit/Classes/UIRotationGestureRecognizer.h index e53d31ed..ee81d3be 100644 --- a/UIKit/Classes/UIRotationGestureRecognizer.h +++ b/UIKit/Classes/UIRotationGestureRecognizer.h @@ -29,11 +29,7 @@ #import "UIGestureRecognizer.h" -@interface UIRotationGestureRecognizer : UIGestureRecognizer { - CGFloat _rotation; -} - +@interface UIRotationGestureRecognizer : UIGestureRecognizer @property (nonatomic) CGFloat rotation; @property (nonatomic,readonly) CGFloat velocity; - @end diff --git a/UIKit/Classes/UIRotationGestureRecognizer.m b/UIKit/Classes/UIRotationGestureRecognizer.m index e604ad4f..745957b9 100644 --- a/UIKit/Classes/UIRotationGestureRecognizer.m +++ b/UIKit/Classes/UIRotationGestureRecognizer.m @@ -31,7 +31,6 @@ #import "UIGestureRecognizerSubclass.h" @implementation UIRotationGestureRecognizer -@synthesize rotation=_rotation; - (id)initWithTarget:(id)target action:(SEL)action { diff --git a/UIKit/Classes/UIScreen+UIPrivate.h b/UIKit/Classes/UIScreen+UIPrivate.h index b6f98330..696ace6c 100644 --- a/UIKit/Classes/UIScreen+UIPrivate.h +++ b/UIKit/Classes/UIScreen+UIPrivate.h @@ -29,13 +29,13 @@ #import "UIScreen.h" -@class UIView, UIEvent; +@class UIKitView, CALayer; @interface UIScreen (UIPrivate) - (void)_setUIKitView:(UIKitView *)theView; +- (void)_setKeyWindow:(UIWindow *)window; +- (void)_addWindow:(UIWindow *)window; +- (void)_removeWindow:(UIWindow *)window; - (CALayer *)_layer; - (BOOL)_hasResizeIndicator; -- (void)_setPopoverController:(UIPopoverController *)controller; -- (UIPopoverController *)_popoverController; -- (UIView *)_hitTest:(CGPoint)clickPoint event:(UIEvent *)theEvent; @end diff --git a/UIKit/Classes/UIScreen.h b/UIKit/Classes/UIScreen.h index 78a8cd79..6a432150 100644 --- a/UIKit/Classes/UIScreen.h +++ b/UIKit/Classes/UIScreen.h @@ -34,24 +34,16 @@ extern NSString *const UIScreenDidConnectNotification; extern NSString *const UIScreenDidDisconnectNotification; extern NSString *const UIScreenModeDidChangeNotification; -@class UIImageView, CALayer, UIKitView, UIScreenMode, UIPopoverController; - -@interface UIScreen : NSObject { -@private - UIImageView *_grabber; - CALayer *_layer; - __unsafe_unretained UIKitView *_UIKitView; - UIScreenMode *_currentMode; - __unsafe_unretained UIPopoverController *_popoverController; -} +@class UIKitView, UIScreenMode, UIWindow; +@interface UIScreen : NSObject + (UIScreen *)mainScreen; + (NSArray *)screens; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readonly) CGRect applicationFrame; @property (nonatomic, readonly, copy) NSArray *availableModes; // only ever returns the currentMode -@property (nonatomic, retain) UIScreenMode *currentMode; // ignores any attempt to set this +@property (nonatomic, strong) UIScreenMode *currentMode; // ignores any attempt to set this @property (nonatomic, readonly) CGFloat scale; - +@property (nonatomic) CGFloat brightness; // not implemented, of course @end diff --git a/UIKit/Classes/UIScreen.m b/UIKit/Classes/UIScreen.m index 0d1bae52..8bcd2187 100644 --- a/UIKit/Classes/UIScreen.m +++ b/UIKit/Classes/UIScreen.m @@ -28,18 +28,16 @@ */ #import "UIScreen.h" -#import "UIScreenAppKitIntegration.h" #import "UIImage+UIPrivate.h" #import "UIImageView.h" #import "UIApplication.h" -#import -#import #import "UIViewLayoutManager.h" -#import "UIColor.h" #import "UIScreenMode+UIPrivate.h" #import "UIWindow.h" #import "UIKitView.h" #import "UIView+UIPrivate.h" +#import +#import NSString *const UIScreenDidConnectNotification = @"UIScreenDidConnectNotification"; NSString *const UIScreenDidDisconnectNotification = @"UIScreenDidDisconnectNotification"; @@ -47,8 +45,13 @@ NSMutableArray *_allScreens = nil; -@implementation UIScreen -@synthesize currentMode=_currentMode; +@implementation UIScreen { + UIImageView *_grabber; + CALayer *_layer; + NSMutableArray *_windows; + __weak UIKitView *_UIKitView; + __weak UIWindow *_keyWindow; +} + (void)initialize { @@ -76,10 +79,13 @@ + (NSArray *)screens - (id)init { if ((self = [super init])) { - _layer = [[CALayer layer] retain]; + _layer = [CALayer layer]; _layer.delegate = self; // required to get the magic of the UIViewLayoutManager... _layer.layoutManager = [UIViewLayoutManager layoutManager]; + _windows = [[NSMutableArray alloc] init]; + _brightness = 1; + _grabber = [[UIImageView alloc] initWithImage:[UIImage _windowResizeGrabberImage]]; _grabber.layer.zPosition = 10000; [_layer addSublayer:_grabber.layer]; @@ -97,12 +103,6 @@ - (void)dealloc [_grabber.layer removeFromSuperlayer]; [_layer removeFromSuperlayer]; - - [_grabber release]; - [_layer release]; - [_currentMode release]; - - [super dealloc]; } - (CGFloat)scale @@ -114,16 +114,6 @@ - (CGFloat)scale } } -- (void)_setPopoverController:(UIPopoverController *)controller -{ - _popoverController = controller; -} - -- (UIPopoverController *)_popoverController -{ - return _popoverController; -} - - (BOOL)_hasResizeIndicator { NSWindow *realWindow = [_UIKitView window]; @@ -189,11 +179,7 @@ - (void)_UIKitViewFrameDidChange - (void)_NSScreenDidChange { - for (UIWindow *window in [[UIApplication sharedApplication].windows reverseObjectEnumerator]) { - if (window.screen == self) { - [window _didMoveToScreen]; - } - } + [self.windows makeObjectsPerformSelector:@selector(_didMoveToScreen)]; } - (void)_setUIKitView:(id)theView @@ -217,24 +203,44 @@ - (void)_setUIKitView:(id)theView } } +- (UIKitView *)UIKitView +{ + return _UIKitView; +} + - (NSArray *)availableModes { return (self.currentMode)? [NSArray arrayWithObject:self.currentMode] : nil; } -- (UIView *)_hitTest:(CGPoint)clickPoint event:(UIEvent *)theEvent +- (void)_addWindow:(UIWindow *)window { - for (UIWindow *window in [[UIApplication sharedApplication].windows reverseObjectEnumerator]) { - if (window.screen == self) { - CGPoint windowPoint = [window convertPoint:clickPoint fromWindow:nil]; - UIView *clickedView = [window hitTest:windowPoint withEvent:theEvent]; - if (clickedView) { - return clickedView; - } - } + [_windows addObject:[NSValue valueWithNonretainedObject:window]]; +} + +- (void)_removeWindow:(UIWindow *)window +{ + if (_keyWindow == window) { + _keyWindow = nil; } - - return nil; + + [_windows removeObject:[NSValue valueWithNonretainedObject:window]]; +} + +- (NSArray *)windows +{ + return [_windows valueForKey:@"nonretainedObjectValue"]; +} + +- (UIWindow *)keyWindow +{ + return _keyWindow; +} + +- (void)_setKeyWindow:(UIWindow *)window +{ + NSAssert([self.windows containsObject:window], @"cannot set key window to a window not on this screen"); + _keyWindow = window; } - (NSString *)description diff --git a/UIKit/Classes/UIScreenAppKitIntegration.h b/UIKit/Classes/UIScreenAppKitIntegration.h index a533af85..5e0358e4 100644 --- a/UIKit/Classes/UIScreenAppKitIntegration.h +++ b/UIKit/Classes/UIScreenAppKitIntegration.h @@ -28,10 +28,22 @@ */ #import "UIScreen.h" +#import "UIKitView.h" @interface UIScreen (AppKitIntegration) + +// the windows that make this screen their home +@property (nonatomic, readonly, copy) NSArray *windows; + +// the window from the -windows array which is this screen's key window. this is not really how iOS is likely to work +// as iOS seems to track a single key window for the whole app, but on OSX the user can change the key window out from +// under the app, so this entire thing has to be managed differently. my design here is that each screen has a potential +// key window which is what is set when a UIWindow is told to become key. the app's keyWindow (as reported by UIApplication) +// will be the keyWindow of the screen that's currently on the NSWindow that's key.... yeah... confusing, eh? +@property (nonatomic, readonly) UIWindow *keyWindow; + // the real NSView that the screen lives on (or nil if there isn't one) -- (UIKitView *)UIKitView; +@property (nonatomic, readonly) UIKitView *UIKitView; // promotes this screen to the main screen // this only changes what [UIScreen mainScreen] returns in the future, it doesn't move anything between views, etc. diff --git a/UIKit/Classes/UIScreenAppKitIntegration.m b/UIKit/Classes/UIScreenAppKitIntegration.m index 6fb63c4e..05443ad1 100644 --- a/UIKit/Classes/UIScreenAppKitIntegration.m +++ b/UIKit/Classes/UIScreenAppKitIntegration.m @@ -35,10 +35,7 @@ extern NSMutableArray *_allScreens; @implementation UIScreen (AppKitIntegration) -- (UIKitView *)UIKitView -{ - return _UIKitView; -} +@dynamic UIKitView, windows, keyWindow; - (CGPoint)convertPoint:(CGPoint)toConvert toScreen:(UIScreen *)toScreen { @@ -46,11 +43,11 @@ - (CGPoint)convertPoint:(CGPoint)toConvert toScreen:(UIScreen *)toScreen return toConvert; } else { // Go all the way through OSX screen coordinates. - NSPoint screenCoords = [[_UIKitView window] convertBaseToScreen:[_UIKitView convertPoint:NSPointFromCGPoint(toConvert) toView:nil]]; + NSPoint screenCoords = [[self.UIKitView window] convertBaseToScreen:[self.UIKitView convertPoint:NSPointFromCGPoint(toConvert) toView:nil]]; if (toScreen) { // Now from there back to the toScreen's window's base - return NSPointToCGPoint([[toScreen UIKitView] convertPoint:[[[toScreen UIKitView] window] convertScreenToBase:screenCoords] fromView:nil]); + return NSPointToCGPoint([toScreen.UIKitView convertPoint:[[toScreen.UIKitView window] convertScreenToBase:screenCoords] fromView:nil]); } else { return NSPointToCGPoint(screenCoords); } @@ -66,13 +63,13 @@ - (CGPoint)convertPoint:(CGPoint)toConvert fromScreen:(UIScreen *)fromScreen if (fromScreen) { // Go all the way through OSX screen coordinates. - screenCoords = [[[fromScreen UIKitView] window] convertBaseToScreen:[[fromScreen UIKitView] convertPoint:NSPointFromCGPoint(toConvert) toView:nil]]; + screenCoords = [[fromScreen.UIKitView window] convertBaseToScreen:[fromScreen.UIKitView convertPoint:NSPointFromCGPoint(toConvert) toView:nil]]; } else { screenCoords = NSPointFromCGPoint(toConvert); } // Now from there back to the our screen - return NSPointToCGPoint([_UIKitView convertPoint:[[_UIKitView window] convertScreenToBase:screenCoords] fromView:nil]); + return NSPointToCGPoint([self.UIKitView convertPoint:[[self.UIKitView window] convertScreenToBase:screenCoords] fromView:nil]); } } diff --git a/UIKit/Classes/UIScreenMode.h b/UIKit/Classes/UIScreenMode.h index 8f7c646a..ee134047 100644 --- a/UIKit/Classes/UIScreenMode.h +++ b/UIKit/Classes/UIScreenMode.h @@ -29,12 +29,7 @@ #import -@interface UIScreenMode : NSObject { - CGFloat _pixelAspectRatio; - CGSize _size; -} - +@interface UIScreenMode : NSObject @property (readonly,nonatomic) CGFloat pixelAspectRatio; @property (readonly,nonatomic) CGSize size; - @end diff --git a/UIKit/Classes/UIScreenMode.m b/UIKit/Classes/UIScreenMode.m index 2496f8a7..a8ac7eb6 100644 --- a/UIKit/Classes/UIScreenMode.m +++ b/UIKit/Classes/UIScreenMode.m @@ -32,7 +32,6 @@ #import @implementation UIScreenMode -@synthesize pixelAspectRatio=_pixelAspectRatio, size=_size; + (id)screenModeWithNSView:(NSView *)theNSView { @@ -40,7 +39,7 @@ + (id)screenModeWithNSView:(NSView *)theNSView UIScreenMode *mode = [[self alloc] init]; mode->_size = NSSizeToCGSize([theNSView bounds].size); mode->_pixelAspectRatio = 1; - return [mode autorelease]; + return mode; } else { return nil; } diff --git a/UIKit/Classes/UIScrollView.h b/UIKit/Classes/UIScrollView.h index 35e1d137..609b9084 100644 --- a/UIKit/Classes/UIScrollView.h +++ b/UIKit/Classes/UIScrollView.h @@ -29,16 +29,16 @@ #import "UIView.h" -typedef enum { +typedef NS_ENUM(NSInteger, UIScrollViewIndicatorStyle) { UIScrollViewIndicatorStyleDefault, UIScrollViewIndicatorStyleBlack, UIScrollViewIndicatorStyleWhite -} UIScrollViewIndicatorStyle; +}; extern const float UIScrollViewDecelerationRateNormal; extern const float UIScrollViewDecelerationRateFast; -@class UIScroller, UIImageView, UIScrollView, UIPanGestureRecognizer, UIScrollWheelGestureRecognizer; +@class UIImageView, UIScrollView, UIPanGestureRecognizer, UIScrollWheelGestureRecognizer; @protocol UIScrollViewDelegate @optional @@ -52,64 +52,13 @@ extern const float UIScrollViewDecelerationRateFast; - (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view; - (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale; - (void)scrollViewDidZoom:(UIScrollView *)scrollView; +- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView; @end -@interface UIScrollView : UIView { -@package - __unsafe_unretained id _delegate; -@private - CGPoint _contentOffset; - CGSize _contentSize; - UIEdgeInsets _contentInset; - UIEdgeInsets _scrollIndicatorInsets; - UIScroller *_verticalScroller; - UIScroller *_horizontalScroller; - BOOL _showsVerticalScrollIndicator; - BOOL _showsHorizontalScrollIndicator; - float _maximumZoomScale; - float _minimumZoomScale; - BOOL _scrollsToTop; - UIScrollViewIndicatorStyle _indicatorStyle; - BOOL _delaysContentTouches; - BOOL _canCancelContentTouches; - BOOL _pagingEnabled; - float _decelerationRate; - - BOOL _bouncesZoom; - BOOL _bounces; - BOOL _zooming; - BOOL _dragging; - BOOL _decelerating; - - UIPanGestureRecognizer *_panGestureRecognizer; - UIScrollWheelGestureRecognizer *_scrollWheelGestureRecognizer; - - id _scrollAnimation; - NSTimer *_scrollTimer; - - struct { - unsigned scrollViewDidScroll : 1; - unsigned scrollViewWillBeginDragging : 1; - unsigned scrollViewDidEndDragging : 1; - unsigned viewForZoomingInScrollView : 1; - unsigned scrollViewWillBeginZooming : 1; - unsigned scrollViewDidEndZooming : 1; - unsigned scrollViewDidZoom : 1; - unsigned scrollViewDidEndScrollingAnimation : 1; - unsigned scrollViewWillBeginDecelerating : 1; - unsigned scrollViewDidEndDecelerating : 1; - } _delegateCan; - - // should be flag struct - BOOL _alwaysBounceHorizontal; - BOOL _alwaysBounceVertical; -} - +@interface UIScrollView : UIView - (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated; - - (void)setZoomScale:(float)scale animated:(BOOL)animated; - (void)zoomToRect:(CGRect)rect animated:(BOOL)animated; - - (void)setContentOffset:(CGPoint)theOffset animated:(BOOL)animated; - (void)flashScrollIndicators; // does nothing @@ -128,21 +77,18 @@ extern const float UIScrollViewDecelerationRateFast; @property (nonatomic) BOOL scrollsToTop; // no effect @property (nonatomic) BOOL delaysContentTouches; // no effect @property (nonatomic) BOOL canCancelContentTouches; // no effect +@property (nonatomic, getter=isDirectionalLockEnabled) BOOL directionalLockEnabled; // no effect @property (nonatomic, readonly, getter=isDragging) BOOL dragging; @property (nonatomic, readonly, getter=isTracking) BOOL tracking; // always returns NO @property (nonatomic, readonly, getter=isDecelerating) BOOL decelerating; // always returns NO @property (nonatomic, assign) BOOL pagingEnabled; @property (nonatomic) float decelerationRate; - @property (nonatomic) float maximumZoomScale; @property (nonatomic) float minimumZoomScale; @property (nonatomic) float zoomScale; @property (nonatomic, readonly, getter=isZooming) BOOL zooming; @property (nonatomic, readonly, getter=isZoomBouncing) BOOL zoomBouncing; // always NO @property (nonatomic) BOOL bouncesZoom; // no effect - @property (nonatomic, readonly) UIPanGestureRecognizer *panGestureRecognizer; @property (nonatomic, readonly) UIScrollWheelGestureRecognizer *scrollWheelGestureRecognizer; // non-standard - - @end diff --git a/UIKit/Classes/UIScrollView.m b/UIKit/Classes/UIScrollView.m index 6db238a9..d4e3b2f1 100644 --- a/UIKit/Classes/UIScrollView.m +++ b/UIKit/Classes/UIScrollView.m @@ -28,13 +28,8 @@ */ #import "UIScrollView.h" -#import "UIView+UIPrivate.h" #import "UIScroller.h" -#import "UIScreen+UIPrivate.h" -#import "UIWindow.h" #import "UITouch.h" -#import "UIImageView.h" -#import "UIImage+UIPrivate.h" #import "UIResponderAppKitIntegration.h" #import "UIScrollViewAnimationScroll.h" #import "UIScrollViewAnimationDeceleration.h" @@ -52,14 +47,26 @@ @interface UIScrollView () <_UIScrollerDelegate> @end -@implementation UIScrollView -@synthesize contentOffset=_contentOffset, contentInset=_contentInset, scrollIndicatorInsets=_scrollIndicatorInsets; -@synthesize showsHorizontalScrollIndicator=_showsHorizontalScrollIndicator, showsVerticalScrollIndicator=_showsVerticalScrollIndicator, contentSize=_contentSize; -@synthesize maximumZoomScale=_maximumZoomScale, minimumZoomScale=_minimumZoomScale, scrollsToTop=_scrollsToTop; -@synthesize indicatorStyle=_indicatorStyle, delaysContentTouches=_delaysContentTouches, delegate=_delegate, pagingEnabled=_pagingEnabled; -@synthesize canCancelContentTouches=_canCancelContentTouches, bouncesZoom=_bouncesZoom, zooming=_zooming; -@synthesize alwaysBounceVertical=_alwaysBounceVertical, alwaysBounceHorizontal=_alwaysBounceHorizontal, bounces=_bounces; -@synthesize decelerationRate=_decelerationRate, scrollWheelGestureRecognizer=_scrollWheelGestureRecognizer, panGestureRecognizer=_panGestureRecognizer; +@implementation UIScrollView { + UIScroller *_verticalScroller; + UIScroller *_horizontalScroller; + + UIScrollViewAnimation *_scrollAnimation; + NSTimer *_scrollTimer; + + struct { + unsigned scrollViewDidScroll : 1; + unsigned scrollViewWillBeginDragging : 1; + unsigned scrollViewDidEndDragging : 1; + unsigned viewForZoomingInScrollView : 1; + unsigned scrollViewWillBeginZooming : 1; + unsigned scrollViewDidEndZooming : 1; + unsigned scrollViewDidZoom : 1; + unsigned scrollViewDidEndScrollingAnimation : 1; + unsigned scrollViewWillBeginDecelerating : 1; + unsigned scrollViewDidEndDecelerating : 1; + } _delegateCan; +} - (id)initWithFrame:(CGRect)frame { @@ -108,12 +115,6 @@ - (void)dealloc _horizontalScroller.delegate = nil; _verticalScroller.delegate = nil; - [_panGestureRecognizer release]; - [_scrollWheelGestureRecognizer release]; - [_scrollAnimation release]; - [_verticalScroller release]; - [_horizontalScroller release]; - [super dealloc]; } - (void)setDelegate:(id)newDelegate @@ -194,7 +195,6 @@ - (void)_cancelScrollAnimation [_scrollTimer invalidate]; _scrollTimer = nil; - [_scrollAnimation release]; _scrollAnimation = nil; if (_delegateCan.scrollViewDidEndScrollingAnimation) { @@ -222,7 +222,8 @@ - (void)_updateScrollAnimation - (void)_setScrollAnimation:(UIScrollViewAnimation *)animation { [self _cancelScrollAnimation]; - _scrollAnimation = [animation retain]; + + _scrollAnimation = animation; if (!_scrollTimer) { _scrollTimer = [NSTimer scheduledTimerWithTimeInterval:1/(NSTimeInterval)UIScrollViewScrollAnimationFramesPerSecond target:self selector:@selector(_updateScrollAnimation) userInfo:nil repeats:YES]; @@ -317,27 +318,38 @@ - (void)insertSubview:(UIView *)subview atIndex:(NSInteger)index [self _bringScrollersToFront]; } +- (void)_updateBounds +{ + CGRect bounds = self.bounds; + bounds.origin.x = _contentOffset.x - _contentInset.left; + bounds.origin.y = _contentOffset.y - _contentInset.top; + self.bounds = bounds; + + [self _updateScrollers]; + [self setNeedsLayout]; +} + - (void)setContentOffset:(CGPoint)theOffset animated:(BOOL)animated { if (animated) { - UIScrollViewAnimationScroll *animation = [[UIScrollViewAnimationScroll alloc] initWithScrollView:self - fromContentOffset:self.contentOffset - toContentOffset:theOffset - duration:UIScrollViewAnimationDuration - curve:UIScrollViewAnimationScrollCurveLinear]; - [self _setScrollAnimation:animation]; - [animation release]; + UIScrollViewAnimationScroll *animation = nil; + + if ([_scrollAnimation isKindOfClass:[UIScrollViewAnimationScroll class]]) { + animation = (UIScrollViewAnimationScroll *)_scrollAnimation; + } + + if (!animation || !CGPointEqualToPoint(theOffset, animation.endContentOffset)) { + [self _setScrollAnimation:[[UIScrollViewAnimationScroll alloc] initWithScrollView:self + fromContentOffset:self.contentOffset + toContentOffset:theOffset + duration:UIScrollViewAnimationDuration + curve:UIScrollViewAnimationScrollCurveLinear]]; + } } else { _contentOffset.x = roundf(theOffset.x); _contentOffset.y = roundf(theOffset.y); - CGRect bounds = self.bounds; - bounds.origin.x = _contentOffset.x+_contentInset.left; - bounds.origin.y = _contentOffset.y+_contentInset.top; - self.bounds = bounds; - - [self _updateScrollers]; - [self setNeedsLayout]; + [self _updateBounds]; if (_delegateCan.scrollViewDidScroll) { [_delegate scrollViewDidScroll:self]; @@ -350,6 +362,20 @@ - (void)setContentOffset:(CGPoint)theOffset [self setContentOffset:theOffset animated:NO]; } +- (void)setContentInset:(UIEdgeInsets)contentInset +{ + if (!UIEdgeInsetsEqualToEdgeInsets(contentInset, _contentInset)) { + const CGFloat x = contentInset.left - _contentInset.left; + const CGFloat y = contentInset.top - _contentInset.top; + + _contentInset = contentInset; + _contentOffset.x -= x; + _contentOffset.y -= y; + + [self _updateBounds]; + } +} + - (void)setContentSize:(CGSize)newSize { if (!CGSizeEqualToSize(newSize, _contentSize)) { @@ -375,33 +401,6 @@ - (BOOL)isTracking return NO; } -- (void)mouseMoved:(CGPoint)delta withEvent:(UIEvent *)event -{ - UITouch *touch = [[event allTouches] anyObject]; - const CGPoint point = [touch locationInView:self]; - const CGFloat scrollerSize = UIScrollerWidthForBoundsSize(self.bounds.size); - const BOOL shouldShowHorizontal = CGRectContainsPoint(CGRectInset(_horizontalScroller.frame, -scrollerSize, -scrollerSize), point); - const BOOL shouldShowVertical = CGRectContainsPoint(CGRectInset(_verticalScroller.frame, -scrollerSize, -scrollerSize), point); - const BOOL shouldShowScrollers = (shouldShowVertical || shouldShowHorizontal || _decelerating); - - _horizontalScroller.alwaysVisible = shouldShowScrollers; - _verticalScroller.alwaysVisible = shouldShowScrollers; - - [super mouseMoved:delta withEvent:event]; -} - -- (void)mouseExitedView:(UIView *)exited enteredView:(UIView *)entered withEvent:(UIEvent *)event -{ - if (!_decelerating) { - if ([exited isDescendantOfView:self] && ![entered isDescendantOfView:self]) { - _horizontalScroller.alwaysVisible = NO; - _verticalScroller.alwaysVisible = NO; - } - } - - [super mouseExitedView:exited enteredView:entered withEvent:event]; -} - - (UIScrollViewAnimation *)_pageSnapAnimation { const CGSize pageSize = self.bounds.size; @@ -428,11 +427,11 @@ - (UIScrollViewAnimation *)_pageSnapAnimation // quickly animate the snap (if necessary) if (!CGPointEqualToPoint(finalContentOffset, _contentOffset)) { - return [[[UIScrollViewAnimationScroll alloc] initWithScrollView:self + return [[UIScrollViewAnimationScroll alloc] initWithScrollView:self fromContentOffset:_contentOffset toContentOffset:finalContentOffset duration:UIScrollViewQuickAnimationDuration - curve:UIScrollViewAnimationScrollCurveQuadraticEaseOut] autorelease]; + curve:UIScrollViewAnimationScrollCurveQuadraticEaseOut]; } else { return nil; } @@ -452,8 +451,8 @@ - (UIScrollViewAnimation *)_decelerationAnimationWithVelocity:(CGPoint)velocity } if (!CGPointEqualToPoint(velocity, CGPointZero) || !CGPointEqualToPoint(confinedOffset, _contentOffset)) { - return [[[UIScrollViewAnimationDeceleration alloc] initWithScrollView:self - velocity:velocity] autorelease]; + return [[UIScrollViewAnimationDeceleration alloc] initWithScrollView:self + velocity:velocity]; } else { return nil; } @@ -475,11 +474,6 @@ - (void)_beginDragging } } -- (BOOL)isDragging -{ - return _dragging; -} - - (void)_endDraggingWithDecelerationVelocity:(CGPoint)velocity { if (_dragging) { @@ -598,9 +592,11 @@ - (void)_gestureDidChange:(UIGestureRecognizer *)gesture // messages can be preserved perfectly rather than trying to emulate them myself. this results // in a better feeling end product even if the bouncing at the edges isn't quite entirely right. // see notes in UIScrollViewAnimationDeceleration.m for more. - if ([_scrollAnimation respondsToSelector:@selector(momentumScrollBy:)]) { - [_scrollAnimation momentumScrollBy:delta]; - } + + // updated note: this used to be guarded by respondsToSelector: but I have instead added a blank + // implementation of -momentumScrollBy: to UIScrollAnimation's base class. If a specific animation + // cannot deal with a momentum scroll, then it will be ignored. + [_scrollAnimation momentumScrollBy:delta]; } else { CGPoint offset = self.contentOffset; offset.x += delta.x; @@ -645,11 +641,6 @@ - (void)_UIScrollerDidEndDragging:(UIScroller *)scroller withEvent:(UIEvent *)ev [self _endDraggingWithDecelerationVelocity:CGPointZero]; } -- (BOOL)isDecelerating -{ - return NO; -} - - (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated { const CGRect contentRect = CGRectMake(0,0,_contentSize.width, _contentSize.height); @@ -728,4 +719,57 @@ - (NSString *)description return [NSString stringWithFormat:@"<%@: %p; frame = (%.0f %.0f; %.0f %.0f); clipsToBounds = %@; layer = %@; contentOffset = {%.0f, %.0f}>", [self className], self, self.frame.origin.x, self.frame.origin.y, self.frame.size.width, self.frame.size.height, (self.clipsToBounds ? @"YES" : @"NO"), self.layer, self.contentOffset.x, self.contentOffset.y]; } +// after some experimentation, it seems UIScrollView blocks or captures the touch events that fall through and +// I'm not entirely sure why, but something is certainly going on there so I'm replicating that here. since I +// suspect it's just stopping everything from going through, I'm also capturing and ignoring some of the +// mouse-related responder events added by Chameleon rather than passing them along the responder chain, too. +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event +{ +} + +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event +{ +} + +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event +{ +} + +- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event +{ +} + +- (void)scrollWheelMoved:(CGPoint)delta withEvent:(UIEvent *)event +{ +} + +- (void)rightClick:(UITouch *)touch withEvent:(UIEvent *)event +{ +} + +- (void)mouseMoved:(UITouch *)touch withEvent:(UIEvent *)event +{ + const CGPoint point = [touch locationInView:self]; + const CGFloat scrollerSize = UIScrollerWidthForBoundsSize(self.bounds.size); + const BOOL shouldShowHorizontal = CGRectContainsPoint(CGRectInset(_horizontalScroller.frame, -scrollerSize, -scrollerSize), point); + const BOOL shouldShowVertical = CGRectContainsPoint(CGRectInset(_verticalScroller.frame, -scrollerSize, -scrollerSize), point); + const BOOL shouldShowScrollers = (shouldShowVertical || shouldShowHorizontal || _decelerating); + + _horizontalScroller.alwaysVisible = shouldShowScrollers; + _verticalScroller.alwaysVisible = shouldShowScrollers; +} + +- (void)mouseExited:(UIView *)view withEvent:(UIEvent *)event +{ + if (!_decelerating) { + _horizontalScroller.alwaysVisible = NO; + _verticalScroller.alwaysVisible = NO; + } +} + +- (id)mouseCursorForEvent:(UIEvent *)event +{ + return nil; +} + @end diff --git a/UIKit/Classes/UIScrollViewAnimation.h b/UIKit/Classes/UIScrollViewAnimation.h index 7432d428..a9406f1a 100644 --- a/UIKit/Classes/UIScrollViewAnimation.h +++ b/UIKit/Classes/UIScrollViewAnimation.h @@ -29,15 +29,13 @@ #import "UIScrollView+UIPrivate.h" -@interface UIScrollViewAnimation : NSObject { -@package - UIScrollView *scrollView; - NSTimeInterval beginTime; -} - +@interface UIScrollViewAnimation : NSObject - (id)initWithScrollView:(UIScrollView *)sv; - (BOOL)animate; +- (void)momentumScrollBy:(CGPoint)delta; +@property (nonatomic, readonly) UIScrollView *scrollView; +@property (nonatomic, assign) NSTimeInterval beginTime; @end extern CGFloat UILinearInterpolation(CGFloat t, CGFloat start, CGFloat end); diff --git a/UIKit/Classes/UIScrollViewAnimation.m b/UIKit/Classes/UIScrollViewAnimation.m index eb6d149f..1e8297f2 100644 --- a/UIKit/Classes/UIScrollViewAnimation.m +++ b/UIKit/Classes/UIScrollViewAnimation.m @@ -56,8 +56,8 @@ @implementation UIScrollViewAnimation - (id)initWithScrollView:(UIScrollView *)sv { if ((self=[super init])) { - scrollView = sv; - beginTime = [NSDate timeIntervalSinceReferenceDate]; + _scrollView = sv; + _beginTime = [NSDate timeIntervalSinceReferenceDate]; } return self; } @@ -67,4 +67,9 @@ - (BOOL)animate return YES; } +- (void)momentumScrollBy:(CGPoint)delta +{ + // does nothing +} + @end diff --git a/UIKit/Classes/UIScrollViewAnimationDeceleration.h b/UIKit/Classes/UIScrollViewAnimationDeceleration.h index 5f747acd..4f822180 100644 --- a/UIKit/Classes/UIScrollViewAnimationDeceleration.h +++ b/UIKit/Classes/UIScrollViewAnimationDeceleration.h @@ -38,15 +38,9 @@ typedef struct { BOOL bounced; } UIScrollViewAnimationDecelerationComponent; -@interface UIScrollViewAnimationDeceleration : UIScrollViewAnimation { - UIScrollViewAnimationDecelerationComponent x; - UIScrollViewAnimationDecelerationComponent y; - NSTimeInterval lastMomentumTime; -} - +@interface UIScrollViewAnimationDeceleration : UIScrollViewAnimation - (id)initWithScrollView:(UIScrollView *)sv velocity:(CGPoint)v; - (void)momentumScrollBy:(CGPoint)delta; - @end diff --git a/UIKit/Classes/UIScrollViewAnimationDeceleration.m b/UIKit/Classes/UIScrollViewAnimationDeceleration.m index dac17cab..7b27db7e 100644 --- a/UIKit/Classes/UIScrollViewAnimationDeceleration.m +++ b/UIKit/Classes/UIScrollViewAnimationDeceleration.m @@ -121,41 +121,45 @@ static BOOL BounceComponent(NSTimeInterval t, UIScrollViewAnimationDecelerationC } } -@implementation UIScrollViewAnimationDeceleration +@implementation UIScrollViewAnimationDeceleration { + UIScrollViewAnimationDecelerationComponent _x; + UIScrollViewAnimationDecelerationComponent _y; + NSTimeInterval _lastMomentumTime; +} - (id)initWithScrollView:(UIScrollView *)sv velocity:(CGPoint)v; { if ((self=[super initWithScrollView:sv])) { - lastMomentumTime = beginTime; - - x.decelerateTime = beginTime; - x.velocity = ClampedVelocty(v.x); - x.position = scrollView.contentOffset.x; - x.returnFrom = 0; - x.returnTime = 0; - x.bounced = NO; - - y.decelerateTime = beginTime; - y.velocity = ClampedVelocty(v.y); - y.position = scrollView.contentOffset.y; - y.returnFrom = 0; - y.returnTime = 0; - y.bounced = NO; + _lastMomentumTime = self.beginTime; + + _x.decelerateTime = self.beginTime; + _x.velocity = ClampedVelocty(v.x); + _x.position = self.scrollView.contentOffset.x; + _x.returnFrom = 0; + _x.returnTime = 0; + _x.bounced = NO; + + _y.decelerateTime = self.beginTime; + _y.velocity = ClampedVelocty(v.y); + _y.position = self.scrollView.contentOffset.y; + _y.returnFrom = 0; + _y.returnTime = 0; + _y.bounced = NO; // if the velocity is 0, we're going to assume we just need to return it back to position immediately // this works around the case where the content was already at an edge and the user just flicked in // such a way that it should bounce a bit and return to the proper offset. not doing something like this // (along with the associated code in UIScrollView) results in crazy forces being applied in those cases. - if (x.velocity == 0) { - x.bounced = YES; - x.returnTime = beginTime; - x.returnFrom = x.position; + if (_x.velocity == 0) { + _x.bounced = YES; + _x.returnTime = self.beginTime; + _x.returnFrom = _x.position; } - if (y.velocity == 0) { - y.bounced = YES; - y.returnTime = beginTime; - y.returnFrom = y.position; + if (_y.velocity == 0) { + _y.bounced = YES; + _y.returnTime = self.beginTime; + _y.returnFrom = _y.position; } } return self; @@ -164,40 +168,40 @@ - (id)initWithScrollView:(UIScrollView *)sv velocity:(CGPoint)v; - (BOOL)animate { const NSTimeInterval currentTime = [NSDate timeIntervalSinceReferenceDate]; - const BOOL isFinishedWaitingForMomentumScroll = ((currentTime - lastMomentumTime) > 0.15f); + const BOOL isFinishedWaitingForMomentumScroll = ((currentTime - _lastMomentumTime) > 0.15f); BOOL finished = NO; - while (!finished && currentTime >= beginTime) { - CGPoint confinedOffset = [scrollView _confinedContentOffset:CGPointMake(x.position, y.position)]; + while (!finished && currentTime >= self.beginTime) { + CGPoint confinedOffset = [self.scrollView _confinedContentOffset:CGPointMake(_x.position, _y.position)]; - const BOOL verticalIsFinished = BounceComponent(beginTime, &y, confinedOffset.y); - const BOOL horizontalIsFinished = BounceComponent(beginTime, &x, confinedOffset.x); + const BOOL verticalIsFinished = BounceComponent(self.beginTime, &_y, confinedOffset.y); + const BOOL horizontalIsFinished = BounceComponent(self.beginTime, &_x, confinedOffset.x); finished = (verticalIsFinished && horizontalIsFinished && isFinishedWaitingForMomentumScroll); - beginTime += physicsTimeStep; + self.beginTime += physicsTimeStep; } - [scrollView _setRestrainedContentOffset:CGPointMake(x.position, y.position)]; + [self.scrollView _setRestrainedContentOffset:CGPointMake(_x.position, _y.position)]; return finished; } - (void)momentumScrollBy:(CGPoint)delta { - lastMomentumTime = [NSDate timeIntervalSinceReferenceDate]; + _lastMomentumTime = [NSDate timeIntervalSinceReferenceDate]; - if (!x.bounced) { - x.position += delta.x; - x.velocity = ClampedVelocty(delta.x / (lastMomentumTime - x.decelerateTime)); - x.decelerateTime = lastMomentumTime; + if (!_x.bounced) { + _x.position += delta.x; + _x.velocity = ClampedVelocty(delta.x / (_lastMomentumTime - _x.decelerateTime)); + _x.decelerateTime = _lastMomentumTime; } - if (!y.bounced) { - y.position += delta.y; - y.velocity = ClampedVelocty(delta.y / (lastMomentumTime - y.decelerateTime)); - y.decelerateTime = lastMomentumTime; + if (!_y.bounced) { + _y.position += delta.y; + _y.velocity = ClampedVelocty(delta.y / (_lastMomentumTime - _y.decelerateTime)); + _y.decelerateTime = _lastMomentumTime; } } diff --git a/UIKit/Classes/UIScrollViewAnimationScroll.h b/UIKit/Classes/UIScrollViewAnimationScroll.h index c7b37c8e..4739063b 100644 --- a/UIKit/Classes/UIScrollViewAnimationScroll.h +++ b/UIKit/Classes/UIScrollViewAnimationScroll.h @@ -29,18 +29,16 @@ #import "UIScrollViewAnimation.h" -typedef enum { +typedef NS_ENUM(NSInteger, UIScrollViewAnimationScrollCurve) { UIScrollViewAnimationScrollCurveLinear, UIScrollViewAnimationScrollCurveQuadraticEaseOut -} UIScrollViewAnimationScrollCurve; - -@interface UIScrollViewAnimationScroll : UIScrollViewAnimation { - CGPoint beginContentOffset; - CGPoint endContentOffset; - NSTimeInterval duration; - UIScrollViewAnimationScrollCurve curve; -} +}; +@interface UIScrollViewAnimationScroll : UIScrollViewAnimation - (id)initWithScrollView:(UIScrollView *)sv fromContentOffset:(CGPoint)from toContentOffset:(CGPoint)to duration:(NSTimeInterval)d curve:(UIScrollViewAnimationScrollCurve)c; +@property (nonatomic, readonly) CGPoint beginContentOffset; +@property (nonatomic, readonly) CGPoint endContentOffset; +@property (nonatomic, readonly) NSTimeInterval duration; +@property (nonatomic, readonly) UIScrollViewAnimationScrollCurve animationCurve; @end diff --git a/UIKit/Classes/UIScrollViewAnimationScroll.m b/UIKit/Classes/UIScrollViewAnimationScroll.m index 014bef36..255136d4 100644 --- a/UIKit/Classes/UIScrollViewAnimationScroll.m +++ b/UIKit/Classes/UIScrollViewAnimationScroll.m @@ -34,10 +34,10 @@ @implementation UIScrollViewAnimationScroll - (id)initWithScrollView:(UIScrollView *)sv fromContentOffset:(CGPoint)from toContentOffset:(CGPoint)to duration:(NSTimeInterval)d curve:(UIScrollViewAnimationScrollCurve)c { if ((self=[super initWithScrollView:sv])) { - beginContentOffset = from; - endContentOffset = to; - duration = d; - curve = c; + _beginContentOffset = from; + _endContentOffset = to; + _duration = d; + _animationCurve = c; } return self; } @@ -45,13 +45,13 @@ - (id)initWithScrollView:(UIScrollView *)sv fromContentOffset:(CGPoint)from toCo - (BOOL)animate { const NSTimeInterval currentTime = [NSDate timeIntervalSinceReferenceDate]; - const NSTimeInterval elapsedTime = currentTime - beginTime; - const CGFloat animationPosition = MIN(1, (elapsedTime / duration)); + const NSTimeInterval elapsedTime = currentTime - self.beginTime; + const CGFloat animationPosition = MIN(1, (elapsedTime / _duration)); - CGFloat (*curveFunction)(CGFloat t, CGFloat start, CGFloat end) = (curve == UIScrollViewAnimationScrollCurveLinear)? &UILinearInterpolation : &UIQuadraticEaseOut; + CGFloat (*curveFunction)(CGFloat t, CGFloat start, CGFloat end) = (_animationCurve == UIScrollViewAnimationScrollCurveLinear)? &UILinearInterpolation : &UIQuadraticEaseOut; - scrollView.contentOffset = CGPointMake(curveFunction(animationPosition, beginContentOffset.x, endContentOffset.x), - curveFunction(animationPosition, beginContentOffset.y, endContentOffset.y)); + self.scrollView.contentOffset = CGPointMake(curveFunction(animationPosition, _beginContentOffset.x, _endContentOffset.x), + curveFunction(animationPosition, _beginContentOffset.y, _endContentOffset.y)); return (animationPosition == 1); } diff --git a/UIKit/Classes/UIScrollWheelGestureRecognizer.h b/UIKit/Classes/UIScrollWheelGestureRecognizer.h index 2ce4063d..a06a2543 100644 --- a/UIKit/Classes/UIScrollWheelGestureRecognizer.h +++ b/UIKit/Classes/UIScrollWheelGestureRecognizer.h @@ -33,11 +33,6 @@ // Unlike UIPanGestureRecognizer, this is a discrete recognizer. It is also, // obviously, entirely non-standard. :) -@interface UIScrollWheelGestureRecognizer : UIGestureRecognizer { - CGPoint _translation; -} - +@interface UIScrollWheelGestureRecognizer : UIGestureRecognizer - (CGPoint)translationInView:(UIView *)view; -- (void)setTranslation:(CGPoint)translation inView:(UIView *)view; - @end diff --git a/UIKit/Classes/UIScrollWheelGestureRecognizer.m b/UIKit/Classes/UIScrollWheelGestureRecognizer.m index 9d6d1b03..2ade616e 100644 --- a/UIKit/Classes/UIScrollWheelGestureRecognizer.m +++ b/UIKit/Classes/UIScrollWheelGestureRecognizer.m @@ -29,27 +29,31 @@ #import "UIScrollWheelGestureRecognizer.h" #import "UIGestureRecognizerSubclass.h" -#import "UITouch+UIPrivate.h" -#import "UIEvent.h" +#import "UITouchEvent.h" +#import "UITouch.h" -@implementation UIScrollWheelGestureRecognizer +@implementation UIScrollWheelGestureRecognizer { + CGPoint _translation; +} - (CGPoint)translationInView:(UIView *)view { return _translation; } -- (void)setTranslation:(CGPoint)translation inView:(UIView *)view -{ - _translation = translation; -} - -- (void)_discreteGestures:(NSSet *)touches withEvent:(UIEvent *)event +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { - UITouch *touch = [[event touchesForGestureRecognizer:self] anyObject]; - if (self.state == UIGestureRecognizerStatePossible && [touch _gesture] == _UITouchDiscreteGestureScrollWheel) { - [self setTranslation:[touch _delta] inView:touch.view]; - self.state = UIGestureRecognizerStateRecognized; + if (self.state == UIGestureRecognizerStatePossible) { + if ([event isKindOfClass:[UITouchEvent class]]) { + UITouchEvent *touchEvent = (UITouchEvent *)event; + + if (touchEvent.touchEventGesture == UITouchEventGestureScrollWheel) { + _translation = touchEvent.translation; + self.state = UIGestureRecognizerStateRecognized; + } else { + self.state = UIGestureRecognizerStateFailed; + } + } } } diff --git a/UIKit/Classes/UIScroller.h b/UIKit/Classes/UIScroller.h index a46fbf8a..b65d824e 100644 --- a/UIKit/Classes/UIScroller.h +++ b/UIKit/Classes/UIScroller.h @@ -40,20 +40,7 @@ CGFloat UIScrollerWidthForBoundsSize(CGSize boundsSize); - (void)_UIScrollerDidEndDragging:(UIScroller *)scroller withEvent:(UIEvent *)event; @end -@interface UIScroller : UIView { -@private - __unsafe_unretained id<_UIScrollerDelegate> _delegate; - CGFloat _contentOffset; - CGFloat _contentSize; - CGFloat _dragOffset; - BOOL _draggingKnob; - BOOL _isVertical; - CGPoint _lastTouchLocation; - NSTimer *_holdTimer; - UIScrollViewIndicatorStyle _indicatorStyle; - NSTimer *_fadeTimer; - BOOL _alwaysVisible; -} +@interface UIScroller : UIView // NOTE: UIScroller set's its own alpha to 0 when it is created, so it is NOT visible by default! // the flash/quickFlash methods alter its own alpha in order to fade in/out, etc. diff --git a/UIKit/Classes/UIScroller.m b/UIKit/Classes/UIScroller.m index cd7c7da7..3d02540b 100644 --- a/UIKit/Classes/UIScroller.m +++ b/UIKit/Classes/UIScroller.m @@ -50,9 +50,14 @@ CGFloat UIScrollerWidthForBoundsSize(CGSize boundsSize) } -@implementation UIScroller -@synthesize delegate=_delegate, contentOffset=_contentOffset, contentSize=_contentSize; -@synthesize indicatorStyle=_indicatorStyle, alwaysVisible=_alwaysVisible; +@implementation UIScroller { + CGFloat _dragOffset; + BOOL _draggingKnob; + BOOL _isVertical; + CGPoint _lastTouchLocation; + NSTimer *_holdTimer; + NSTimer *_fadeTimer; +} - (id)initWithFrame:(CGRect)frame { @@ -77,7 +82,7 @@ - (void)_fadeOut [UIView animateWithDuration:0.33 delay:0 - options:UIViewAnimationOptionCurveEaseOut | UIViewAnimationOptionTransitionNone | UIViewAnimationOptionAllowUserInteraction + options:UIViewAnimationOptionCurveEaseOut | UIViewAnimationOptionTransitionNone | UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionBeginFromCurrentState animations:^(void) { self.alpha = _UIScrollerMinimumAlpha; } @@ -97,7 +102,7 @@ - (void)_fadeIn [UIView animateWithDuration:0.33 delay:0 - options:UIViewAnimationOptionCurveEaseOut | UIViewAnimationOptionTransitionNone | UIViewAnimationOptionAllowUserInteraction + options:UIViewAnimationOptionCurveEaseOut | UIViewAnimationOptionTransitionNone | UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionBeginFromCurrentState animations:^(void) { self.alpha = 1; } diff --git a/UIKit/Classes/UISearchBar.h b/UIKit/Classes/UISearchBar.h index 31350b1d..a6336fe7 100644 --- a/UIKit/Classes/UISearchBar.h +++ b/UIKit/Classes/UISearchBar.h @@ -38,23 +38,15 @@ @protocol UISearchBarDelegate; -@interface UISearchBar : UIView { - UITextField *_searchField; - BOOL _showsCancelButton; - __unsafe_unretained id _delegate; - NSString *_placeholder; -} - +@interface UISearchBar : UIView @property (nonatomic, copy) NSString *text; -@property (nonatomic,assign) id delegate; +@property (nonatomic, assign) id delegate; @property (nonatomic) BOOL showsCancelButton; -@property (nonatomic,copy) NSString *placeholder; - +@property (nonatomic, copy) NSString *placeholder; @end @protocol UISearchBarDelegate - @optional - (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar; @@ -70,5 +62,4 @@ - (void)searchBarResultsListButtonClicked:(UISearchBar *)searchBar; - (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope; - @end diff --git a/UIKit/Classes/UISearchBar.m b/UIKit/Classes/UISearchBar.m index 4990b4f7..90fa4aff 100644 --- a/UIKit/Classes/UISearchBar.m +++ b/UIKit/Classes/UISearchBar.m @@ -35,8 +35,9 @@ #import "UISearchBar.h" -@implementation UISearchBar -@synthesize delegate=_delegate, showsCancelButton = _showsCancelButton, placeholder=_placeholder; +@implementation UISearchBar { + UITextField *_searchField; +} - (id)initWithFrame:(CGRect)frame { @@ -50,9 +51,6 @@ - (id)initWithFrame:(CGRect)frame - (void)dealloc { _delegate = nil; - [_placeholder release]; - [_searchField release]; - [super dealloc]; } - (NSString *)text diff --git a/UIKit/Classes/UISearchDisplayController.h b/UIKit/Classes/UISearchDisplayController.h index aa4406e2..a19fc66d 100644 --- a/UIKit/Classes/UISearchDisplayController.h +++ b/UIKit/Classes/UISearchDisplayController.h @@ -38,15 +38,7 @@ @class UISearchBar, UITableView, UIViewController, UIPopoverController; @protocol UITableViewDataSource, UITableViewDelegate, UISearchDisplayDelegate; -@interface UISearchDisplayController : NSObject { - UIViewController *_viewController; - UISearchBar *_searchBar; - UITableView *_tableView; - __unsafe_unretained id _delegate; - __unsafe_unretained id _tableViewDataSource; - __unsafe_unretained id _tableViewDelegate; -} - +@interface UISearchDisplayController : NSObject - (id)initWithSearchBar:(UISearchBar *)searchBar contentsController:(UIViewController *)viewController; @property (nonatomic, assign) id delegate; @@ -57,16 +49,14 @@ @property (nonatomic, readonly) UISearchBar *searchBar; @property (nonatomic, readonly) UIViewController *searchContentsController; -@property (nonatomic,readonly) UITableView *searchResultsTableView; -@property (nonatomic,assign) id searchResultsDataSource; -@property (nonatomic,assign) id searchResultsDelegate; - +@property (nonatomic, readonly) UITableView *searchResultsTableView; +@property (nonatomic, assign) id searchResultsDataSource; +@property (nonatomic, assign) id searchResultsDelegate; @end @protocol UISearchDisplayDelegate - @optional // when we start/end showing the search UI @@ -88,5 +78,4 @@ // return YES to reload table. called when search string/option changes. convenience methods on top UISearchBar delegate methods - (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString; - (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption; - @end diff --git a/UIKit/Classes/UISearchDisplayController.m b/UIKit/Classes/UISearchDisplayController.m index 32bafaa6..457d216b 100644 --- a/UIKit/Classes/UISearchDisplayController.m +++ b/UIKit/Classes/UISearchDisplayController.m @@ -38,20 +38,22 @@ #import "UIViewController.h" -@implementation UISearchDisplayController - +@implementation UISearchDisplayController { + UIViewController *_viewController; + __unsafe_unretained UITableView *_tableView; + __unsafe_unretained id _tableViewDataSource; + __unsafe_unretained id _tableViewDelegate; +} @synthesize searchContentsController = _viewController; -@synthesize searchBar = _searchBar; @synthesize searchResultsTableView = _tableView; @synthesize searchResultsDataSource = _tableViewDataSource; @synthesize searchResultsDelegate = _tableViewDelegate; -@synthesize delegate = _delegate; - (id)initWithSearchBar:(UISearchBar *)searchBar contentsController:(UIViewController *)viewController { if ((self = [super init])) { - _searchBar = [searchBar retain]; - _viewController = [viewController retain]; + _searchBar = searchBar; + _viewController = viewController; } return self; } @@ -61,9 +63,6 @@ - (void)dealloc _delegate = nil; _tableViewDataSource = nil; _tableViewDelegate = nil; - [_searchBar release]; - [_viewController release]; - [super dealloc]; } - (BOOL)isActive diff --git a/UIKit/Classes/UISegmentedControl.h b/UIKit/Classes/UISegmentedControl.h index 81fc4b97..dbc41c1c 100644 --- a/UIKit/Classes/UISegmentedControl.h +++ b/UIKit/Classes/UISegmentedControl.h @@ -12,75 +12,46 @@ // - Setting item content offset is not supported #import "UIControl.h" -#import "UIImage.h" -#import "UIFont.h" -typedef enum { - UISegmentedControlStylePlain, // large plain - UISegmentedControlStyleBordered, // large bordered - UISegmentedControlStyleBar, // small button/nav bar style. tintable - UISegmentedControlStyleBezeled, // large bezeled style. tintable -} UISegmentedControlStyle; +@class UIImage; -enum { - UISegmentedControlNoSegment = -1 // segment index for no selected segment +typedef NS_ENUM(NSInteger, UISegmentedControlStyle) { + UISegmentedControlStylePlain, // large plain + UISegmentedControlStyleBordered, // large bordered + UISegmentedControlStyleBar, // small button/nav bar style. tintable + UISegmentedControlStyleBezeled, // large bezeled style. tintable }; -@interface UISegmentedControl : UIControl { - -@private - - NSMutableArray *_segments; - NSInteger _selectedSegmentIndex; - NSUInteger _numberOfSegments; - BOOL _momentary; - NSMutableDictionary *_segmentMeta; - - UIImage *_buttonImage; - UIImage *_highlightedButtonImage; - UIImage *_dividerImage; - UIImage *_highlightedDividerImage; - - UIFont *_font; - UIColor *_textColor; - UIColor *_disabledTextColor; - UIColor *_textShadowColor; - CGSize _textShadowOffset; - UIEdgeInsets _textEdgeInsets; +enum { + UISegmentedControlNoSegment = -1 // segment index for no selected segment +}; - UISegmentedControlStyle _segmentedControlStyle; - UIColor *_tintColor; -} +typedef NS_ENUM(NSInteger, UISegmentedControlSegment) { + UISegmentedControlSegmentAny = 0, + UISegmentedControlSegmentLeft = 1, + UISegmentedControlSegmentCenter = 2, + UISegmentedControlSegmentRight = 3, + UISegmentedControlSegmentAlone = 4, +}; +@interface UISegmentedControl : UIControl @property (nonatomic) UISegmentedControlStyle segmentedControlStyle; // stub -@property (nonatomic,retain) UIColor *tintColor; // stub +@property (nonatomic,strong) UIColor *tintColor; // stub @property (nonatomic, assign, readonly) NSUInteger numberOfSegments; @property (nonatomic, assign) NSInteger selectedSegmentIndex; @property (nonatomic, getter=isMomentary) BOOL momentary; - (id)initWithItems:(NSArray *)items; -//- (void)insertSegmentWithTitle:(NSString *)title atIndex:(NSUInteger)segment animated:(BOOL)animated; -//- (void)insertSegmentWithImage:(UIImage *)image atIndex:(NSUInteger)segment animated:(BOOL)animated; -//- (void)removeSegmentAtIndex:(NSUInteger)segment animated:(BOOL)animated; -//- (void)removeAllSegments; - - (void)setTitle:(NSString *)title forSegmentAtIndex:(NSUInteger)segment; - (NSString *)titleForSegmentAtIndex:(NSUInteger)segment; - (void)setImage:(UIImage *)image forSegmentAtIndex:(NSUInteger)segment; - (UIImage *)imageForSegmentAtIndex:(NSUInteger)segment; -//- (void)setWidth:(CGFloat)width forSegmentAtIndex:(NSUInteger)segment; -//- (CGFloat)widthForSegmentAtIndex:(NSUInteger)segment; - -//- (void)setContentOffset:(CGSize)offset forSegmentAtIndex:(NSUInteger)segment; -//- (CGSize)contentOffsetForSegmentAtIndex:(NSUInteger)segment; - - (void)setEnabled:(BOOL)enabled forSegmentAtIndex:(NSUInteger)segment; - (BOOL)isEnabledForSegmentAtIndex:(NSUInteger)segment; - (void)setTitleTextAttributes:(NSDictionary *)attributes forState:(UIControlState)state; - (NSDictionary *)titleTextAttributesForState:(UIControlState)state; - @end diff --git a/UIKit/Classes/UISegmentedControl.m b/UIKit/Classes/UISegmentedControl.m index ae1cb6fd..372552cb 100644 --- a/UIKit/Classes/UISegmentedControl.m +++ b/UIKit/Classes/UISegmentedControl.m @@ -11,64 +11,28 @@ #import "UIColor.h" #import "UIStringDrawing.h" #import "UIGraphics.h" +#import "UIImage.h" +#import "UIFont.h" static NSString *kSSSegmentedControlEnabledKey = @"enabled"; -@interface UISegmentedControl () -@property (nonatomic, retain) UIImage *buttonImage; -@property (nonatomic, retain) UIImage *highlightedButtonImage; -@property (nonatomic, retain) UIImage *dividerImage; -@property (nonatomic, retain) UIImage *highlightedDividerImage; - -@property (nonatomic, retain) UIFont *font; -@property (nonatomic, retain) UIColor *textColor; -@property (nonatomic, retain) UIColor *disabledTextColor; -@property (nonatomic, retain) UIColor *textShadowColor; -@property (nonatomic, assign) CGSize textShadowOffset; -@property (nonatomic, assign) UIEdgeInsets textEdgeInsets; - -- (NSMutableDictionary *)_metaForSegmentIndex:(NSUInteger)index; -- (id)_metaValueForKey:(NSString *)key segmentIndex:(NSUInteger)index; -- (void)_setMetaValue:(id)value forKey:(NSString *)key segmentIndex:(NSUInteger)index; -@end - -@implementation UISegmentedControl - -@synthesize numberOfSegments = _numberOfSegments; -@synthesize selectedSegmentIndex = _selectedSegmentIndex; -@synthesize momentary = _momentary; -@synthesize buttonImage = _buttonImage; -@synthesize highlightedButtonImage = _highlightedButtonImage; -@synthesize dividerImage = _dividerImage; -@synthesize highlightedDividerImage = _highlightedDividerImage; -@synthesize font = _font; -@synthesize textColor = _textColor; -@synthesize disabledTextColor = _disabledTextColor; -@synthesize textShadowColor = _textShadowColor; -@synthesize textShadowOffset = _textShadowOffset; -@synthesize textEdgeInsets = _textEdgeInsets; -@synthesize segmentedControlStyle = _segmentedControlStyle; -@synthesize tintColor = _tintColor; - -#pragma mark NSObject - -- (void)dealloc -{ - [_segments release]; - [_buttonImage release]; - [_highlightedButtonImage release]; - [_dividerImage release]; - [_highlightedDividerImage release]; - [_font release]; - [_textColor release]; - [_disabledTextColor release]; - [_textShadowColor release]; - [_segmentMeta release]; - [_tintColor release]; - [super dealloc]; +@implementation UISegmentedControl { + NSMutableArray *_segments; + NSMutableDictionary *_segmentMeta; + + UIImage *_buttonImage; + UIImage *_highlightedButtonImage; + UIImage *_dividerImage; + UIImage *_highlightedDividerImage; + + UIFont *_font; + UIColor *_textColor; + UIColor *_disabledTextColor; + UIColor *_textShadowColor; + CGSize _textShadowOffset; + UIEdgeInsets _textEdgeInsets; } - #pragma mark UIResponder - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event @@ -110,16 +74,16 @@ - (id)initWithFrame:(CGRect)frame _momentary = NO; // TODO: add images - self.buttonImage = [[UIImage imageNamed:@"UISegmentBarButton.png"] stretchableImageWithLeftCapWidth:6 topCapHeight:0]; - self.highlightedButtonImage = [[UIImage imageNamed:@"UISegmentBarButtonHighlighted.png"] stretchableImageWithLeftCapWidth:6 topCapHeight:0]; - self.dividerImage = [UIImage imageNamed:@"UISegmentBarDivider.png"]; - self.highlightedDividerImage = [UIImage imageNamed:@"UISegmentBarDividerHighlighted.png"]; + _buttonImage = [[UIImage imageNamed:@"UISegmentBarButton.png"] stretchableImageWithLeftCapWidth:6 topCapHeight:0]; + _highlightedButtonImage = [[UIImage imageNamed:@"UISegmentBarButtonHighlighted.png"] stretchableImageWithLeftCapWidth:6 topCapHeight:0]; + _dividerImage = [UIImage imageNamed:@"UISegmentBarDivider.png"]; + _highlightedDividerImage = [UIImage imageNamed:@"UISegmentBarDividerHighlighted.png"]; self.selectedSegmentIndex = UISegmentedControlNoSegment; - _font = [[UIFont boldSystemFontOfSize:12.0f] retain]; - _textColor = [[UIColor whiteColor] retain]; - _disabledTextColor = [[UIColor colorWithWhite:0.561f alpha:1.0f] retain]; - _textShadowColor = [[UIColor colorWithWhite:0.0f alpha:0.5f] retain]; + _font = [UIFont boldSystemFontOfSize:12.0f]; + _textColor = [UIColor whiteColor]; + _disabledTextColor = [UIColor colorWithWhite:0.561f alpha:1.0f]; + _textShadowColor = [UIColor colorWithWhite:0.0f alpha:0.5f]; _textShadowOffset = CGSizeMake(0.0f, -1.0f); _textEdgeInsets = UIEdgeInsetsMake(-1.0f, 0.0f, 0.0f, 0.0f); } diff --git a/UIKit/Classes/UISlider.h b/UIKit/Classes/UISlider.h index d3f76acb..f1fe6e35 100644 --- a/UIKit/Classes/UISlider.h +++ b/UIKit/Classes/UISlider.h @@ -37,14 +37,24 @@ @class UIImageView, UIImage; -@interface UISlider : UIControl { - float _value; - float _minimumValue; - float _maximumValue; -} +@interface UISlider : UIControl +- (UIImage *)minimumTrackImageForState:(UIControlState)state; +- (void)setMinimumTrackImage:(UIImage *)image forState:(UIControlState)state; +- (UIImage *)maximumTrackImageForState:(UIControlState)state; +- (void)setMaximumTrackImage:(UIImage *)image forState:(UIControlState)state; +- (UIImage *)thumbImageForState:(UIControlState)state; +- (void)setThumbImage:(UIImage *)image forState:(UIControlState)state; @property (nonatomic) float value; @property (nonatomic) float minimumValue; @property (nonatomic) float maximumValue; +@property (nonatomic, strong) UIImage *minimumValueImage; +@property (nonatomic, strong) UIImage *maximumValueImage; +@property (nonatomic, strong) UIColor *minimumTrackTintColor; +@property (nonatomic, readonly) UIImage *currentMinimumTrackImage; +@property (nonatomic, strong) UIColor *maximumTrackTintColor; +@property (nonatomic, readonly) UIImage *currentMaximumTrackImage; +@property (nonatomic, strong) UIColor *thumbTintColor; +@property (nonatomic, readonly) UIImage *currentThumbImage; @end diff --git a/UIKit/Classes/UISlider.m b/UIKit/Classes/UISlider.m index 349eadfa..7571c6d3 100644 --- a/UIKit/Classes/UISlider.m +++ b/UIKit/Classes/UISlider.m @@ -38,13 +38,51 @@ @implementation UISlider -@synthesize value = _value; -@synthesize minimumValue = _minimumValue; -@synthesize maximumValue = _maximumValue; - - (NSString *)description { return [NSString stringWithFormat:@"<%@: %p; frame = (%.0f %.0f; %.0f %.0f); opaque = %@; layer = %@; value = %f>", [self className], self, self.frame.origin.x, self.frame.origin.y, self.frame.size.width, self.frame.size.height, (self.opaque ? @"YES" : @"NO"), self.layer, self.value]; } +- (UIImage *)minimumTrackImageForState:(UIControlState)state +{ + return nil; +} + +- (void)setMinimumTrackImage:(UIImage *)image forState:(UIControlState)state +{ +} + +- (UIImage *)maximumTrackImageForState:(UIControlState)state +{ + return nil; +} + +- (void)setMaximumTrackImage:(UIImage *)image forState:(UIControlState)state +{ +} + +- (UIImage *)thumbImageForState:(UIControlState)state +{ + return nil; +} + +- (void)setThumbImage:(UIImage *)image forState:(UIControlState)state +{ +} + +- (UIImage *)currentMinimumTrackImage +{ + return nil; +} + +- (UIImage *)currentMaximumTrackImage +{ + return nil; +} + +- (UIImage *)currentThumbImage +{ + return nil; +} + @end diff --git a/UIKit/Classes/UISplitViewController.h b/UIKit/Classes/UISplitViewController.h index 388d3d64..71670fa2 100644 --- a/UIKit/Classes/UISplitViewController.h +++ b/UIKit/Classes/UISplitViewController.h @@ -31,21 +31,9 @@ @protocol UISplitViewControllerDelegate; -@interface UISplitViewController : UIViewController { -@private - __unsafe_unretained id _delegate; - NSArray *_viewControllers; - - struct { - unsigned willPresentViewController : 1; - unsigned willHideViewController : 1; - unsigned willShowViewController : 1; - } _delegateHas; -} - +@interface UISplitViewController : UIViewController @property (nonatomic, assign) id delegate; @property (nonatomic, copy) NSArray *viewControllers; - @end @class UIPopoverController; diff --git a/UIKit/Classes/UISplitViewController.m b/UIKit/Classes/UISplitViewController.m index 384892a3..8152703b 100644 --- a/UIKit/Classes/UISplitViewController.m +++ b/UIKit/Classes/UISplitViewController.m @@ -28,7 +28,6 @@ */ #import "UISplitViewController.h" -#import "UIViewController+UIPrivate.h" #import "UIView.h" #import "UITouch.h" #import "UIColor.h" @@ -64,12 +63,6 @@ - (id)initWithFrame:(CGRect)frame return self; } -- (void)dealloc -{ - [leftPanel release]; - [rightPanel release]; - [super dealloc]; -} - (void)addViewControllers:(NSArray *)viewControllers { @@ -175,8 +168,13 @@ - (id)mouseCursorForEvent:(UIEvent *)event -@implementation UISplitViewController -@synthesize delegate=_delegate, viewControllers=_viewControllers; +@implementation UISplitViewController { + struct { + unsigned willPresentViewController : 1; + unsigned willHideViewController : 1; + unsigned willShowViewController : 1; + } _delegateHas; +} - (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle { @@ -185,11 +183,6 @@ - (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle return self; } -- (void)dealloc -{ - [_viewControllers release]; - [super dealloc]; -} - (void)setDelegate:(id )newDelegate { @@ -201,7 +194,7 @@ - (void)setDelegate:(id )newDelegate - (void)loadView { - self.view = [[[_UISplitViewControllerView alloc] initWithFrame:CGRectMake(0,0,1024,768)] autorelease]; + self.view = [[_UISplitViewControllerView alloc] initWithFrame:CGRectMake(0,0,1024,768)]; self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; } @@ -209,6 +202,7 @@ - (void)setViewControllers:(NSArray *)newControllers { assert([newControllers count]==2); + /* if (![newControllers isEqualToArray:_viewControllers]) { for (UIViewController *c in _viewControllers) { [c _setParentViewController:nil]; @@ -237,11 +231,12 @@ - (void)setViewControllers:(NSArray *)newControllers } } - [_viewControllers release]; _viewControllers = [newControllers copy]; } + */ } +/* - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; @@ -274,5 +269,6 @@ - (void)viewDidDisappear:(BOOL)animated [c viewDidDisappear:animated]; } } + */ @end diff --git a/UIKit/Classes/UIStringDrawing.h b/UIKit/Classes/UIStringDrawing.h index c8b7d909..493bc929 100644 --- a/UIKit/Classes/UIStringDrawing.h +++ b/UIKit/Classes/UIStringDrawing.h @@ -29,31 +29,31 @@ #import -typedef enum { +typedef NS_ENUM(NSInteger, UILineBreakMode) { UILineBreakModeWordWrap = 0, UILineBreakModeCharacterWrap, UILineBreakModeClip, UILineBreakModeHeadTruncation, UILineBreakModeTailTruncation, UILineBreakModeMiddleTruncation, -} UILineBreakMode; +}; -typedef enum { +typedef NS_ENUM(NSInteger, UITextAlignment) { UITextAlignmentLeft, UITextAlignmentCenter, UITextAlignmentRight, -} UITextAlignment; +}; -typedef enum { +typedef NS_ENUM(NSInteger, UIBaselineAdjustment) { UIBaselineAdjustmentAlignBaselines, UIBaselineAdjustmentAlignCenters, UIBaselineAdjustmentNone, -} UIBaselineAdjustment; +}; -NSString *const UITextAttributeFont; -NSString *const UITextAttributeTextColor; -NSString *const UITextAttributeTextShadowColor; -NSString *const UITextAttributeTextShadowOffset; +extern NSString *const UITextAttributeFont; +extern NSString *const UITextAttributeTextColor; +extern NSString *const UITextAttributeTextShadowColor; +extern NSString *const UITextAttributeTextShadowOffset; @class UIFont; diff --git a/UIKit/Classes/UISwipeGestureRecognizer.h b/UIKit/Classes/UISwipeGestureRecognizer.h index ff3304a8..47f87fff 100644 --- a/UIKit/Classes/UISwipeGestureRecognizer.h +++ b/UIKit/Classes/UISwipeGestureRecognizer.h @@ -29,19 +29,17 @@ #import "UIGestureRecognizer.h" -typedef enum { +// OSX's native swipe gesture doesn't seem to support the idea of varying numbers of touches involved in +// the gesture, so this will recognize for any OSX swipe regardless of touch count! + +typedef NS_OPTIONS(NSUInteger, UISwipeGestureRecognizerDirection) { UISwipeGestureRecognizerDirectionRight = 1 << 0, UISwipeGestureRecognizerDirectionLeft = 1 << 1, UISwipeGestureRecognizerDirectionUp = 1 << 2, UISwipeGestureRecognizerDirectionDown = 1 << 3 -} UISwipeGestureRecognizerDirection; - -@interface UISwipeGestureRecognizer : UIGestureRecognizer { - UISwipeGestureRecognizerDirection _direction; - NSUInteger _numberOfTouchesRequired; -} +}; +@interface UISwipeGestureRecognizer : UIGestureRecognizer @property (nonatomic) UISwipeGestureRecognizerDirection direction; @property (nonatomic) NSUInteger numberOfTouchesRequired; - @end diff --git a/UIKit/Classes/UISwipeGestureRecognizer.m b/UIKit/Classes/UISwipeGestureRecognizer.m index 08a7e86f..689eb031 100644 --- a/UIKit/Classes/UISwipeGestureRecognizer.m +++ b/UIKit/Classes/UISwipeGestureRecognizer.m @@ -29,9 +29,9 @@ #import "UISwipeGestureRecognizer.h" #import "UIGestureRecognizerSubclass.h" +#import "UITouchEvent.h" @implementation UISwipeGestureRecognizer -@synthesize direction=_direction, numberOfTouchesRequired=_numberOfTouchesRequired; - (id)initWithTarget:(id)target action:(SEL)action { @@ -42,4 +42,29 @@ - (id)initWithTarget:(id)target action:(SEL)action return self; } +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event +{ + if (self.state == UIGestureRecognizerStatePossible) { + if ([event isKindOfClass:[UITouchEvent class]]) { + UITouchEvent *touchEvent = (UITouchEvent *)event; + + if (touchEvent.touchEventGesture == UITouchEventGestureSwipe) { + if (_direction == UISwipeGestureRecognizerDirectionLeft && touchEvent.translation.x > 0) { + self.state = UIGestureRecognizerStateRecognized; + } else if (_direction == UISwipeGestureRecognizerDirectionRight && touchEvent.translation.x < 0) { + self.state = UIGestureRecognizerStateRecognized; + } else if (_direction == UISwipeGestureRecognizerDirectionUp && touchEvent.translation.y > 0) { + self.state = UIGestureRecognizerStateRecognized; + } else if (_direction == UISwipeGestureRecognizerDirectionDown && touchEvent.translation.y < 0) { + self.state = UIGestureRecognizerStateRecognized; + } else { + self.state = UIGestureRecognizerStateFailed; + } + } else { + self.state = UIGestureRecognizerStateFailed; + } + } + } +} + @end diff --git a/UIKit/Classes/UISwitch.h b/UIKit/Classes/UISwitch.h index 93844054..87b276b5 100644 --- a/UIKit/Classes/UISwitch.h +++ b/UIKit/Classes/UISwitch.h @@ -29,13 +29,9 @@ #import "UIControl.h" -@interface UISwitch : UIControl { - BOOL _on; -} - +@interface UISwitch : UIControl - (id)initWithFrame:(CGRect)frame; - (void)setOn:(BOOL)on animated:(BOOL)animated; @property(nonatomic, getter=isOn) BOOL on; - @end diff --git a/UIKit/Classes/UISwitch.m b/UIKit/Classes/UISwitch.m index 2f80778c..b5434534 100644 --- a/UIKit/Classes/UISwitch.m +++ b/UIKit/Classes/UISwitch.m @@ -30,7 +30,6 @@ #import "UISwitch.h" @implementation UISwitch -@synthesize on = _on; - (id)initWithFrame:(CGRect)frame { diff --git a/UIKit/Classes/UITabBar.h b/UIKit/Classes/UITabBar.h index 9f0b43b7..4dfc9460 100644 --- a/UIKit/Classes/UITabBar.h +++ b/UIKit/Classes/UITabBar.h @@ -51,21 +51,13 @@ @end -@interface UITabBar : UIView { - __unsafe_unretained id _delegate; - NSArray *_items; - NSInteger _selectedItemIndex; -} - -@property (nonatomic, assign) id delegate; -@property (nonatomic, copy) NSArray *items; -@property (nonatomic, assign) UITabBarItem *selectedItem; - +@interface UITabBar : UIView - (void)setItems:(NSArray *)items animated:(BOOL)animated; - -// stub - (void)beginCustomizingItems:(NSArray *)items; - (BOOL)endCustomizingAnimated:(BOOL)animated; - (BOOL)isCustomizing; +@property (nonatomic, assign) id delegate; +@property (nonatomic, copy) NSArray *items; +@property (nonatomic, assign) UITabBarItem *selectedItem; @end diff --git a/UIKit/Classes/UITabBar.m b/UIKit/Classes/UITabBar.m index 9a2bc699..8b4a5b83 100644 --- a/UIKit/Classes/UITabBar.m +++ b/UIKit/Classes/UITabBar.m @@ -40,9 +40,9 @@ #define TABBAR_HEIGHT 60.0 -@implementation UITabBar - -@synthesize items = _items, delegate = _delegate; +@implementation UITabBar { + NSInteger _selectedItemIndex; +} - (id)initWithFrame:(CGRect)rect { @@ -50,7 +50,7 @@ - (id)initWithFrame:(CGRect)rect rect.size.height = TABBAR_HEIGHT; // tabbar is always fixed _selectedItemIndex = -1; UIImage *backgroundImage = [UIImage _popoverBackgroundImage]; - UIImageView *backgroundView = [[[UIImageView alloc] initWithImage:backgroundImage] autorelease]; + UIImageView *backgroundView = [[UIImageView alloc] initWithImage:backgroundImage]; backgroundView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; backgroundView.frame = rect; [self addSubview:backgroundView]; @@ -58,13 +58,6 @@ - (id)initWithFrame:(CGRect)rect return self; } -- (void)dealloc -{ - _delegate = nil; - [_items release]; - [super dealloc]; -} - - (UITabBarItem *)selectedItem { if (_selectedItemIndex >= 0) { diff --git a/UIKit/Classes/UITabBarController.h b/UIKit/Classes/UITabBarController.h index 2fb7dc07..bbd54404 100644 --- a/UIKit/Classes/UITabBarController.h +++ b/UIKit/Classes/UITabBarController.h @@ -41,18 +41,11 @@ @end @class UITabBar; -@interface UITabBarController : UIViewController { - UITabBar *_tabBar; - __unsafe_unretained UIViewController *_selectedViewController; - NSArray *_viewControllers; - NSUInteger _selectedIndex; -} - +@interface UITabBarController : UIViewController - (void)setViewControllers:(NSArray *)viewController animated:(BOOL)animated; @property (nonatomic, assign) UIViewController *selectedViewController; @property (nonatomic, copy) NSArray *viewControllers; @property (nonatomic, assign) NSUInteger selectedIndex; @property (nonatomic, readonly) UITabBar *tabBar; - @end diff --git a/UIKit/Classes/UITabBarController.m b/UIKit/Classes/UITabBarController.m index a37ef105..5c51d91e 100644 --- a/UIKit/Classes/UITabBarController.m +++ b/UIKit/Classes/UITabBarController.m @@ -32,11 +32,6 @@ @implementation UITabBarController -@synthesize selectedViewController = _selectedViewController; -@synthesize viewControllers = _viewControllers; -@synthesize selectedIndex = _selectedIndex; -@synthesize tabBar = _tabBar; - - (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle { if ((self = [super initWithNibName:nibName bundle:nibBundle])) { @@ -45,11 +40,6 @@ - (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle return self; } -- (void)dealloc -{ - [_tabBar release]; - [super dealloc]; -} - (void)setViewControllers:(NSArray *)viewController animated:(BOOL)animated { diff --git a/UIKit/Classes/UITabBarItem.h b/UIKit/Classes/UITabBarItem.h index a7c1bde7..7f49de64 100644 --- a/UIKit/Classes/UITabBarItem.h +++ b/UIKit/Classes/UITabBarItem.h @@ -37,7 +37,7 @@ @class UIImage; -typedef enum { +typedef NS_ENUM(NSInteger, UITabBarSystemItem) { UITabBarSystemItemMore, UITabBarSystemItemFavorites, UITabBarSystemItemFeatured, @@ -50,16 +50,12 @@ typedef enum { UITabBarSystemItemDownloads, UITabBarSystemItemMostRecent, UITabBarSystemItemMostViewed, -} UITabBarSystemItem; +}; -@interface UITabBarItem : UIBarItem { - NSString *_badgeValue; -} - +@interface UITabBarItem : UIBarItem - (id)initWithTitle:(NSString *)title image:(UIImage *)image tag:(NSInteger)tag; - (id)initWithTabBarSystemItem:(UITabBarSystemItem)systemItem tag:(NSInteger)tag; @property (nonatomic, copy) NSString *badgeValue; - @end diff --git a/UIKit/Classes/UITabBarItem.m b/UIKit/Classes/UITabBarItem.m index 6672b43d..b8fb492b 100644 --- a/UIKit/Classes/UITabBarItem.m +++ b/UIKit/Classes/UITabBarItem.m @@ -37,7 +37,6 @@ #import "UIImage.h" @implementation UITabBarItem -@synthesize badgeValue=_badgeValue; - (id)initWithTitle:(NSString *)title image:(UIImage *)image tag:(NSInteger)tag { @@ -55,10 +54,4 @@ - (id)initWithTabBarSystemItem:(UITabBarSystemItem)systemItem tag:(NSInteger)tag return self; } -- (void)dealloc -{ - [_badgeValue release]; - [super dealloc]; -} - @end diff --git a/UIKit/Classes/UITableView.h b/UIKit/Classes/UITableView.h index a6bdfb7b..93eb6272 100644 --- a/UIKit/Classes/UITableView.h +++ b/UIKit/Classes/UITableView.h @@ -66,76 +66,33 @@ extern NSString *const UITableViewIndexSearch; - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath; @end -typedef enum { +typedef NS_ENUM(NSInteger, UITableViewStyle) { UITableViewStylePlain, UITableViewStyleGrouped -} UITableViewStyle; +}; -typedef enum { +typedef NS_ENUM(NSInteger, UITableViewScrollPosition) { UITableViewScrollPositionNone, UITableViewScrollPositionTop, UITableViewScrollPositionMiddle, UITableViewScrollPositionBottom -} UITableViewScrollPosition; +}; -typedef enum { +typedef NS_ENUM(NSInteger, UITableViewRowAnimation) { UITableViewRowAnimationFade, UITableViewRowAnimationRight, UITableViewRowAnimationLeft, UITableViewRowAnimationTop, UITableViewRowAnimationBottom, UITableViewRowAnimationNone, - UITableViewRowAnimationMiddle -} UITableViewRowAnimation; - -@interface UITableView : UIScrollView { -@private - UITableViewStyle _style; - __unsafe_unretained id _dataSource; - BOOL _needsReload; - CGFloat _rowHeight; - UIColor *_separatorColor; - UITableViewCellSeparatorStyle _separatorStyle; - UIView *_tableHeaderView; - UIView *_tableFooterView; - UIView *_backgroundView; - BOOL _allowsSelection; - BOOL _allowsSelectionDuringEditing; - BOOL _editing; - NSIndexPath *_selectedRow; - NSIndexPath *_highlightedRow; - NSMutableDictionary *_cachedCells; - NSMutableSet *_reusableCells; - NSMutableArray *_sections; - CGFloat _sectionHeaderHeight; - CGFloat _sectionFooterHeight; - - struct { - unsigned heightForRowAtIndexPath : 1; - unsigned heightForHeaderInSection : 1; - unsigned heightForFooterInSection : 1; - unsigned viewForHeaderInSection : 1; - unsigned viewForFooterInSection : 1; - unsigned willSelectRowAtIndexPath : 1; - unsigned didSelectRowAtIndexPath : 1; - unsigned willDeselectRowAtIndexPath : 1; - unsigned didDeselectRowAtIndexPath : 1; - unsigned willBeginEditingRowAtIndexPath : 1; - unsigned didEndEditingRowAtIndexPath : 1; - unsigned titleForDeleteConfirmationButtonForRowAtIndexPath: 1; - } _delegateHas; - - struct { - unsigned numberOfSectionsInTableView : 1; - unsigned titleForHeaderInSection : 1; - unsigned titleForFooterInSection : 1; - unsigned commitEditingStyle : 1; - unsigned canEditRowAtIndexPath : 1; - } _dataSourceHas; -} + UITableViewRowAnimationMiddle, + UITableViewRowAnimationAutomatic = 100 +}; +@interface UITableView : UIScrollView - (id)initWithFrame:(CGRect)frame style:(UITableViewStyle)style; - (void)reloadData; +- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation; - (NSInteger)numberOfSections; - (NSInteger)numberOfRowsInSection:(NSInteger)section; - (NSArray *)indexPathsForRowsInRect:(CGRect)rect; @@ -174,14 +131,13 @@ typedef enum { @property (nonatomic, assign) id dataSource; @property (nonatomic) CGFloat rowHeight; @property (nonatomic) UITableViewCellSeparatorStyle separatorStyle; -@property (nonatomic, retain) UIColor *separatorColor; -@property (nonatomic, retain) UIView *tableHeaderView; -@property (nonatomic, retain) UIView *tableFooterView; -@property (nonatomic, retain) UIView *backgroundView; +@property (nonatomic, strong) UIColor *separatorColor; +@property (nonatomic, strong) UIView *tableHeaderView; +@property (nonatomic, strong) UIView *tableFooterView; +@property (nonatomic, strong) UIView *backgroundView; @property (nonatomic) BOOL allowsSelection; @property (nonatomic) BOOL allowsSelectionDuringEditing; // not implemented @property (nonatomic, getter=isEditing) BOOL editing; @property (nonatomic) CGFloat sectionHeaderHeight; @property (nonatomic) CGFloat sectionFooterHeight; - @end diff --git a/UIKit/Classes/UITableView.m b/UIKit/Classes/UITableView.m index 119c1ca0..8adb6151 100644 --- a/UIKit/Classes/UITableView.m +++ b/UIKit/Classes/UITableView.m @@ -36,7 +36,7 @@ #import "UIScreenAppKitIntegration.h" #import "UIWindow.h" #import "UIKitView.h" -#import "UIApplication+UIPrivate.h" +#import "UIApplicationAppKitIntegration.h" #import #import #import @@ -46,16 +46,37 @@ const CGFloat _UITableViewDefaultRowHeight = 43; -@interface UITableView () -- (void)_setNeedsReload; -@end - -@implementation UITableView -@synthesize style=_style, dataSource=_dataSource, rowHeight=_rowHeight, separatorStyle=_separatorStyle, separatorColor=_separatorColor; -@synthesize tableHeaderView=_tableHeaderView, tableFooterView=_tableFooterView, allowsSelection=_allowsSelection, editing=_editing; -@synthesize sectionFooterHeight=_sectionFooterHeight, sectionHeaderHeight=_sectionHeaderHeight; -@synthesize allowsSelectionDuringEditing=_allowsSelectionDuringEditing, backgroundView=_backgroundView; -@dynamic delegate; +@implementation UITableView { + BOOL _needsReload; + NSIndexPath *_selectedRow; + NSIndexPath *_highlightedRow; + NSMutableDictionary *_cachedCells; + NSMutableSet *_reusableCells; + NSMutableArray *_sections; + + struct { + unsigned heightForRowAtIndexPath : 1; + unsigned heightForHeaderInSection : 1; + unsigned heightForFooterInSection : 1; + unsigned viewForHeaderInSection : 1; + unsigned viewForFooterInSection : 1; + unsigned willSelectRowAtIndexPath : 1; + unsigned didSelectRowAtIndexPath : 1; + unsigned willDeselectRowAtIndexPath : 1; + unsigned didDeselectRowAtIndexPath : 1; + unsigned willBeginEditingRowAtIndexPath : 1; + unsigned didEndEditingRowAtIndexPath : 1; + unsigned titleForDeleteConfirmationButtonForRowAtIndexPath: 1; + } _delegateHas; + + struct { + unsigned numberOfSectionsInTableView : 1; + unsigned titleForHeaderInSection : 1; + unsigned titleForFooterInSection : 1; + unsigned commitEditingStyle : 1; + unsigned canEditRowAtIndexPath : 1; + } _dataSourceHas; +} - (id)initWithFrame:(CGRect)frame { @@ -87,18 +108,6 @@ - (id)initWithFrame:(CGRect)frame style:(UITableViewStyle)theStyle return self; } -- (void)dealloc -{ - [_selectedRow release]; - [_highlightedRow release]; - [_tableFooterView release]; - [_tableHeaderView release]; - [_cachedCells release]; - [_sections release]; - [_reusableCells release]; - [_separatorColor release]; - [super dealloc]; -} - (void)setDataSource:(id)newSource { @@ -117,18 +126,18 @@ - (void)setDelegate:(id)newDelegate { [super setDelegate:newDelegate]; - _delegateHas.heightForRowAtIndexPath = [_delegate respondsToSelector:@selector(tableView:heightForRowAtIndexPath:)]; - _delegateHas.heightForHeaderInSection = [_delegate respondsToSelector:@selector(tableView:heightForHeaderInSection:)]; - _delegateHas.heightForFooterInSection = [_delegate respondsToSelector:@selector(tableView:heightForFooterInSection:)]; - _delegateHas.viewForHeaderInSection = [_delegate respondsToSelector:@selector(tableView:viewForHeaderInSection:)]; - _delegateHas.viewForFooterInSection = [_delegate respondsToSelector:@selector(tableView:viewForFooterInSection:)]; - _delegateHas.willSelectRowAtIndexPath = [_delegate respondsToSelector:@selector(tableView:willSelectRowAtIndexPath:)]; - _delegateHas.didSelectRowAtIndexPath = [_delegate respondsToSelector:@selector(tableView:didSelectRowAtIndexPath:)]; - _delegateHas.willDeselectRowAtIndexPath = [_delegate respondsToSelector:@selector(tableView:willDeselectRowAtIndexPath:)]; - _delegateHas.didDeselectRowAtIndexPath = [_delegate respondsToSelector:@selector(tableView:didDeselectRowAtIndexPath:)]; - _delegateHas.willBeginEditingRowAtIndexPath = [_delegate respondsToSelector:@selector(tableView:willBeginEditingRowAtIndexPath:)]; - _delegateHas.didEndEditingRowAtIndexPath = [_delegate respondsToSelector:@selector(tableView:didEndEditingRowAtIndexPath:)]; - _delegateHas.titleForDeleteConfirmationButtonForRowAtIndexPath = [_delegate respondsToSelector:@selector(tableView:titleForDeleteConfirmationButtonForRowAtIndexPath:)]; + _delegateHas.heightForRowAtIndexPath = [newDelegate respondsToSelector:@selector(tableView:heightForRowAtIndexPath:)]; + _delegateHas.heightForHeaderInSection = [newDelegate respondsToSelector:@selector(tableView:heightForHeaderInSection:)]; + _delegateHas.heightForFooterInSection = [newDelegate respondsToSelector:@selector(tableView:heightForFooterInSection:)]; + _delegateHas.viewForHeaderInSection = [newDelegate respondsToSelector:@selector(tableView:viewForHeaderInSection:)]; + _delegateHas.viewForFooterInSection = [newDelegate respondsToSelector:@selector(tableView:viewForFooterInSection:)]; + _delegateHas.willSelectRowAtIndexPath = [newDelegate respondsToSelector:@selector(tableView:willSelectRowAtIndexPath:)]; + _delegateHas.didSelectRowAtIndexPath = [newDelegate respondsToSelector:@selector(tableView:didSelectRowAtIndexPath:)]; + _delegateHas.willDeselectRowAtIndexPath = [newDelegate respondsToSelector:@selector(tableView:willDeselectRowAtIndexPath:)]; + _delegateHas.didDeselectRowAtIndexPath = [newDelegate respondsToSelector:@selector(tableView:didDeselectRowAtIndexPath:)]; + _delegateHas.willBeginEditingRowAtIndexPath = [newDelegate respondsToSelector:@selector(tableView:willBeginEditingRowAtIndexPath:)]; + _delegateHas.didEndEditingRowAtIndexPath = [newDelegate respondsToSelector:@selector(tableView:didEndEditingRowAtIndexPath:)]; + _delegateHas.titleForDeleteConfirmationButtonForRowAtIndexPath = [newDelegate respondsToSelector:@selector(tableView:titleForDeleteConfirmationButtonForRowAtIndexPath:)]; } - (void)setRowHeight:(CGFloat)newHeight @@ -161,36 +170,37 @@ - (void)_updateSectionsCache const NSInteger numberOfRowsInSection = [self numberOfRowsInSection:section]; UITableViewSection *sectionRecord = [[UITableViewSection alloc] init]; - sectionRecord.headerView = _delegateHas.viewForHeaderInSection? [self.delegate tableView:self viewForHeaderInSection:section] : nil; - sectionRecord.footerView = _delegateHas.viewForFooterInSection? [self.delegate tableView:self viewForFooterInSection:section] : nil; sectionRecord.headerTitle = _dataSourceHas.titleForHeaderInSection? [self.dataSource tableView:self titleForHeaderInSection:section] : nil; sectionRecord.footerTitle = _dataSourceHas.titleForFooterInSection? [self.dataSource tableView:self titleForFooterInSection:section] : nil; + sectionRecord.headerHeight = _delegateHas.heightForHeaderInSection? [self.delegate tableView:self heightForHeaderInSection:section] : _sectionHeaderHeight; + sectionRecord.footerHeight = _delegateHas.heightForFooterInSection ? [self.delegate tableView:self heightForFooterInSection:section] : _sectionFooterHeight; + + sectionRecord.headerView = (sectionRecord.headerHeight > 0 && _delegateHas.viewForHeaderInSection)? [self.delegate tableView:self viewForHeaderInSection:section] : nil; + sectionRecord.footerView = (sectionRecord.footerHeight > 0 && _delegateHas.viewForFooterInSection)? [self.delegate tableView:self viewForFooterInSection:section] : nil; + // make a default section header view if there's a title for it and no overriding view - if (!sectionRecord.headerView && sectionRecord.headerTitle) { + if (!sectionRecord.headerView && sectionRecord.headerHeight > 0 && sectionRecord.headerTitle) { sectionRecord.headerView = [UITableViewSectionLabel sectionLabelWithTitle:sectionRecord.headerTitle]; } // make a default section footer view if there's a title for it and no overriding view - if (!sectionRecord.footerView && sectionRecord.footerTitle) { + if (!sectionRecord.footerView && sectionRecord.footerHeight > 0 && sectionRecord.footerTitle) { sectionRecord.footerView = [UITableViewSectionLabel sectionLabelWithTitle:sectionRecord.footerTitle]; } - - // if there's a view, then we need to set the height, otherwise it's going to be zero + if (sectionRecord.headerView) { [self addSubview:sectionRecord.headerView]; - sectionRecord.headerHeight = _delegateHas.heightForHeaderInSection? [self.delegate tableView:self heightForHeaderInSection:section] : _sectionHeaderHeight; } else { sectionRecord.headerHeight = 0; } if (sectionRecord.footerView) { [self addSubview:sectionRecord.footerView]; - sectionRecord.footerHeight = _delegateHas.heightForFooterInSection? [self.delegate tableView:self heightForFooterInSection:section] : _sectionFooterHeight; } else { sectionRecord.footerHeight = 0; } - + CGFloat *rowHeights = malloc(numberOfRowsInSection * sizeof(CGFloat)); CGFloat totalRowsHeight = 0; @@ -205,7 +215,6 @@ - (void)_updateSectionsCache free(rowHeights); [_sections addObject:sectionRecord]; - [sectionRecord release]; } } } @@ -315,7 +324,6 @@ - (void)_layoutTableView } // non-reusable cells should end up dealloced after at this point, but reusable ones live on in _reusableCells. - [availableCells release]; // now make sure that all available (but unused) reusable cells aren't on screen in the visible area. // this is done becaue when resizing a table view by shrinking it's height in an animation, it looks better. The reason is that @@ -456,7 +464,7 @@ - (NSArray *)indexPathsForRowsInRect:(CGRect)rect offset += sectionRecord.footerHeight; } - return [results autorelease]; + return results; } - (NSIndexPath *)indexPathForRowAtPoint:(CGPoint)point @@ -487,7 +495,7 @@ - (NSArray *)indexPathsForVisibleRows - (NSArray *)visibleCells { - NSMutableArray *cells = [[[NSMutableArray alloc] init] autorelease]; + NSMutableArray *cells = [[NSMutableArray alloc] init]; for (NSIndexPath *index in [self indexPathsForVisibleRows]) { UITableViewCell *cell = [self cellForRowAtIndexPath:index]; if (cell) { @@ -501,8 +509,7 @@ - (void)setTableHeaderView:(UIView *)newHeader { if (newHeader != _tableHeaderView) { [_tableHeaderView removeFromSuperview]; - [_tableHeaderView release]; - _tableHeaderView = [newHeader retain]; + _tableHeaderView = newHeader; [self _setContentSize]; [self addSubview:_tableHeaderView]; } @@ -512,8 +519,7 @@ - (void)setTableFooterView:(UIView *)newFooter { if (newFooter != _tableFooterView) { [_tableFooterView removeFromSuperview]; - [_tableFooterView release]; - _tableFooterView = [newFooter retain]; + _tableFooterView = newFooter; [self _setContentSize]; [self addSubview:_tableFooterView]; } @@ -523,8 +529,7 @@ - (void)setBackgroundView:(UIView *)backgroundView { if (_backgroundView != backgroundView) { [_backgroundView removeFromSuperview]; - [_backgroundView release]; - _backgroundView = [backgroundView retain]; + _backgroundView = backgroundView; [self insertSubview:_backgroundView atIndex:0]; } } @@ -552,9 +557,7 @@ - (void)reloadData [_cachedCells removeAllObjects]; // clear prior selection - [_selectedRow release]; _selectedRow = nil; - [_highlightedRow release]; _highlightedRow = nil; // trigger the section cache to be repopulated @@ -564,6 +567,11 @@ - (void)reloadData _needsReload = NO; } +- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation +{ + [self reloadData]; +} + - (void)_reloadDataIfNeeded { if (_needsReload) { @@ -601,14 +609,14 @@ - (void)setFrame:(CGRect)frame - (NSIndexPath *)indexPathForSelectedRow { - return [[_selectedRow retain] autorelease]; + return _selectedRow; } - (NSIndexPath *)indexPathForCell:(UITableViewCell *)cell { for (NSIndexPath *index in [_cachedCells allKeys]) { if ([_cachedCells objectForKey:index] == cell) { - return [[index retain] autorelease]; + return index; } } @@ -619,7 +627,6 @@ - (void)deselectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated { if (indexPath && [indexPath isEqual:_selectedRow]) { [self cellForRowAtIndexPath:_selectedRow].selected = NO; - [_selectedRow release]; _selectedRow = nil; } } @@ -633,8 +640,7 @@ - (void)selectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated sc if (![_selectedRow isEqual:indexPath]) { [self deselectRowAtIndexPath:_selectedRow animated:animated]; - [_selectedRow release]; - _selectedRow = [indexPath retain]; + _selectedRow = indexPath; [self cellForRowAtIndexPath:_selectedRow].selected = YES; } @@ -643,6 +649,35 @@ - (void)selectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated sc [self scrollToRowAtIndexPath:_selectedRow atScrollPosition:scrollPosition animated:animated]; } +- (void)_setUserSelectedRowAtIndexPath:(NSIndexPath *)rowToSelect +{ + if (_delegateHas.willSelectRowAtIndexPath) { + rowToSelect = [self.delegate tableView:self willSelectRowAtIndexPath:rowToSelect]; + } + + NSIndexPath *selectedRow = [self indexPathForSelectedRow]; + + if (selectedRow && ![selectedRow isEqual:rowToSelect]) { + NSIndexPath *rowToDeselect = selectedRow; + + if (_delegateHas.willDeselectRowAtIndexPath) { + rowToDeselect = [self.delegate tableView:self willDeselectRowAtIndexPath:rowToDeselect]; + } + + [self deselectRowAtIndexPath:rowToDeselect animated:NO]; + + if (_delegateHas.didDeselectRowAtIndexPath) { + [self.delegate tableView:self didDeselectRowAtIndexPath:rowToDeselect]; + } + } + + [self selectRowAtIndexPath:rowToSelect animated:NO scrollPosition:UITableViewScrollPositionNone]; + + if (_delegateHas.didSelectRowAtIndexPath) { + [self.delegate tableView:self didSelectRowAtIndexPath:rowToSelect]; + } +} + - (void)_scrollRectToVisible:(CGRect)aRect atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated { if (!CGRectIsNull(aRect) && aRect.size.height > 0) { @@ -684,10 +719,15 @@ - (UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier { for (UITableViewCell *cell in _reusableCells) { if ([cell.reuseIdentifier isEqualToString:identifier]) { - [cell retain]; + UITableViewCell *strongCell = cell; + + // the above strongCell reference seems totally unnecessary, but without it ARC apparently + // ends up releasing the cell when it's removed on this line even though we're referencing it + // later in this method by way of the cell variable. I do not like this. [_reusableCells removeObject:cell]; - [cell prepareForReuse]; - return [cell autorelease]; + + [strongCell prepareForReuse]; + return strongCell; } } @@ -726,63 +766,25 @@ - (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableVi - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { - if (!_highlightedRow) { - UITouch *touch = [touches anyObject]; - const CGPoint location = [touch locationInView:self]; - - _highlightedRow = [[self indexPathForRowAtPoint:location] retain]; - [self cellForRowAtIndexPath:_highlightedRow].highlighted = YES; - } } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { - // this isn't quite how iOS seems to do it, but I think it makes sense on OSX - if (_highlightedRow) { +} + +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event +{ + if (!_highlightedRow) { UITouch *touch = [touches anyObject]; const CGPoint location = [touch locationInView:self]; - if (!CGRectContainsPoint([self rectForRowAtIndexPath:_highlightedRow], location)) { - [self cellForRowAtIndexPath:_highlightedRow].highlighted = NO; - [_highlightedRow release]; - _highlightedRow = nil; - } + _highlightedRow = [self indexPathForRowAtPoint:location]; + [self cellForRowAtIndexPath:_highlightedRow].highlighted = YES; } -} -- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event -{ if (_highlightedRow) { - NSIndexPath *selectedRow = [self indexPathForSelectedRow]; - - if (selectedRow) { - NSIndexPath *rowToDeselect = selectedRow; - - if (_delegateHas.willDeselectRowAtIndexPath) { - rowToDeselect = [_delegate tableView:self willDeselectRowAtIndexPath:rowToDeselect]; - } - - [self deselectRowAtIndexPath:rowToDeselect animated:NO]; - - if (_delegateHas.didDeselectRowAtIndexPath) { - [_delegate tableView:self didDeselectRowAtIndexPath:rowToDeselect]; - } - } - - NSIndexPath *rowToSelect = _highlightedRow; - - if (_delegateHas.willSelectRowAtIndexPath) { - rowToSelect = [_delegate tableView:self willSelectRowAtIndexPath:rowToSelect]; - } - [self cellForRowAtIndexPath:_highlightedRow].highlighted = NO; - [self selectRowAtIndexPath:rowToSelect animated:NO scrollPosition:UITableViewScrollPositionNone]; - - if (_delegateHas.didSelectRowAtIndexPath) { - [_delegate tableView:self didSelectRowAtIndexPath:rowToSelect]; - } - - [_highlightedRow release]; + [self _setUserSelectedRowAtIndexPath:_highlightedRow]; _highlightedRow = nil; } } @@ -791,7 +793,6 @@ - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { if (_highlightedRow) { [self cellForRowAtIndexPath:_highlightedRow].highlighted = NO; - [_highlightedRow release]; _highlightedRow = nil; } } @@ -808,7 +809,7 @@ - (void)_beginEditingRowAtIndexPath:(NSIndexPath *)indexPath self.editing = YES; if (_delegateHas.willBeginEditingRowAtIndexPath) { - [_delegate tableView:self willBeginEditingRowAtIndexPath:indexPath]; + [self.delegate tableView:self willBeginEditingRowAtIndexPath:indexPath]; } // deferring this because it presents a modal menu and that's what we do everywhere else in Chameleon @@ -822,7 +823,7 @@ - (void)_endEditingRowAtIndexPath:(NSIndexPath *)indexPath self.editing = NO; if (_delegateHas.didEndEditingRowAtIndexPath) { - [_delegate tableView:self didEndEditingRowAtIndexPath:indexPath]; + [self.delegate tableView:self didEndEditingRowAtIndexPath:indexPath]; } } } @@ -836,7 +837,7 @@ - (void)_showEditMenuForRowAtIndexPath:(NSIndexPath *)indexPath // fetch the title for the delete menu item if (_delegateHas.titleForDeleteConfirmationButtonForRowAtIndexPath) { - menuItemTitle = [_delegate tableView:self titleForDeleteConfirmationButtonForRowAtIndexPath:indexPath]; + menuItemTitle = [self.delegate tableView:self titleForDeleteConfirmationButtonForRowAtIndexPath:indexPath]; } if ([menuItemTitle length] == 0) { menuItemTitle = @"Delete"; @@ -856,12 +857,9 @@ - (void)_showEditMenuForRowAtIndexPath:(NSIndexPath *)indexPath CGPoint screenPoint = [self.window.screen convertPoint:NSPointToCGPoint(mouseLocation) fromScreen:nil]; // modally present a menu with the single delete option on it, if it was selected, then do the delete, otherwise do nothing - const BOOL didSelectItem = [menu popUpMenuPositioningItem:nil atLocation:NSPointFromCGPoint(screenPoint) inView:[self.window.screen UIKitView]]; + const BOOL didSelectItem = [menu popUpMenuPositioningItem:nil atLocation:NSPointFromCGPoint(screenPoint) inView:self.window.screen.UIKitView]; - [menu release]; - [theItem release]; - - [[UIApplication sharedApplication] _cancelTouches]; + UIApplicationInterruptTouchesInView(nil); if (didSelectItem) { [_dataSource tableView:self commitEditingStyle:UITableViewCellEditingStyleDelete forRowAtIndexPath:indexPath]; @@ -885,4 +883,71 @@ - (void)rightClick:(UITouch *)touch withEvent:(UIEvent *)event } } +// these can come down to use from AppKit if the table view somehow ends up in the responder chain. +// arrow keys move the selection, page up/down keys scroll the view + +- (void)moveUp:(id)sender +{ + NSIndexPath *selection = self.indexPathForSelectedRow; + + if (selection.row > 0) { + selection = [NSIndexPath indexPathForRow:selection.row-1 inSection:selection.section]; + } else if (selection.row == 0 && selection.section > 0) { + for (NSInteger section = selection.section - 1; section >= 0; section--) { + const NSInteger rows = [self numberOfRowsInSection:section]; + + if (rows > 0) { + selection = [NSIndexPath indexPathForRow:rows-1 inSection:section]; + break; + } + } + } + + if (![selection isEqual:self.indexPathForSelectedRow]) { + [self _setUserSelectedRowAtIndexPath:selection]; + [NSCursor setHiddenUntilMouseMoves:YES]; + } +} + +- (void)moveDown:(id)sender +{ + NSIndexPath *selection = self.indexPathForSelectedRow; + + if ((selection.row + 1) < [self numberOfRowsInSection:selection.section]) { + selection = [NSIndexPath indexPathForRow:selection.row+1 inSection:selection.section]; + } else { + for (NSInteger section = selection.section + 1; section < self.numberOfSections; section++) { + const NSInteger rows = [self numberOfRowsInSection:section]; + + if (rows > 0) { + selection = [NSIndexPath indexPathForRow:0 inSection:section]; + break; + } + } + } + + if (![selection isEqual:self.indexPathForSelectedRow]) { + [self _setUserSelectedRowAtIndexPath:selection]; + [NSCursor setHiddenUntilMouseMoves:YES]; + } +} + +- (void)pageUp:(id)sender +{ + NSArray *visibleRows = [self indexPathsForVisibleRows]; + + if ([visibleRows count] > 0) { + [self scrollToRowAtIndexPath:[visibleRows objectAtIndex:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES]; + [NSCursor setHiddenUntilMouseMoves:YES]; + [self flashScrollIndicators]; + } +} + +- (void)pageDown:(id)sender +{ + [self scrollToRowAtIndexPath:[[self indexPathsForVisibleRows] lastObject] atScrollPosition:UITableViewScrollPositionTop animated:YES]; + [NSCursor setHiddenUntilMouseMoves:YES]; + [self flashScrollIndicators]; +} + @end diff --git a/UIKit/Classes/UITableViewCell.h b/UIKit/Classes/UITableViewCell.h index 04bfb533..b962dee3 100644 --- a/UIKit/Classes/UITableViewCell.h +++ b/UIKit/Classes/UITableViewCell.h @@ -29,78 +29,56 @@ #import "UIView.h" -typedef enum { +typedef NS_ENUM(NSInteger, UITableViewCellAccessoryType) { UITableViewCellAccessoryNone, UITableViewCellAccessoryDisclosureIndicator, UITableViewCellAccessoryDetailDisclosureButton, UITableViewCellAccessoryCheckmark -} UITableViewCellAccessoryType; +}; -typedef enum { +typedef NS_ENUM(NSInteger, UITableViewCellSeparatorStyle) { UITableViewCellSeparatorStyleNone, UITableViewCellSeparatorStyleSingleLine, UITableViewCellSeparatorStyleSingleLineEtched -} UITableViewCellSeparatorStyle; +}; -typedef enum { +typedef NS_ENUM(NSInteger, UITableViewCellStyle) { UITableViewCellStyleDefault, UITableViewCellStyleValue1, UITableViewCellStyleValue2, UITableViewCellStyleSubtitle -} UITableViewCellStyle; +}; -typedef enum { +typedef NS_ENUM(NSInteger, UITableViewCellSelectionStyle) { UITableViewCellSelectionStyleNone, UITableViewCellSelectionStyleBlue, UITableViewCellSelectionStyleGray -} UITableViewCellSelectionStyle; +}; -typedef enum { +typedef NS_ENUM(NSInteger, UITableViewCellEditingStyle) { UITableViewCellEditingStyleNone, UITableViewCellEditingStyleDelete, UITableViewCellEditingStyleInsert -} UITableViewCellEditingStyle; +}; -@class UITableViewCellSeparator, UILabel, UIImageView; - -@interface UITableViewCell : UIView { -@private - UITableViewCellStyle _style; - UITableViewCellSeparator *_seperatorView; - UIView *_contentView; - UILabel *_textLabel; - UILabel *_detailTextLabel; // not yet displayed! - UIImageView *_imageView; - UIView *_backgroundView; - UIView *_selectedBackgroundView; - UITableViewCellAccessoryType _accessoryType; - UIView *_accessoryView; - UITableViewCellAccessoryType _editingAccessoryType; - UITableViewCellSelectionStyle _selectionStyle; - NSInteger _indentationLevel; - BOOL _editing; - BOOL _selected; - BOOL _highlighted; - BOOL _showingDeleteConfirmation; - NSString *_reuseIdentifier; - CGFloat _indentationWidth; -} +@class UILabel, UIImageView; +@interface UITableViewCell : UIView - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier; - (void)setSelected:(BOOL)selected animated:(BOOL)animated; - (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated; - (void)prepareForReuse; -@property (nonatomic, readonly, retain) UIView *contentView; -@property (nonatomic, readonly, retain) UILabel *textLabel; -@property (nonatomic, readonly, retain) UILabel *detailTextLabel; -@property (nonatomic, readonly, retain) UIImageView *imageView; -@property (nonatomic, retain) UIView *backgroundView; -@property (nonatomic, retain) UIView *selectedBackgroundView; +@property (nonatomic, readonly, strong) UIView *contentView; +@property (nonatomic, readonly, strong) UILabel *textLabel; +@property (nonatomic, readonly, strong) UILabel *detailTextLabel; +@property (nonatomic, readonly, strong) UIImageView *imageView; +@property (nonatomic, strong) UIView *backgroundView; +@property (nonatomic, strong) UIView *selectedBackgroundView; @property (nonatomic) UITableViewCellSelectionStyle selectionStyle; @property (nonatomic) NSInteger indentationLevel; @property (nonatomic) UITableViewCellAccessoryType accessoryType; -@property (nonatomic, retain) UIView *accessoryView; +@property (nonatomic, strong) UIView *accessoryView; @property (nonatomic) UITableViewCellAccessoryType editingAccessoryType; @property (nonatomic, getter=isSelected) BOOL selected; @property (nonatomic, getter=isHighlighted) BOOL highlighted; @@ -108,5 +86,4 @@ typedef enum { @property (nonatomic, readonly) BOOL showingDeleteConfirmation; // not yet implemented @property (nonatomic, readonly, copy) NSString *reuseIdentifier; @property (nonatomic, assign) CGFloat indentationWidth; // 10 per default - @end diff --git a/UIKit/Classes/UITableViewCell.m b/UIKit/Classes/UITableViewCell.m index d3f5a429..865538c3 100644 --- a/UIKit/Classes/UITableViewCell.m +++ b/UIKit/Classes/UITableViewCell.m @@ -36,12 +36,13 @@ extern CGFloat _UITableViewDefaultRowHeight; -@implementation UITableViewCell -@synthesize accessoryType=_accessoryType, selectionStyle=_selectionStyle, indentationLevel=_indentationLevel; -@synthesize editingAccessoryType=_editingAccessoryType, selected=_selected, backgroundView=_backgroundView; -@synthesize selectedBackgroundView=_selectedBackgroundView, highlighted=_highlighted, reuseIdentifier=_reuseIdentifier; -@synthesize editing = _editing, detailTextLabel = _detailTextLabel, showingDeleteConfirmation = _showingDeleteConfirmation; -@synthesize indentationWidth=_indentationWidth, accessoryView=_accessoryView; +@implementation UITableViewCell { + UITableViewCellStyle _style; + UITableViewCellSeparator *_seperatorView; + UIView *_contentView; + UIImageView *_imageView; + UILabel *_textLabel; +} - (id)initWithFrame:(CGRect)frame { @@ -68,19 +69,6 @@ - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reus return self; } -- (void)dealloc -{ - [_seperatorView release]; - [_contentView release]; - [_accessoryView release]; - [_textLabel release]; - [_detailTextLabel release]; - [_imageView release]; - [_backgroundView release]; - [_selectedBackgroundView release]; - [_reuseIdentifier release]; - [super dealloc]; -} - (void)layoutSubviews { @@ -220,8 +208,7 @@ - (void)setBackgroundView:(UIView *)theBackgroundView { if (theBackgroundView != _backgroundView) { [_backgroundView removeFromSuperview]; - [_backgroundView release]; - _backgroundView = [theBackgroundView retain]; + _backgroundView = theBackgroundView; [self addSubview:_backgroundView]; self.backgroundColor = [UIColor clearColor]; } @@ -231,8 +218,7 @@ - (void)setSelectedBackgroundView:(UIView *)theSelectedBackgroundView { if (theSelectedBackgroundView != _selectedBackgroundView) { [_selectedBackgroundView removeFromSuperview]; - [_selectedBackgroundView release]; - _selectedBackgroundView = [theSelectedBackgroundView retain]; + _selectedBackgroundView = theSelectedBackgroundView; _selectedBackgroundView.hidden = !_selected; [self addSubview:_selectedBackgroundView]; } diff --git a/UIKit/Classes/UITableViewCellSeparator.h b/UIKit/Classes/UITableViewCellSeparator.h index b58cfb9b..361a2728 100644 --- a/UIKit/Classes/UITableViewCellSeparator.h +++ b/UIKit/Classes/UITableViewCellSeparator.h @@ -32,11 +32,7 @@ @class UIColor; -@interface UITableViewCellSeparator : UIView { -@private - UITableViewCellSeparatorStyle _style; - UIColor *_color; -} +@interface UITableViewCellSeparator : UIView - (void)setSeparatorStyle:(UITableViewCellSeparatorStyle)theStyle color:(UIColor *)theColor; diff --git a/UIKit/Classes/UITableViewCellSeparator.m b/UIKit/Classes/UITableViewCellSeparator.m index cb2b0a7d..53630fe1 100644 --- a/UIKit/Classes/UITableViewCellSeparator.m +++ b/UIKit/Classes/UITableViewCellSeparator.m @@ -31,7 +31,10 @@ #import "UIColor.h" #import "UIGraphics.h" -@implementation UITableViewCellSeparator +@implementation UITableViewCellSeparator { + UITableViewCellSeparatorStyle _style; + UIColor *_color; +} - (id)initWithFrame:(CGRect)frame { @@ -42,11 +45,6 @@ - (id)initWithFrame:(CGRect)frame return self; } -- (void)dealloc -{ - [_color release]; - [super dealloc]; -} - (void)setSeparatorStyle:(UITableViewCellSeparatorStyle)theStyle color:(UIColor *)theColor { @@ -56,8 +54,7 @@ - (void)setSeparatorStyle:(UITableViewCellSeparatorStyle)theStyle color:(UIColor } if (_color != theColor) { - [_color release]; - _color = [theColor retain]; + _color = theColor; [self setNeedsDisplay]; } diff --git a/UIKit/Classes/UITableViewController.h b/UIKit/Classes/UITableViewController.h index e30b9dc8..40b618e0 100644 --- a/UIKit/Classes/UITableViewController.h +++ b/UIKit/Classes/UITableViewController.h @@ -30,16 +30,9 @@ #import "UIViewController.h" #import "UITableView.h" -@interface UITableViewController : UIViewController { -@private - UITableViewStyle _style; - BOOL _clearsSelectionOnViewWillAppear; - BOOL _hasReloaded; -} - +@interface UITableViewController : UIViewController - (id)initWithStyle:(UITableViewStyle)style; -@property (nonatomic, retain) UITableView *tableView; +@property (nonatomic, strong) UITableView *tableView; @property (nonatomic) BOOL clearsSelectionOnViewWillAppear; - @end diff --git a/UIKit/Classes/UITableViewController.m b/UIKit/Classes/UITableViewController.m index 82d91fcb..c2e80410 100644 --- a/UIKit/Classes/UITableViewController.m +++ b/UIKit/Classes/UITableViewController.m @@ -29,8 +29,10 @@ #import "UITableViewController.h" -@implementation UITableViewController -@synthesize clearsSelectionOnViewWillAppear=_clearsSelectionOnViewWillAppear; +@implementation UITableViewController { + UITableViewStyle _style; + BOOL _hasReloaded; +} - (id)init { @@ -47,7 +49,7 @@ - (id)initWithStyle:(UITableViewStyle)theStyle - (void)loadView { - self.tableView = [[[UITableView alloc] initWithFrame:CGRectMake(0,0,320,480) style:_style] autorelease]; + self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0,0,320,480) style:_style]; self.tableView.delegate = self; self.tableView.dataSource = self; } diff --git a/UIKit/Classes/UITableViewSection.h b/UIKit/Classes/UITableViewSection.h index 42686d45..c3e05355 100644 --- a/UIKit/Classes/UITableViewSection.h +++ b/UIKit/Classes/UITableViewSection.h @@ -31,17 +31,7 @@ @class UIView; -@interface UITableViewSection : NSObject { - CGFloat rowsHeight; - CGFloat headerHeight; - CGFloat footerHeight; - NSInteger numberOfRows; - CGFloat *rowHeights; - UIView *headerView; - UIView *footerView; - NSString *headerTitle; - NSString *footerTitle; -} +@interface UITableViewSection : NSObject - (CGFloat)sectionHeight; @@ -52,8 +42,8 @@ @property (nonatomic, assign) CGFloat footerHeight; @property (nonatomic, readonly) NSInteger numberOfRows; @property (nonatomic, readonly) CGFloat *rowHeights; -@property (nonatomic, retain) UIView *headerView; -@property (nonatomic, retain) UIView *footerView; +@property (nonatomic, strong) UIView *headerView; +@property (nonatomic, strong) UIView *footerView; @property (nonatomic, copy) NSString *headerTitle; @property (nonatomic, copy) NSString *footerTitle; diff --git a/UIKit/Classes/UITableViewSection.m b/UIKit/Classes/UITableViewSection.m index 51c6b522..d58beea4 100644 --- a/UIKit/Classes/UITableViewSection.m +++ b/UIKit/Classes/UITableViewSection.m @@ -31,27 +31,21 @@ #import "UIView.h" @implementation UITableViewSection -@synthesize rowsHeight, headerHeight, footerHeight, rowHeights, numberOfRows, headerView, footerView, headerTitle, footerTitle; - (CGFloat)sectionHeight { - return rowsHeight + headerHeight + footerHeight; + return self.rowsHeight + self.headerHeight + self.footerHeight; } - (void)setNumberOfRows:(NSInteger)rows withHeights:(CGFloat *)newRowHeights { - rowHeights = realloc(rowHeights, sizeof(CGFloat) * rows); - memcpy(rowHeights, newRowHeights, sizeof(CGFloat) * rows); - numberOfRows = rows; + _rowHeights = realloc(_rowHeights, sizeof(CGFloat) * rows); + memcpy(_rowHeights, newRowHeights, sizeof(CGFloat) * rows); + _numberOfRows = rows; } - (void)dealloc { - if (rowHeights) free(rowHeights); - [headerView release]; - [footerView release]; - [headerTitle release]; - [footerTitle release]; - [super dealloc]; + if (_rowHeights) free(_rowHeights); } @end diff --git a/UIKit/Classes/UITableViewSectionLabel.m b/UIKit/Classes/UITableViewSectionLabel.m index b09d7333..1eb4d0ce 100644 --- a/UIKit/Classes/UITableViewSectionLabel.m +++ b/UIKit/Classes/UITableViewSectionLabel.m @@ -40,7 +40,7 @@ + (UITableViewSectionLabel *)sectionLabelWithTitle:(NSString *)title label.textColor = [UIColor whiteColor]; label.shadowColor = [UIColor colorWithRed:100/255.f green:105/255.f blue:110/255.f alpha:1]; label.shadowOffset = CGSizeMake(0,1); - return [label autorelease]; + return label; } - (void)drawRect:(CGRect)rect diff --git a/UIKit/Classes/UITapGestureRecognizer.h b/UIKit/Classes/UITapGestureRecognizer.h index f6bbcc94..ba88aae5 100644 --- a/UIKit/Classes/UITapGestureRecognizer.h +++ b/UIKit/Classes/UITapGestureRecognizer.h @@ -29,12 +29,7 @@ #import "UIGestureRecognizer.h" -@interface UITapGestureRecognizer : UIGestureRecognizer { - NSUInteger _numberOfTapsRequired; - NSUInteger _numberOfTouchesRequired; -} - +@interface UITapGestureRecognizer : UIGestureRecognizer @property (nonatomic) NSUInteger numberOfTapsRequired; @property (nonatomic) NSUInteger numberOfTouchesRequired; - @end diff --git a/UIKit/Classes/UITapGestureRecognizer.m b/UIKit/Classes/UITapGestureRecognizer.m index dfa512eb..05a98bcb 100644 --- a/UIKit/Classes/UITapGestureRecognizer.m +++ b/UIKit/Classes/UITapGestureRecognizer.m @@ -32,7 +32,6 @@ #import "UITouch.h" @implementation UITapGestureRecognizer -@synthesize numberOfTapsRequired=_numberOfTapsRequired, numberOfTouchesRequired=_numberOfTouchesRequired; - (id)initWithTarget:(id)target action:(SEL)action { diff --git a/UIKit/Classes/UITextField.h b/UIKit/Classes/UITextField.h index 9c569090..23f28bc9 100644 --- a/UIKit/Classes/UITextField.h +++ b/UIKit/Classes/UITextField.h @@ -29,27 +29,27 @@ #import "UIControl.h" #import "UIStringDrawing.h" -#import "UITextInputTraits.h" +#import "UITextInput.h" extern NSString *const UITextFieldTextDidBeginEditingNotification; extern NSString *const UITextFieldTextDidChangeNotification; extern NSString *const UITextFieldTextDidEndEditingNotification; -typedef enum { +typedef NS_ENUM(NSInteger, UITextBorderStyle) { UITextBorderStyleNone, UITextBorderStyleLine, UITextBorderStyleBezel, UITextBorderStyleRoundedRect -} UITextBorderStyle; +}; -typedef enum { +typedef NS_ENUM(NSInteger, UITextFieldViewMode) { UITextFieldViewModeNever, UITextFieldViewModeWhileEditing, UITextFieldViewModeUnlessEditing, UITextFieldViewModeAlways -} UITextFieldViewMode; +}; -@class UIFont, UIColor, UITextField, UIImage, UITextLayer; +@class UIFont, UIColor, UITextField, UIImage; @protocol UITextFieldDelegate @optional @@ -63,39 +63,7 @@ typedef enum { - (BOOL)textFieldShouldReturn:(UITextField *)textField; @end -@interface UITextField : UIControl { -@private - UITextLayer *_textLayer; - - __unsafe_unretained id _delegate; - UITextFieldViewMode _clearButtonMode; - UIView *_leftView; - UITextFieldViewMode _leftViewMode; - UIView *_rightView; - UITextFieldViewMode _rightViewMode; - UIImage *_background; - UIImage *_disabledBackground; - BOOL _editing; - BOOL _clearsOnBeginEditing; - BOOL _adjustsFontSizeToFitWidth; - NSString *_placeholder; - UITextBorderStyle _borderStyle; - CGFloat _minimumFontSize; - - UIView *_inputAccessoryView; - UIView *_inputView; - - struct { - unsigned shouldBeginEditing : 1; - unsigned didBeginEditing : 1; - unsigned shouldEndEditing : 1; - unsigned didEndEditing : 1; - unsigned shouldChangeCharacters : 1; - unsigned shouldClear : 1; - unsigned shouldReturn : 1; - } _delegateHas; -} - +@interface UITextField : UIControl - (CGRect)borderRectForBounds:(CGRect)bounds; - (CGRect)clearButtonRectForBounds:(CGRect)bounds; - (CGRect)editingRectForBounds:(CGRect)bounds; @@ -111,24 +79,33 @@ typedef enum { @property (nonatomic, assign) UITextAlignment textAlignment; @property (nonatomic, copy) NSString *placeholder; @property (nonatomic, copy) NSString *text; -@property (nonatomic, retain) UIFont *font; +@property (nonatomic, strong) UIFont *font; @property (nonatomic) UITextBorderStyle borderStyle; -@property (nonatomic, retain) UIColor *textColor; +@property (nonatomic, strong) UIColor *textColor; @property (nonatomic, readonly, getter=isEditing) BOOL editing; @property (nonatomic) BOOL clearsOnBeginEditing; @property (nonatomic) BOOL adjustsFontSizeToFitWidth; @property (nonatomic) CGFloat minimumFontSize; -@property (nonatomic, retain) UIImage *background; -@property (nonatomic, retain) UIImage *disabledBackground; +@property (nonatomic, strong) UIImage *background; +@property (nonatomic, strong) UIImage *disabledBackground; @property (nonatomic) UITextFieldViewMode clearButtonMode; -@property (nonatomic, retain) UIView *leftView; +@property (nonatomic, strong) UIView *leftView; @property (nonatomic) UITextFieldViewMode leftViewMode; -@property (nonatomic, retain) UIView *rightView; +@property (nonatomic, strong) UIView *rightView; @property (nonatomic) UITextFieldViewMode rightViewMode; -@property (nonatomic, readwrite, retain) UIView *inputAccessoryView; -@property (nonatomic, readwrite, retain) UIView *inputView; +@property (readwrite, strong) UIView *inputAccessoryView; +@property (readwrite, strong) UIView *inputView; +@end + +// for unknown reasons, Apple's UIKit actually declares this here (and not in UIView) +// the documentation makes it sound as if this only resigns text fields, but the comment +// in UIKit's actual UITextField header file indicates it may only care about first +// responder status, so that is how I will implement it +@interface UIView (UITextField) +- (BOOL)endEditing:(BOOL)force; @end + diff --git a/UIKit/Classes/UITextField.m b/UIKit/Classes/UITextField.m index 27f24fed..446fc31b 100644 --- a/UIKit/Classes/UITextField.m +++ b/UIKit/Classes/UITextField.m @@ -44,11 +44,20 @@ @interface UIControl () @interface UITextField () @end -@implementation UITextField -@synthesize delegate=_delegate, background=_background, disabledBackground=_disabledBackground, editing=_editing, clearsOnBeginEditing=_clearsOnBeginEditing; -@synthesize adjustsFontSizeToFitWidth=_adjustsFontSizeToFitWidth, clearButtonMode=_clearButtonMode, leftView=_leftView, rightView=_rightView; -@synthesize leftViewMode=_leftViewMode, rightViewMode=_rightViewMode, placeholder=_placeholder, borderStyle=_borderStyle; -@synthesize inputAccessoryView=_inputAccessoryView, inputView=_inputView, minimumFontSize=_minimumFontSize; +@implementation UITextField { + UITextLayer *_textLayer; + + struct { + unsigned shouldBeginEditing : 1; + unsigned didBeginEditing : 1; + unsigned shouldEndEditing : 1; + unsigned didEndEditing : 1; + unsigned shouldChangeCharacters : 1; + unsigned shouldClear : 1; + unsigned shouldReturn : 1; + } _delegateHas; +} +@synthesize inputAccessoryView, inputView; - (id)initWithFrame:(CGRect)frame { @@ -71,15 +80,6 @@ - (id)initWithFrame:(CGRect)frame - (void)dealloc { [_textLayer removeFromSuperlayer]; - [_textLayer release]; - [_leftView release]; - [_rightView release]; - [_background release]; - [_disabledBackground release]; - [_placeholder release]; - [_inputAccessoryView release]; - [_inputView release]; - [super dealloc]; } - (BOOL)_isLeftViewVisible @@ -134,7 +134,6 @@ - (void)setDelegate:(id)theDelegate - (void)setPlaceholder:(NSString *)thePlaceholder { if (![thePlaceholder isEqualToString:_placeholder]) { - [_placeholder release]; _placeholder = [thePlaceholder copy]; [self setNeedsDisplay]; } @@ -151,8 +150,7 @@ - (void)setBorderStyle:(UITextBorderStyle)style - (void)setBackground:(UIImage *)aBackground { if (aBackground != _background) { - [_background release]; - _background = [aBackground retain]; + _background = aBackground; [self setNeedsDisplay]; } } @@ -160,8 +158,7 @@ - (void)setBackground:(UIImage *)aBackground - (void)setDisabledBackground:(UIImage *)aBackground { if (aBackground != _disabledBackground) { - [_disabledBackground release]; - _disabledBackground = [aBackground retain]; + _disabledBackground = aBackground; [self setNeedsDisplay]; } } @@ -170,8 +167,7 @@ - (void)setLeftView:(UIView *)leftView { if (leftView != _leftView) { [_leftView removeFromSuperview]; - [_leftView release]; - _leftView = [leftView retain]; + _leftView = leftView; [self addSubview:_leftView]; } } @@ -180,8 +176,7 @@ - (void)setRightView:(UIView *)rightView { if (rightView != _rightView) { [_rightView removeFromSuperview]; - [_rightView release]; - _rightView = [rightView retain]; + _rightView = rightView; [self addSubview:_rightView]; } } @@ -372,11 +367,13 @@ - (BOOL)canBecomeFirstResponder - (BOOL)becomeFirstResponder { - if ([super becomeFirstResponder]) { - return [_textLayer becomeFirstResponder]; - } else { - return NO; + BOOL result = [super becomeFirstResponder]; + + if (result && (result = [_textLayer becomeFirstResponder])) { + [self _textDidBeginEditing]; } + + return result; } - (BOOL)resignFirstResponder @@ -514,4 +511,67 @@ - (id)mouseCursorForEvent:(UIEvent *)event return [NSCursor IBeamCursor]; } +- (CGSize)sizeThatFits:(CGSize)size +{ + return [_textLayer sizeThatFits:size]; +} + +#pragma mark UITextInput + +- (void)setSelectedTextRange:(UITextRange *)range +{ +} + +- (UITextRange *)selectedTextRange +{ + return nil; +} + +- (UITextRange *)beginningOfDocument +{ + return nil; +} + +- (UITextPosition *)endOfDocument +{ + return nil; +} + +- (NSInteger)offsetFromPosition:(UITextPosition *)fromPosition toPosition:(UITextPosition *)toPosition +{ + return 0; +} + +- (UITextPosition *)positionFromPosition:(UITextPosition *)position offset:(NSInteger)offset +{ + return nil; +} + +- (UITextRange *)textRangeFromPosition:(UITextPosition *)fromPosition toPosition:(UITextPosition *)toPosition +{ + return nil; +} + +@end + + +@implementation UIView (UITextField) + +- (BOOL)endEditing:(BOOL)force +{ + if ([self isFirstResponder]) { + if (force || [self canResignFirstResponder]) { + return [self resignFirstResponder]; + } + } else { + for (UIView *view in self.subviews) { + if ([view endEditing:force]) { + return YES; + } + } + } + + return NO; +} + @end diff --git a/UIKit/Classes/UIViewBlockAnimationDelegate.m b/UIKit/Classes/UITextInput.h similarity index 62% rename from UIKit/Classes/UIViewBlockAnimationDelegate.m rename to UIKit/Classes/UITextInput.h index 8ad5d1f1..07dd4216 100644 --- a/UIKit/Classes/UIViewBlockAnimationDelegate.m +++ b/UIKit/Classes/UITextInput.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, The Iconfactory. All rights reserved. + * Copyright (c) 2013, The Iconfactory. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -27,27 +27,25 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#import "UIViewBlockAnimationDelegate.h" -#import "UIApplication.h" +#import "UITextInputTraits.h" -@implementation UIViewBlockAnimationDelegate -@synthesize completion=_completion, ignoreInteractionEvents=_ignoreInteractionEvents; +@interface UITextPosition : NSObject +@end -- (void)dealloc -{ - [_completion release]; - [super dealloc]; -} +@interface UITextRange : NSObject +@property (nonatomic, readonly) UITextPosition *start; +@property (nonatomic, readonly) UITextPosition *end; +@property (nonatomic, readonly, getter=isEmpty) BOOL empty; +@end -- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished -{ - if (_completion) { - _completion([finished boolValue]); - } - - if (_ignoreInteractionEvents) { - [[UIApplication sharedApplication] endIgnoringInteractionEvents]; - } -} +@protocol UIKeyInput +@end +@protocol UITextInput +@property (readwrite, copy) UITextRange *selectedTextRange; +@property (nonatomic, readonly) UITextPosition *beginningOfDocument; +@property (nonatomic, readonly) UITextPosition *endOfDocument; +- (NSInteger)offsetFromPosition:(UITextPosition *)fromPosition toPosition:(UITextPosition *)toPosition; +- (UITextPosition *)positionFromPosition:(UITextPosition *)position offset:(NSInteger)offset; +- (UITextRange *)textRangeFromPosition:(UITextPosition *)fromPosition toPosition:(UITextPosition *)toPosition; @end diff --git a/UIKit/Classes/UIKey+UIPrivate.h b/UIKit/Classes/UITextInput.m similarity index 90% rename from UIKit/Classes/UIKey+UIPrivate.h rename to UIKit/Classes/UITextInput.m index 31795af3..dc51db4a 100644 --- a/UIKit/Classes/UIKey+UIPrivate.h +++ b/UIKit/Classes/UITextInput.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, The Iconfactory. All rights reserved. + * Copyright (c) 2013, The Iconfactory. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -27,10 +27,10 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#import "UIKey.h" +#import "UITextInput.h" -@class NSEvent; +@implementation UITextPosition +@end -@interface UIKey (UIPrivate) -- (id)initWithNSEvent:(NSEvent *)event; +@implementation UITextRange @end diff --git a/UIKit/Classes/UITextInputTraits.h b/UIKit/Classes/UITextInputTraits.h index 1c3ca1bc..32872f17 100644 --- a/UIKit/Classes/UITextInputTraits.h +++ b/UIKit/Classes/UITextInputTraits.h @@ -29,25 +29,25 @@ #import -typedef enum { +typedef NS_ENUM(NSInteger, UITextAutocapitalizationType) { UITextAutocapitalizationTypeNone, UITextAutocapitalizationTypeWords, UITextAutocapitalizationTypeSentences, UITextAutocapitalizationTypeAllCharacters, -} UITextAutocapitalizationType; +}; -typedef enum { +typedef NS_ENUM(NSInteger, UITextAutocorrectionType) { UITextAutocorrectionTypeDefault, UITextAutocorrectionTypeNo, UITextAutocorrectionTypeYes, -} UITextAutocorrectionType; +}; -typedef enum { +typedef NS_ENUM(NSInteger, UIKeyboardAppearance) { UIKeyboardAppearanceDefault, UIKeyboardAppearanceAlert, -} UIKeyboardAppearance; +}; -typedef enum { +typedef NS_ENUM(NSInteger, UIKeyboardType) { UIKeyboardTypeDefault, UIKeyboardTypeASCIICapable, UIKeyboardTypeNumbersAndPunctuation, @@ -56,10 +56,12 @@ typedef enum { UIKeyboardTypePhonePad, UIKeyboardTypeNamePhonePad, UIKeyboardTypeEmailAddress, + UIKeyboardTypeDecimalPad, + UIKeyboardTypeTwitter, UIKeyboardTypeAlphabet = UIKeyboardTypeASCIICapable -} UIKeyboardType; +}; -typedef enum { +typedef NS_ENUM(NSInteger, UIReturnKeyType) { UIReturnKeyDefault, UIReturnKeyGo, UIReturnKeyGoogle, @@ -71,7 +73,7 @@ typedef enum { UIReturnKeyYahoo, UIReturnKeyDone, UIReturnKeyEmergencyCall, -} UIReturnKeyType; +}; @protocol UITextInputTraits @property (nonatomic) UITextAutocapitalizationType autocapitalizationType; diff --git a/UIKit/Classes/UITextLayer.h b/UIKit/Classes/UITextLayer.h index c6092e0f..9cd1ed01 100644 --- a/UIKit/Classes/UITextLayer.h +++ b/UIKit/Classes/UITextLayer.h @@ -54,7 +54,6 @@ @protocol UITextLayerTextDelegate @required - (BOOL)_textShouldBeginEditing; -- (void)_textDidBeginEditing; - (BOOL)_textShouldEndEditing; - (void)_textDidEndEditing; - (BOOL)_textShouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text; @@ -65,34 +64,19 @@ - (void)_textDidReceiveReturnKey; @end -@interface UITextLayer : CALayer { - id containerView; - BOOL containerCanScroll; - UICustomNSTextView *textView; - UICustomNSClipView *clipView; - BOOL secureTextEntry; - BOOL editable; - UIColor *textColor; - UIFont *font; - BOOL changingResponderStatus; - - struct { - unsigned didChange : 1; - unsigned didChangeSelection : 1; - unsigned didReturnKey : 1; - } textDelegateHas; -} +@interface UITextLayer : CALayer - (id)initWithContainer:(UIView *)aView isField:(BOOL)isField; - (void)setContentOffset:(CGPoint)contentOffset; - (void)scrollRangeToVisible:(NSRange)range; - (BOOL)becomeFirstResponder; - (BOOL)resignFirstResponder; +- (CGSize)sizeThatFits:(CGSize)size; @property (nonatomic, assign) NSRange selectedRange; @property (nonatomic, copy) NSString *text; -@property (nonatomic, retain) UIColor *textColor; -@property (nonatomic, retain) UIFont *font; +@property (nonatomic, strong) UIColor *textColor; +@property (nonatomic, strong) UIFont *font; @property (nonatomic, assign) BOOL editable; @property (nonatomic, getter=isSecureTextEntry) BOOL secureTextEntry; @property (nonatomic, assign) UITextAlignment textAlignment; diff --git a/UIKit/Classes/UITextLayer.m b/UIKit/Classes/UITextLayer.m index 638e48ab..555ba2ee 100644 --- a/UIKit/Classes/UITextLayer.m +++ b/UIKit/Classes/UITextLayer.m @@ -32,12 +32,10 @@ #import "UICustomNSTextView.h" #import "UICustomNSClipView.h" #import "UIWindow.h" -#import "UIScreen+UIPrivate.h" -#import "UIScreenAppKitIntegration.h" -#import "UIApplication+UIPrivate.h" +#import "UIKitView.h" #import "AppKitIntegration.h" #import "UIView+UIPrivate.h" -#import "UIKitView.h" +#import "UIKey.h" #import #import @@ -45,31 +43,42 @@ @interface UITextLayer () *_containerView; + BOOL _containerCanScroll; + UICustomNSTextView *_textView; + UICustomNSClipView *_clipView; + BOOL _changingResponderStatus; + + struct { + unsigned didChange : 1; + unsigned didChangeSelection : 1; + unsigned didReturnKey : 1; + } _textDelegateHas; +} - (id)initWithContainer:(UIView *)aView isField:(BOOL)isField { if ((self=[super init])) { self.masksToBounds = NO; - containerView = aView; + _containerView = aView; - textDelegateHas.didChange = [containerView respondsToSelector:@selector(_textDidChange)]; - textDelegateHas.didChangeSelection = [containerView respondsToSelector:@selector(_textDidChangeSelection)]; - textDelegateHas.didReturnKey = [containerView respondsToSelector:@selector(_textDidReceiveReturnKey)]; + _textDelegateHas.didChange = [_containerView respondsToSelector:@selector(_textDidChange)]; + _textDelegateHas.didChangeSelection = [_containerView respondsToSelector:@selector(_textDidChangeSelection)]; + _textDelegateHas.didReturnKey = [_containerView respondsToSelector:@selector(_textDidReceiveReturnKey)]; - containerCanScroll = [containerView respondsToSelector:@selector(setContentOffset:)] - && [containerView respondsToSelector:@selector(contentOffset)] - && [containerView respondsToSelector:@selector(setContentSize:)] - && [containerView respondsToSelector:@selector(contentSize)] - && [containerView respondsToSelector:@selector(isScrollEnabled)]; + _containerCanScroll = [_containerView respondsToSelector:@selector(setContentOffset:)] + && [_containerView respondsToSelector:@selector(contentOffset)] + && [_containerView respondsToSelector:@selector(setContentSize:)] + && [_containerView respondsToSelector:@selector(contentSize)] + && [_containerView respondsToSelector:@selector(isScrollEnabled)]; - clipView = [(UICustomNSClipView *)[UICustomNSClipView alloc] initWithFrame:NSMakeRect(0,0,100,100)]; - textView = [(UICustomNSTextView *)[UICustomNSTextView alloc] initWithFrame:[clipView frame] secureTextEntry:secureTextEntry isField:isField]; + _clipView = [(UICustomNSClipView *)[UICustomNSClipView alloc] initWithFrame:NSMakeRect(0,0,100,100)]; + _textView = [(UICustomNSTextView *)[UICustomNSTextView alloc] initWithFrame:[_clipView frame] secureTextEntry:_secureTextEntry isField:isField]; - [textView setDelegate:self]; - [clipView setDocumentView:textView]; + [_textView setDelegate:self]; + [_clipView setDocumentView:_textView]; self.textAlignment = UITextAlignmentLeft; [self setNeedsLayout]; @@ -79,13 +88,8 @@ - (id)initWithContainer:(UIView @optional @@ -49,40 +49,18 @@ extern NSString *const UITextViewTextDidEndEditingNotification; - (void)textViewDidChangeSelection:(UITextView *)textView; @end -@interface UITextView : UIScrollView { -@private - UITextLayer *_textLayer; - UIDataDetectorTypes _dataDetectorTypes; - - UIView *_inputAccessoryView; - UIView *_inputView; - - struct { - unsigned shouldBeginEditing : 1; - unsigned didBeginEditing : 1; - unsigned shouldEndEditing : 1; - unsigned didEndEditing : 1; - unsigned shouldChangeText : 1; - unsigned didChange : 1; - unsigned didChangeSelection : 1; - } _delegateHas; -} - +@interface UITextView : UIScrollView - (void)scrollRangeToVisible:(NSRange)range; - +- (BOOL)hasText; @property (nonatomic) UITextAlignment textAlignment; // stub, not yet implemented! @property (nonatomic) NSRange selectedRange; @property (nonatomic, getter=isEditable) BOOL editable; @property (nonatomic, copy) NSString *text; -@property (nonatomic, retain) UIColor *textColor; -@property (nonatomic, retain) UIFont *font; +@property (nonatomic, strong) UIColor *textColor; +@property (nonatomic, strong) UIFont *font; @property (nonatomic) UIDataDetectorTypes dataDetectorTypes; @property (nonatomic, assign) id delegate; - -@property (nonatomic, readwrite, retain) UIView *inputAccessoryView; -@property (nonatomic, readwrite, retain) UIView *inputView; - -- (BOOL)hasText; - +@property (readwrite, strong) UIView *inputAccessoryView; +@property (readwrite, strong) UIView *inputView; @end diff --git a/UIKit/Classes/UITextView.m b/UIKit/Classes/UITextView.m index a89563df..9c5106fd 100644 --- a/UIKit/Classes/UITextView.m +++ b/UIKit/Classes/UITextView.m @@ -45,9 +45,20 @@ @interface UITextView () @end -@implementation UITextView -@synthesize dataDetectorTypes=_dataDetectorTypes, inputAccessoryView=_inputAccessoryView, inputView=_inputView; -@dynamic delegate; +@implementation UITextView { + UITextLayer *_textLayer; + + struct { + unsigned shouldBeginEditing : 1; + unsigned didBeginEditing : 1; + unsigned shouldEndEditing : 1; + unsigned didEndEditing : 1; + unsigned shouldChangeText : 1; + unsigned didChange : 1; + unsigned didChangeSelection : 1; + } _delegateHas; +} +@synthesize inputAccessoryView, inputView; - (id)initWithFrame:(CGRect)frame { @@ -68,10 +79,6 @@ - (id)initWithFrame:(CGRect)frame - (void)dealloc { [_textLayer removeFromSuperlayer]; - [_textLayer release]; - [_inputAccessoryView release]; - [_inputView release]; - [super dealloc]; } - (void)layoutSubviews @@ -328,4 +335,45 @@ - (id)mouseCursorForEvent:(UIEvent *)event return self.editable? [NSCursor IBeamCursor] : nil; } +- (CGSize)sizeThatFits:(CGSize)size +{ + return [_textLayer sizeThatFits:size]; +} + +#pragma mark UITextInput + +- (void)setSelectedTextRange:(UITextRange *)range +{ +} + +- (UITextRange *)selectedTextRange +{ + return nil; +} + +- (UITextRange *)beginningOfDocument +{ + return nil; +} + +- (UITextPosition *)endOfDocument +{ + return nil; +} + +- (NSInteger)offsetFromPosition:(UITextPosition *)fromPosition toPosition:(UITextPosition *)toPosition +{ + return 0; +} + +- (UITextPosition *)positionFromPosition:(UITextPosition *)position offset:(NSInteger)offset +{ + return nil; +} + +- (UITextRange *)textRangeFromPosition:(UITextPosition *)fromPosition toPosition:(UITextPosition *)toPosition +{ + return nil; +} + @end diff --git a/UIKit/Classes/UIThreePartImage.h b/UIKit/Classes/UIThreePartImage.h index 1390109b..a0959ca8 100644 --- a/UIKit/Classes/UIThreePartImage.h +++ b/UIKit/Classes/UIThreePartImage.h @@ -29,11 +29,7 @@ #import "UIImage+UIPrivate.h" -@interface UIThreePartImage : UIImage { -@private - NSInteger _capSize; - BOOL _vertical; -} +@interface UIThreePartImage : UIImage - (id)initWithRepresentations:(NSArray *)reps capSize:(NSInteger)capSize vertical:(BOOL)isVertical; diff --git a/UIKit/Classes/UIThreePartImage.m b/UIKit/Classes/UIThreePartImage.m index 5ff5ffe9..31834ad0 100644 --- a/UIKit/Classes/UIThreePartImage.m +++ b/UIKit/Classes/UIThreePartImage.m @@ -30,7 +30,10 @@ #import "UIThreePartImage.h" #import "UIImageRep.h" -@implementation UIThreePartImage +@implementation UIThreePartImage { + NSInteger _capSize; + BOOL _vertical; +} - (id)initWithRepresentations:(NSArray *)reps capSize:(NSInteger)capSize vertical:(BOOL)isVertical { diff --git a/UIKit/Classes/UIToolbar.h b/UIKit/Classes/UIToolbar.h index 54ced7b0..a1f80505 100644 --- a/UIKit/Classes/UIToolbar.h +++ b/UIKit/Classes/UIToolbar.h @@ -30,25 +30,20 @@ #import "UIView.h" #import "UIInterface.h" -typedef enum { +typedef NS_ENUM(NSInteger, UIToolbarPosition) { UIToolbarPositionAny = 0, UIToolbarPositionBottom = 1, UIToolbarPositionTop = 2, -} UIToolbarPosition; - -@interface UIToolbar : UIView { -@private - UIBarStyle _barStyle; - UIColor *_tintColor; - NSMutableArray *_toolbarItems; - BOOL _translucent; -} +}; +@interface UIToolbar : UIView - (void)setItems:(NSArray *)items animated:(BOOL)animated; +- (UIImage *)backgroundImageForToolbarPosition:(UIToolbarPosition)topOrBottom barMetrics:(UIBarMetrics)barMetrics; +- (void)setBackgroundImage:(UIImage *)backgroundImage forToolbarPosition:(UIToolbarPosition)topOrBottom barMetrics:(UIBarMetrics)barMetrics; + @property (nonatomic) UIBarStyle barStyle; -@property (nonatomic, retain) UIColor *tintColor; +@property (nonatomic, strong) UIColor *tintColor; @property (nonatomic, copy) NSArray *items; @property (nonatomic,assign,getter=isTranslucent) BOOL translucent; - @end diff --git a/UIKit/Classes/UIToolbar.m b/UIKit/Classes/UIToolbar.m index 54b31289..88852e31 100644 --- a/UIKit/Classes/UIToolbar.m +++ b/UIKit/Classes/UIToolbar.m @@ -33,14 +33,9 @@ #import "UIColor.h" #import "UIGraphics.h" +static const CGFloat kBarHeight = 28; - - - -@interface UIToolbarItem : NSObject { - UIBarButtonItem *item; - UIView *view; -} +@interface UIToolbarItem : NSObject - (id)initWithBarButtonItem:(UIBarButtonItem *)anItem; @@ -51,37 +46,30 @@ - (id)initWithBarButtonItem:(UIBarButtonItem *)anItem; @end @implementation UIToolbarItem -@synthesize item, view; - (id)initWithBarButtonItem:(UIBarButtonItem *)anItem { if ((self=[super init])) { NSAssert((anItem != nil), @"the bar button item must not be nil"); - item = [anItem retain]; + _item = anItem; - if (!item->_isSystemItem && item.customView) { - view = [item.customView retain]; - } else if (!item->_isSystemItem || (item->_systemItem != UIBarButtonSystemItemFixedSpace && item->_systemItem != UIBarButtonSystemItemFlexibleSpace)) { - view = [[UIToolbarButton alloc] initWithBarButtonItem:item]; + if (!_item->_isSystemItem && _item.customView) { + _view = _item.customView; + } else if (!_item->_isSystemItem || (_item->_systemItem != UIBarButtonSystemItemFixedSpace && _item->_systemItem != UIBarButtonSystemItemFlexibleSpace)) { + _view = [[UIToolbarButton alloc] initWithBarButtonItem:_item]; } } return self; } -- (void)dealloc -{ - [item release]; - [view release]; - [super dealloc]; -} - (CGFloat)width { - if (view) { - return view.frame.size.width; - } else if (item->_isSystemItem && item->_systemItem == UIBarButtonSystemItemFixedSpace) { - return item.width; + if (_view) { + return _view.frame.size.width; + } else if (_item->_isSystemItem && _item->_systemItem == UIBarButtonSystemItemFixedSpace) { + return _item.width; } else { return -1; } @@ -96,16 +84,14 @@ - (CGFloat)width -@implementation UIToolbar -@synthesize barStyle=_barStyle, tintColor=_tintColor, translucent=_translucent; - -- (id)init -{ - return [self initWithFrame:CGRectMake(0,0,320,32)]; +@implementation UIToolbar { + NSMutableArray *_toolbarItems; } - (id)initWithFrame:(CGRect)frame { + frame.size.height = kBarHeight; + if ((self=[super initWithFrame:frame])) { _toolbarItems = [[NSMutableArray alloc] init]; self.barStyle = UIBarStyleDefault; @@ -115,13 +101,6 @@ - (id)initWithFrame:(CGRect)frame return self; } -- (void)dealloc -{ - [_tintColor release]; - [_toolbarItems release]; - [super dealloc]; -} - - (void)setBarStyle:(UIBarStyle)newStyle { _barStyle = newStyle; @@ -242,7 +221,6 @@ - (void)setItems:(NSArray *)newItems animated:(BOOL)animated UIToolbarItem *toolbarItem = [[UIToolbarItem alloc] initWithBarButtonItem:item]; [_toolbarItems addObject:toolbarItem]; [self addSubview:toolbarItem.view]; - [toolbarItem release]; } // if animated, fade them in @@ -302,4 +280,19 @@ - (NSString *)description return [NSString stringWithFormat:@"<%@: %p; barStyle = %@; tintColor = %@, isTranslucent = %@>", [self className], self, barStyle, ([self.tintColor description] ?: @"Default"), (self.translucent ? @"YES" : @"NO")]; } +- (UIImage *)backgroundImageForToolbarPosition:(UIToolbarPosition)topOrBottom barMetrics:(UIBarMetrics)barMetrics +{ + return nil; +} + +- (void)setBackgroundImage:(UIImage *)backgroundImage forToolbarPosition:(UIToolbarPosition)topOrBottom barMetrics:(UIBarMetrics)barMetrics +{ +} + +- (CGSize)sizeThatFits:(CGSize)size +{ + size.height = kBarHeight; + return size; +} + @end diff --git a/UIKit/Classes/UIToolbarButton.h b/UIKit/Classes/UIToolbarButton.h index 371b5317..574352fd 100644 --- a/UIKit/Classes/UIToolbarButton.h +++ b/UIKit/Classes/UIToolbarButton.h @@ -31,8 +31,7 @@ @class UIBarButtonItem; -@interface UIToolbarButton : UIButton { -} +@interface UIToolbarButton : UIButton - (id)initWithBarButtonItem:(UIBarButtonItem *)item; diff --git a/UIKit/Classes/UITouch+UIPrivate.h b/UIKit/Classes/UITouch+UIPrivate.h index 2bdbed0f..1c17ed64 100644 --- a/UIKit/Classes/UITouch+UIPrivate.h +++ b/UIKit/Classes/UITouch+UIPrivate.h @@ -29,19 +29,20 @@ #import "UITouch.h" -@class UIView; +@class UIGestureRecognizer; @interface UITouch (UIPrivate) -- (void)_setPhase:(UITouchPhase)phase screenLocation:(CGPoint)screenLocation tapCount:(NSUInteger)tapCount timestamp:(NSTimeInterval)timestamp; -- (void)_updatePhase:(UITouchPhase)phase screenLocation:(CGPoint)screenLocation timestamp:(NSTimeInterval)timestamp; -- (void)_updateGesture:(_UITouchGesture)gesture screenLocation:(CGPoint)screenLocation delta:(CGPoint)delta rotation:(CGFloat)rotation magnification:(CGFloat)magnification timestamp:(NSTimeInterval)timestamp; -- (void)_setDiscreteGesture:(_UITouchGesture)gesture screenLocation:(CGPoint)screenLocation tapCount:(NSUInteger)tapCount delta:(CGPoint)delta timestamp:(NSTimeInterval)timestamp; -- (void)_setTouchedView:(UIView *)view; // sets up the window and gesture recognizers as well -- (void)_removeFromView; // sets the initial view to nil, but leaves window and gesture recognizers alone - used when a view is removed while touch is active -- (void)_setTouchPhaseCancelled; -- (CGPoint)_delta; -- (CGFloat)_rotation; -- (CGFloat)_magnification; -- (UIView *)_previousView; -- (_UITouchGesture)_gesture; +@property (nonatomic, readwrite, assign) NSTimeInterval timestamp; // defaults to now +@property (nonatomic, readwrite, assign) NSUInteger tapCount; // defaults to 0 +@property (nonatomic, readwrite, assign) UITouchPhase phase; // defaults to UITouchPhaseBegan, if changed to UITouchPhaseStationary, also sets previous location to current value of locationInWindow +@property (nonatomic, readwrite, assign) UIView *view; // defaults to nil +@property (nonatomic, readwrite, assign) CGPoint locationOnScreen; // if phase is UITouchPhaseBegan or UITouchPhaseStationary, also sets internal previous location to same value + +@property (nonatomic, readwrite, assign) BOOL wasDeliveredToView; // defaults to NO, used to keep things on the up and up with gesture recognizers that can delay and cancel touches (pure evil) +@property (nonatomic, readwrite, assign) BOOL wasCancelledInView; // defaults to NO, used to keep things on the up and up with gesture recognizers that can delay and cancel touches (pure evil) +@property (nonatomic, readonly) NSTimeInterval beganPhaseTimestamp; // when phase is UITouchPhaseBegan, changes to timestamp property also copied here +@property (nonatomic, readonly) CGPoint beganPhaseLocationOnScreen; // when phase is UITouchPhaseBegan, changes to locationOnScreen property also copied here + +- (void)_addGestureRecognizer:(UIGestureRecognizer *)recognizer; +- (void)_removeGestureRecognizer:(UIGestureRecognizer *)recognizer; @end diff --git a/UIKit/Classes/UITouch.h b/UIKit/Classes/UITouch.h index 3344b1a3..ea27e7cc 100644 --- a/UIKit/Classes/UITouch.h +++ b/UIKit/Classes/UITouch.h @@ -29,55 +29,24 @@ #import -typedef enum { +typedef NS_ENUM(NSInteger, UITouchPhase) { UITouchPhaseBegan, UITouchPhaseMoved, UITouchPhaseStationary, UITouchPhaseEnded, UITouchPhaseCancelled, - _UITouchPhaseGestureBegan, - _UITouchPhaseGestureChanged, - _UITouchPhaseGestureEnded, - _UITouchPhaseDiscreteGesture -} UITouchPhase; - -typedef enum { - _UITouchGestureUnknown = 0, - _UITouchGesturePan, // maps only to touch-enabled scrolling devices like magic trackpad, etc. for older wheels, use _UITouchGestureScrollWheel - _UITouchGestureRotation, // only works for touch-enabled input devices - _UITouchGesturePinch, // only works for touch-enabled input devices - _UITouchGestureSwipe, // only works for touch-enabled input devices (this is actually discrete, but OSX sends gesture begin/end events around it) - _UITouchDiscreteGestureRightClick, // should be pretty obvious - _UITouchDiscreteGestureScrollWheel, // this is used by old fashioned wheel mice or when the OS sends its automatic momentum scroll events - _UITouchDiscreteGestureMouseMove // the mouse moved but wasn't in a gesture or the button was not being held down -} _UITouchGesture; +}; @class UIView, UIWindow; -@interface UITouch : NSObject { -@private - NSTimeInterval _timestamp; - NSUInteger _tapCount; - UITouchPhase _phase; - _UITouchGesture _gesture; - CGPoint _delta; - CGFloat _rotation; - CGFloat _magnification; - CGPoint _location; - CGPoint _previousLocation; - UIView *_view; - UIWindow *_window; - NSArray *_gestureRecognizers; -} - +@interface UITouch : NSObject - (CGPoint)locationInView:(UIView *)inView; - (CGPoint)previousLocationInView:(UIView *)inView; @property (nonatomic, readonly) NSTimeInterval timestamp; @property (nonatomic, readonly) NSUInteger tapCount; @property (nonatomic, readonly) UITouchPhase phase; -@property (nonatomic, readonly, retain) UIView *view; -@property (nonatomic, readonly, retain) UIWindow *window; -@property (nonatomic,readonly,copy) NSArray *gestureRecognizers; - +@property (nonatomic, readonly, strong) UIView *view; +@property (nonatomic, readonly, strong) UIWindow *window; +@property (nonatomic, readonly, copy) NSArray *gestureRecognizers; @end diff --git a/UIKit/Classes/UITouch.m b/UIKit/Classes/UITouch.m index 1c9852d8..3dcb8fe4 100644 --- a/UIKit/Classes/UITouch.m +++ b/UIKit/Classes/UITouch.m @@ -29,197 +29,149 @@ #import "UITouch+UIPrivate.h" #import "UIWindow.h" -#import "UIGestureRecognizerSubclass.h" -#import +#import "UIView+UIPrivate.h" -static NSArray *GestureRecognizersForView(UIView *view) -{ - NSMutableArray *recognizers = [[NSMutableArray alloc] initWithCapacity:0]; - - while (view) { - [recognizers addObjectsFromArray:view.gestureRecognizers]; - view = [view superview]; - } - - return [recognizers autorelease]; +@implementation UITouch { + CGPoint _locationOnScreen; + CGPoint _previousLocationOnScreen; + NSMutableArray *_gestureRecognizers; + BOOL _wasDeliveredToView; + BOOL _wasCancelledInView; + NSTimeInterval _beganPhaseTimestamp; + CGPoint _beganPhaseLocationOnScreen; } -@implementation UITouch -@synthesize timestamp=_timestamp, tapCount=_tapCount, phase=_phase, view=_view, window=_window, gestureRecognizers=_gestureRecognizers; - - (id)init { if ((self=[super init])) { - _phase = UITouchPhaseCancelled; - _gesture = _UITouchGestureUnknown; + _phase = UITouchPhaseBegan; + _timestamp = [NSDate timeIntervalSinceReferenceDate]; + _gestureRecognizers = [NSMutableArray new]; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_viewDidMoveToSuperviewNotification:) name:UIViewDidMoveToSuperviewNotification object:nil]; } return self; } - (void)dealloc { - [_window release]; - [_view release]; - [_gestureRecognizers release]; - [super dealloc]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIViewDidMoveToSuperviewNotification object:nil]; } +- (void)_viewDidMoveToSuperviewNotification:(NSNotification *)notification +{ + if ([_view isDescendantOfView:[notification object]]) { + _view = nil; + } +} - - -- (void)_setPhase:(UITouchPhase)phase screenLocation:(CGPoint)screenLocation tapCount:(NSUInteger)tapCount timestamp:(NSTimeInterval)timestamp; +- (void)setTimestamp:(NSTimeInterval)timestamp { - _phase = phase; - _gesture = _UITouchGestureUnknown; - _previousLocation = _location = screenLocation; - _tapCount = tapCount; _timestamp = timestamp; - _rotation = 0; - _magnification = 0; + + if (_phase == UITouchPhaseBegan) { + _beganPhaseTimestamp = timestamp; + } } -- (void)_updatePhase:(UITouchPhase)phase screenLocation:(CGPoint)screenLocation timestamp:(NSTimeInterval)timestamp; +- (void)setTapCount:(NSUInteger)tapCount { - if (!CGPointEqualToPoint(screenLocation, _location)) { - _previousLocation = _location; - _location = screenLocation; - } - - _phase = phase; - _timestamp = timestamp; + _tapCount = tapCount; } -- (void)_updateGesture:(_UITouchGesture)gesture screenLocation:(CGPoint)screenLocation delta:(CGPoint)delta rotation:(CGFloat)rotation magnification:(CGFloat)magnification timestamp:(NSTimeInterval)timestamp; +- (void)setPhase:(UITouchPhase)phase { - if (!CGPointEqualToPoint(screenLocation, _location)) { - _previousLocation = _location; - _location = screenLocation; - } - - _phase = _UITouchPhaseGestureChanged; + _phase = phase; - _gesture = gesture; - _delta = delta; - _rotation = rotation; - _magnification = magnification; - _timestamp = timestamp; + if (phase == UITouchPhaseStationary || phase == UITouchPhaseBegan) { + _previousLocationOnScreen = _locationOnScreen; + } } -- (void)_setDiscreteGesture:(_UITouchGesture)gesture screenLocation:(CGPoint)screenLocation tapCount:(NSUInteger)tapCount delta:(CGPoint)delta timestamp:(NSTimeInterval)timestamp; +- (void)setView:(UIView *)view { - _phase = _UITouchPhaseDiscreteGesture; - _gesture = gesture; - _previousLocation = _location = screenLocation; - _tapCount = tapCount; - _delta = delta; - _timestamp = timestamp; - _rotation = 0; - _magnification = 0; + _view = view; + _window = view.window; } -- (_UITouchGesture)_gesture +- (CGPoint)locationOnScreen { - return _gesture; + return _locationOnScreen; } -- (void)_setTouchedView:(UIView *)view +- (void)setLocationOnScreen:(CGPoint)locationOnScreen { - if (_view != view) { - [_view release]; - _view = [view retain]; - } + _previousLocationOnScreen = _locationOnScreen; + _locationOnScreen = locationOnScreen; - if (_window != view.window) { - [_window release]; - _window = [view.window retain]; + if (_phase == UITouchPhaseStationary || _phase == UITouchPhaseBegan) { + _previousLocationOnScreen = locationOnScreen; + } + + if (_phase == UITouchPhaseBegan) { + _beganPhaseLocationOnScreen = locationOnScreen; } +} - [_gestureRecognizers release]; - _gestureRecognizers = [GestureRecognizersForView(_view) copy]; +- (BOOL)wasDeliveredToView +{ + return _wasDeliveredToView; } -- (void)_removeFromView +- (void)setWasDeliveredToView:(BOOL)wasDeliveredToView { - NSMutableArray *remainingRecognizers = [_gestureRecognizers mutableCopy]; + _wasDeliveredToView = wasDeliveredToView; +} - // if the view is being removed from this touch, we need to remove/cancel any gesture recognizers that belong to the view - // being removed. this kinda feels like the wrong place for this, but the touch itself has a list of potential gesture - // recognizers attached to it so an active touch only considers the recongizers that were present at the point the touch - // first touched the screen. it could easily have recognizers attached to it from superviews of the view being removed so - // we can't just cancel them all. the view itself could cancel its own recognizers, but then it needs a way to remove them - // from an active touch so in a sense we're right back where we started. so I figured we might as well just take care of it - // here and see what happens. - for (UIGestureRecognizer *recognizer in _gestureRecognizers) { - if (recognizer.view == _view) { - if (recognizer.state == UIGestureRecognizerStateBegan || recognizer.state == UIGestureRecognizerStateChanged) { - recognizer.state = UIGestureRecognizerStateCancelled; - } - [remainingRecognizers removeObject:recognizer]; - } - } - - [_gestureRecognizers release]; - _gestureRecognizers = [remainingRecognizers copy]; - [remainingRecognizers release]; - - [_view release]; - _view = nil; +- (BOOL)wasCancelledInView +{ + return _wasCancelledInView; } -- (void)_setTouchPhaseCancelled +- (void)setWasCancelledInView:(BOOL)wasCancelledInView { - _phase = UITouchPhaseCancelled; + _wasCancelledInView = wasCancelledInView; } -- (CGPoint)_delta +- (NSTimeInterval)beganPhaseTimestamp { - return _delta; + return _beganPhaseTimestamp; } -- (CGFloat)_rotation +- (CGPoint)beganPhaseLocationOnScreen { - return _rotation; + return _beganPhaseLocationOnScreen; } -- (CGFloat)_magnification +- (NSArray *)gestureRecognizers { - return _magnification; + return [_gestureRecognizers copy]; } -- (UIWindow *)window +- (void)_addGestureRecognizer:(UIGestureRecognizer *)gesture { - return _window; + [_gestureRecognizers addObject:gesture]; } -- (CGPoint)_convertLocationPoint:(CGPoint)thePoint toView:(UIView *)inView +- (void)_removeGestureRecognizer:(UIGestureRecognizer *)gesture { - UIWindow *window = self.window; - - // The stored location should always be in the coordinate space of the UIScreen that contains the touch's window. - // So first convert from the screen to the window: - CGPoint point = [window convertPoint:thePoint fromWindow:nil]; - - // Then convert to the desired location (if any). - if (inView) { - point = [inView convertPoint:point fromView:window]; - } - - return point; + [_gestureRecognizers removeObject:gesture]; } - (CGPoint)locationInView:(UIView *)inView { - return [self _convertLocationPoint:_location toView:inView]; + return [self.window convertPoint:[self.window convertPoint:_locationOnScreen fromWindow:nil] toView:inView]; } - (CGPoint)previousLocationInView:(UIView *)inView { - return [self _convertLocationPoint:_previousLocation toView:inView]; + return [self.window convertPoint:[self.window convertPoint:_previousLocationOnScreen fromWindow:nil] toView:inView]; } - (NSString *)description { NSString *phase = @""; + switch (self.phase) { case UITouchPhaseBegan: phase = @"Began"; @@ -236,19 +188,8 @@ - (NSString *)description case UITouchPhaseCancelled: phase = @"Cancelled"; break; - case _UITouchPhaseGestureBegan: - phase = @"GestureBegan"; - break; - case _UITouchPhaseGestureChanged: - phase = @"GestureChanged"; - break; - case _UITouchPhaseGestureEnded: - phase = @"GestureEnded"; - break; - case _UITouchPhaseDiscreteGesture: - phase = @"DiscreteGesture"; - break; } + return [NSString stringWithFormat:@"<%@: %p; timestamp = %e; tapCount = %lu; phase = %@; view = %@; window = %@>", [self className], self, self.timestamp, (unsigned long)self.tapCount, phase, self.view, self.window]; } diff --git a/UIKit/Classes/UIEvent+UIPrivate.h b/UIKit/Classes/UITouchEvent.h similarity index 53% rename from UIKit/Classes/UIEvent+UIPrivate.h rename to UIKit/Classes/UITouchEvent.h index 709bf4a8..70477676 100644 --- a/UIKit/Classes/UIEvent+UIPrivate.h +++ b/UIKit/Classes/UITouchEvent.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, The Iconfactory. All rights reserved. + * Copyright (c) 2013, The Iconfactory. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -29,10 +29,37 @@ #import "UIEvent.h" -@interface UIEvent (UIPrivate) -- (id)initWithEventType:(UIEventType)type; -- (void)_setTouch:(UITouch *)touch; -- (void)_setTimestamp:(NSTimeInterval)timestamp; -- (void)_setUnhandledKeyPressEvent; -- (BOOL)_isUnhandledKeyPressEvent; +@class UITouch; + +typedef NS_ENUM(NSInteger, UITouchEventGesture) { + UITouchEventGestureNone, // a normal click-drag touch (not a standard OSX gesture) + + // handle standard OSX gestures + UITouchEventGestureBegin, // when OSX sends the begin gesture event, but hasn't identified the exact gesture yet + UITouchEventGesturePinch, + UITouchEventGestureRotate, + UITouchEventGesturePan, + + // discrete gestures that violate all the rules + UITouchEventGestureScrollWheel, + UITouchEventGestureRightClick, + UITouchEventGestureMouseMove, + UITouchEventGestureMouseEntered, + UITouchEventGestureMouseExited, + UITouchEventGestureSwipe, +}; + +@interface UITouchEvent : UIEvent +- (id)initWithTouch:(UITouch *)touch; +- (void)endTouchEvent; + +@property (nonatomic, readonly, strong) UITouch *touch; +@property (nonatomic, readwrite, assign) UITouchEventGesture touchEventGesture; // default UITouchEventGestureNone +@property (nonatomic, readonly) BOOL isDiscreteGesture; // YES for the mouse UITouchEventGesture types + +// used for the various OSX gestures +@property (nonatomic, readwrite, assign) CGPoint translation; +@property (nonatomic, readwrite, assign) CGFloat rotation; +@property (nonatomic, readwrite, assign) CGFloat magnification; + @end diff --git a/UIKit/Classes/UIApplication+UIPrivate.h b/UIKit/Classes/UITouchEvent.m similarity index 57% rename from UIKit/Classes/UIApplication+UIPrivate.h rename to UIKit/Classes/UITouchEvent.m index 75a59b6c..bd35d6f6 100644 --- a/UIKit/Classes/UIApplication+UIPrivate.h +++ b/UIKit/Classes/UITouchEvent.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, The Iconfactory. All rights reserved. + * Copyright (c) 2013, The Iconfactory. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -27,20 +27,51 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#import "UIApplication.h" - -@class UIWindow, UIScreen, NSEvent, UIPopoverController; - -@interface UIApplication (UIPrivate) -- (void)_setKeyWindow:(UIWindow *)newKeyWindow; -- (void)_windowDidBecomeVisible:(UIWindow *)theWindow; -- (void)_windowDidBecomeHidden:(UIWindow *)theWindow; -- (BOOL)_sendGlobalKeyboardNSEvent:(NSEvent *)theNSEvent fromScreen:(UIScreen *)theScreen; // checks for CMD-Return/Enter and returns YES if it was handled, NO if not -- (BOOL)_sendKeyboardNSEvent:(NSEvent *)theNSEvent fromScreen:(UIScreen *)theScreen; // returns YES if it was handled within UIKit (first calls _sendGlobalKeyboardNSEvent:fromScreen:) -- (void)_sendMouseNSEvent:(NSEvent *)theNSEvent fromScreen:(UIScreen *)theScreen; -- (void)_cancelTouches; -- (void)_removeViewFromTouches:(UIView *)aView; -- (UIResponder *)_firstResponderForScreen:(UIScreen *)screen; -- (BOOL)_firstResponderCanPerformAction:(SEL)action withSender:(id)sender fromScreen:(UIScreen *)theScreen; -- (BOOL)_sendActionToFirstResponder:(SEL)action withSender:(id)sender fromScreen:(UIScreen *)theScreen; +#import "UITouchEvent.h" +#import "UITouch.h" +#import "UIGestureRecognizer+UIPrivate.h" + +@implementation UITouchEvent + +- (id)initWithTouch:(UITouch *)touch +{ + if ((self=[super init])) { + _touch = touch; + _touchEventGesture = UITouchEventGestureNone; + } + return self; +} + +- (NSTimeInterval)timestamp +{ + return _touch.timestamp; +} + +- (NSSet *)allTouches +{ + return [NSSet setWithObject:_touch]; +} + +- (UIEventType)type +{ + return UIEventTypeTouches; +} + +- (BOOL)isDiscreteGesture +{ + return (_touchEventGesture == UITouchEventGestureScrollWheel || + _touchEventGesture == UITouchEventGestureRightClick || + _touchEventGesture == UITouchEventGestureMouseMove || + _touchEventGesture == UITouchEventGestureMouseEntered || + _touchEventGesture == UITouchEventGestureMouseExited || + _touchEventGesture == UITouchEventGestureSwipe); +} + +- (void)endTouchEvent +{ + for (UIGestureRecognizer *gesture in _touch.gestureRecognizers) { + [gesture _endTrackingTouch:_touch withEvent:self]; + } +} + @end diff --git a/UIKit/Classes/UITransitionView.h b/UIKit/Classes/UITransitionView.h deleted file mode 100644 index 50e86d71..00000000 --- a/UIKit/Classes/UITransitionView.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2011, The Iconfactory. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of The Iconfactory nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE ICONFACTORY BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import "UIView.h" - -typedef enum { - UITransitionNone = 0, // no animation is done - UITransitionFromLeft, // the new view slides in from the left over top of the old view - UITransitionFromRight, // the new view slides in from the right over top of the old view - UITransitionFromTop, // the new view slides in from the top over top of the old view - UITransitionFromBottom, // the new view slides in from the bottom over top of the old view - UITransitionPushLeft, // the new view slides in from the right and pushes the old view off the left - UITransitionPushRight, // the new view slides in from the left and pushes the old view off the right - UITransitionPushUp, // the new view slides in from the bottom and pushes the old view off the top - UITransitionPushDown, // the new view slides in from the top and pushes the old view off the bottom - UITransitionCrossFade, // new view fades in as old view fades out - UITransitionFadeIn, // new view fades in over old view - UITransitionFadeOut // old view fades out to reveal the new view behind it -} UITransition; - -@class UITransitionView; - -@protocol UITransitionViewDelegate -- (void)transitionView:(UITransitionView *)transitionView didTransitionFromView:(UIView *)fromView toView:(UIView *)toView withTransition:(UITransition)transition; -@end - -@interface UITransitionView : UIView { - UITransition _transition; - UIView *_view; - __unsafe_unretained id _delegate; -} - -- (id)initWithFrame:(CGRect)frame view:(UIView *)aView; - -@property (nonatomic, retain) UIView *view; -@property (nonatomic, assign) UITransition transition; -@property (nonatomic, assign) id delegate; - -@end diff --git a/UIKit/Classes/UITransitionView.m b/UIKit/Classes/UITransitionView.m deleted file mode 100644 index 3308b532..00000000 --- a/UIKit/Classes/UITransitionView.m +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) 2011, The Iconfactory. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of The Iconfactory nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE ICONFACTORY BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import "UITransitionView.h" - -@implementation UITransitionView -@synthesize view=_view, transition=_transition, delegate=_delegate; - -- (id)initWithFrame:(CGRect)frame view:(UIView *)aView -{ - if ((self=[super initWithFrame:frame])) { - self.view = aView; - } - return self; -} - -- (void)dealloc -{ - [_view release]; - [super dealloc]; -} - -- (void)setFrame:(CGRect)frame -{ - [super setFrame:frame]; - _view.frame = self.bounds; -} - -- (CGRect)_rectForIncomingView -{ - switch (_transition) { - case UITransitionPushRight: - case UITransitionFromLeft: return CGRectOffset(self.bounds,-self.bounds.size.width,0); - case UITransitionPushLeft: - case UITransitionFromRight: return CGRectOffset(self.bounds,self.bounds.size.width,0); - case UITransitionPushDown: - case UITransitionFromTop: return CGRectOffset(self.bounds,0,-self.bounds.size.height); - case UITransitionPushUp: - case UITransitionFromBottom: return CGRectOffset(self.bounds,0,self.bounds.size.height); - default: return self.bounds; - } -} - -- (CGRect)_rectForOutgoingView -{ - switch (_transition) { - case UITransitionPushLeft: return CGRectOffset(self.bounds,-self.bounds.size.width,0); - case UITransitionPushRight: return CGRectOffset(self.bounds,self.bounds.size.width,0); - case UITransitionPushDown: return CGRectOffset(self.bounds,0,self.bounds.size.height); - case UITransitionPushUp: return CGRectOffset(self.bounds,0,-self.bounds.size.height); - default: return self.bounds; - } -} - -- (void)_finishTransition:(NSDictionary *)info -{ - UIView *fromView = [info objectForKey:@"fromView"]; - UIView *toView = [info objectForKey:@"toView"]; - UITransition transition = [[info objectForKey:@"transition"] intValue]; - - [fromView removeFromSuperview]; - - [_delegate transitionView:self didTransitionFromView:fromView toView:toView withTransition:transition]; -} - -- (void)setView:(UIView *)aView -{ - if (aView != _view) { - aView.frame = [self _rectForIncomingView]; - [self addSubview:aView]; - - NSDictionary *info = [NSDictionary dictionaryWithObjectsAndKeys: - _view, @"fromView", - aView, @"toView", - [NSNumber numberWithInt:_transition], @"transition", - nil]; - - if (_transition == UITransitionNone) { - [self _finishTransition:info]; - } else { - if (_transition == UITransitionFadeOut) { - [self sendSubviewToBack:aView]; - } else if (_transition == UITransitionFadeIn) { - aView.alpha = 0; - } - - [UIView animateWithDuration:0.33 - animations:^(void) { - _view.frame = [self _rectForOutgoingView]; - aView.frame = self.bounds; - - if (_transition == UITransitionFadeOut || _transition == UITransitionCrossFade) { - _view.alpha = 0; - } - - if (_transition == UITransitionFadeIn || _transition == UITransitionCrossFade) { - aView.alpha = 1; - } - } - completion:^(BOOL finished) { - [self _finishTransition:info]; - }]; - } - - [_view release]; - _view = [aView retain]; - } -} - -@end diff --git a/UIKit/Classes/UIView.h b/UIKit/Classes/UIView.h index 655518bc..13b194e9 100644 --- a/UIKit/Classes/UIView.h +++ b/UIKit/Classes/UIView.h @@ -31,7 +31,7 @@ #import "UIGeometry.h" #import "UIAppearance.h" -enum { +typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) { UIViewAutoresizingNone = 0, UIViewAutoresizingFlexibleLeftMargin = 1 << 0, UIViewAutoresizingFlexibleWidth = 1 << 1, @@ -40,9 +40,8 @@ enum { UIViewAutoresizingFlexibleHeight = 1 << 4, UIViewAutoresizingFlexibleBottomMargin = 1 << 5 }; -typedef NSUInteger UIViewAutoresizing; -typedef enum { +typedef NS_ENUM(NSInteger, UIViewContentMode) { UIViewContentModeScaleToFill, UIViewContentModeScaleAspectFit, UIViewContentModeScaleAspectFill, @@ -56,24 +55,24 @@ typedef enum { UIViewContentModeTopRight, UIViewContentModeBottomLeft, UIViewContentModeBottomRight, -} UIViewContentMode; +}; -typedef enum { +typedef NS_ENUM(NSInteger, UIViewAnimationCurve) { UIViewAnimationCurveEaseInOut, UIViewAnimationCurveEaseIn, UIViewAnimationCurveEaseOut, UIViewAnimationCurveLinear -} UIViewAnimationCurve; +}; -typedef enum { +typedef NS_ENUM(NSInteger, UIViewAnimationTransition) { UIViewAnimationTransitionNone, UIViewAnimationTransitionFlipFromLeft, UIViewAnimationTransitionFlipFromRight, UIViewAnimationTransitionCurlUp, UIViewAnimationTransitionCurlDown, -} UIViewAnimationTransition; +}; -enum { +typedef NS_OPTIONS(NSUInteger, UIViewAnimationOptions) { UIViewAnimationOptionLayoutSubviews = 1 << 0, // not currently supported UIViewAnimationOptionAllowUserInteraction = 1 << 1, UIViewAnimationOptionBeginFromCurrentState = 1 << 2, @@ -82,46 +81,26 @@ enum { UIViewAnimationOptionOverrideInheritedDuration = 1 << 5, // not currently supported UIViewAnimationOptionOverrideInheritedCurve = 1 << 6, // not currently supported UIViewAnimationOptionAllowAnimatedContent = 1 << 7, // not currently supported - UIViewAnimationOptionShowHideTransitionViews = 1 << 8, // not currently supported + UIViewAnimationOptionShowHideTransitionViews = 1 << 8, UIViewAnimationOptionCurveEaseInOut = 0 << 16, UIViewAnimationOptionCurveEaseIn = 1 << 16, UIViewAnimationOptionCurveEaseOut = 2 << 16, UIViewAnimationOptionCurveLinear = 3 << 16, - UIViewAnimationOptionTransitionNone = 0 << 20, // not currently supported - UIViewAnimationOptionTransitionFlipFromLeft = 1 << 20, // not currently supported - UIViewAnimationOptionTransitionFlipFromRight = 2 << 20, // not currently supported - UIViewAnimationOptionTransitionCurlUp = 3 << 20, // not currently supported - UIViewAnimationOptionTransitionCurlDown = 4 << 20, // not currently supported - UIViewAnimationOptionTransitionCrossDissolve = 5 << 20, // not currently supported - UIViewAnimationOptionTransitionFlipFromTop = 6 << 20, // not currently supported - UIViewAnimationOptionTransitionFlipFromBottom = 7 << 20, // not currently supported + UIViewAnimationOptionTransitionNone = 0 << 20, + UIViewAnimationOptionTransitionFlipFromLeft = 1 << 20, + UIViewAnimationOptionTransitionFlipFromRight = 2 << 20, + UIViewAnimationOptionTransitionCurlUp = 3 << 20, + UIViewAnimationOptionTransitionCurlDown = 4 << 20, + UIViewAnimationOptionTransitionCrossDissolve = 5 << 20, + UIViewAnimationOptionTransitionFlipFromTop = 6 << 20, + UIViewAnimationOptionTransitionFlipFromBottom = 7 << 20, }; -typedef NSUInteger UIViewAnimationOptions; @class UIColor, CALayer, UIViewController, UIGestureRecognizer; -@interface UIView : UIResponder { -@private - UIView *_superview; - NSMutableSet *_subviews; - BOOL _clearsContextBeforeDrawing; - BOOL _autoresizesSubviews; - BOOL _userInteractionEnabled; - CALayer *_layer; - NSInteger _tag; - UIViewContentMode _contentMode; - UIColor *_backgroundColor; - BOOL _implementsDrawRect; - BOOL _multipleTouchEnabled; - BOOL _exclusiveTouch; - UIViewController *_viewController; - UIViewAutoresizing _autoresizingMask; - BOOL _needsDidAppearOrDisappear; - NSMutableSet *_gestureRecognizers; -} - +@interface UIView : UIResponder + (Class)layerClass; - (id)initWithFrame:(CGRect)frame; @@ -163,7 +142,6 @@ typedef NSUInteger UIViewAnimationOptions; + (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion; + (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations; -// the block-based transition methods are not currently implemented + (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion; + (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^)(BOOL finished))completion; @@ -205,6 +183,5 @@ typedef NSUInteger UIViewAnimationOptions; @property (nonatomic) CGFloat contentScaleFactor; @property (nonatomic, getter=isMultipleTouchEnabled) BOOL multipleTouchEnabled; // state is maintained, but it has no effect @property (nonatomic, getter=isExclusiveTouch) BOOL exclusiveTouch; // state is maintained, but it has no effect -@property (nonatomic,copy) NSArray *gestureRecognizers; - +@property (nonatomic, copy) NSArray *gestureRecognizers; @end diff --git a/UIKit/Classes/UIView.m b/UIKit/Classes/UIView.m index ecdc0d27..8e2fb72b 100644 --- a/UIKit/Classes/UIView.m +++ b/UIKit/Classes/UIView.m @@ -30,14 +30,12 @@ #import "UIView+UIPrivate.h" #import "UIWindow.h" #import "UIGraphics.h" -#import "UIColor.h" #import "UIViewLayoutManager.h" #import "UIViewAnimationGroup.h" -#import "UIViewBlockAnimationDelegate.h" #import "UIViewController.h" #import "UIAppearanceInstance.h" -#import "UIApplication+UIPrivate.h" #import "UIGestureRecognizer+UIPrivate.h" +#import "UIApplicationAppKitIntegration.h" #import "UIScreen.h" #import "UIColor+UIPrivate.h" #import "UIColorRep.h" @@ -51,10 +49,13 @@ static NSMutableArray *_animationGroups; static BOOL _animationsEnabled = YES; -@implementation UIView -@synthesize layer=_layer, superview=_superview, clearsContextBeforeDrawing=_clearsContextBeforeDrawing, autoresizesSubviews=_autoresizesSubviews; -@synthesize tag=_tag, userInteractionEnabled=_userInteractionEnabled, contentMode=_contentMode, backgroundColor=_backgroundColor; -@synthesize multipleTouchEnabled=_multipleTouchEnabled, exclusiveTouch=_exclusiveTouch, autoresizingMask=_autoresizingMask; +@implementation UIView { + __unsafe_unretained UIView *_superview; + __unsafe_unretained UIViewController *_viewController; + NSMutableSet *_subviews; + BOOL _implementsDrawRect; + NSMutableSet *_gestureRecognizers; +} + (void)initialize { @@ -81,14 +82,14 @@ - (id)init - (id)initWithFrame:(CGRect)theFrame { if ((self=[super init])) { - _implementsDrawRect = [isa _instanceImplementsDrawRect]; + _implementsDrawRect = [[self class] _instanceImplementsDrawRect]; _clearsContextBeforeDrawing = YES; _autoresizesSubviews = YES; _userInteractionEnabled = YES; _subviews = [[NSMutableSet alloc] init]; _gestureRecognizers = [[NSMutableSet alloc] init]; - _layer = [[[isa layerClass] alloc] init]; + _layer = [[[[self class] layerClass] alloc] init]; _layer.delegate = self; _layer.layoutManager = [UIViewLayoutManager layoutManager]; @@ -104,18 +105,12 @@ - (id)initWithFrame:(CGRect)theFrame - (void)dealloc { - [[_subviews allObjects] makeObjectsPerformSelector:@selector(removeFromSuperview)]; + [_gestureRecognizers makeObjectsPerformSelector:@selector(_setView:) withObject:nil]; + [[_subviews allObjects] makeObjectsPerformSelector:@selector(_removeFromDeallocatedSuperview)]; _layer.layoutManager = nil; _layer.delegate = nil; [_layer removeFromSuperlayer]; - - [_subviews release]; - [_layer release]; - [_backgroundColor release]; - [_gestureRecognizers release]; - - [super dealloc]; } - (void)_setViewController:(UIViewController *)theViewController @@ -138,7 +133,7 @@ - (UIResponder *)nextResponder return (UIResponder *)[self _viewController] ?: (UIResponder *)_superview; } -- (id)_appearanceContainer +- (id)_UIAppearanceContainer { return self.superview; } @@ -172,12 +167,14 @@ - (void)_willMoveFromWindow:(UIWindow *)fromWindow toWindow:(UIWindow *)toWindow [self resignFirstResponder]; } - [self _setAppearanceNeedsUpdate]; + [self _UIAppearanceSetNeedsUpdate]; [self willMoveToWindow:toWindow]; for (UIView *subview in self.subviews) { [subview _willMoveFromWindow:fromWindow toWindow:toWindow]; } + + [[self _viewController] beginAppearanceTransition:(toWindow != nil) animated:NO]; } } @@ -202,22 +199,30 @@ - (void)_didMoveFromWindow:(UIWindow *)fromWindow toWindow:(UIWindow *)toWindow for (UIView *subview in self.subviews) { [subview _didMoveFromWindow:fromWindow toWindow:toWindow]; } - } -} - -- (BOOL)_subviewControllersNeedAppearAndDisappear -{ - UIView *view = self; - - while (view) { - if ([view _viewController] != nil) { - return NO; - } else { - view = [view superview]; + + UIViewController *controller = [self _viewController]; + + if (controller) { + if ([[self class] _isAnimating]) { + void (^completionBlock)(BOOL) = [[self class] _animationCompletionBlock]; + + [[self class] _setAnimationCompletionBlock:^(BOOL finished) { + [controller endAppearanceTransition]; + + if (completionBlock) { + completionBlock(finished); + } + }]; + } else { + // this is sort of strange, but testing against iOS 6 seems to indicate that appearance transitions + // that don't occur within an animation block still do something like this.. it waits until the runloop + // cycles before really finishing. I can think of some good reasons for this behavior, so I think it + // makes sense to try to replicate it, but I know the real thing doesn't do it like this... :/ + // (although to be fair, the real thing doesn't do anything much like I'm doing it, so...) + [controller performSelector:@selector(endAppearanceTransition) withObject:nil afterDelay:0]; + } } } - - return YES; } - (void)addSubview:(UIView *)subview @@ -228,31 +233,19 @@ - (void)addSubview:(UIView *)subview UIWindow *oldWindow = subview.window; UIWindow *newWindow = self.window; - subview->_needsDidAppearOrDisappear = [self _subviewControllersNeedAppearAndDisappear]; - - if ([subview _viewController] && subview->_needsDidAppearOrDisappear) { - [[subview _viewController] viewWillAppear:NO]; - } - [subview _willMoveFromWindow:oldWindow toWindow:newWindow]; [subview willMoveToSuperview:self]; - { - [subview retain]; - - if (subview.superview) { - [subview.layer removeFromSuperlayer]; - [subview.superview->_subviews removeObject:subview]; - } - - [subview willChangeValueForKey:@"superview"]; - [_subviews addObject:subview]; - subview->_superview = self; - [_layer addSublayer:subview.layer]; - [subview didChangeValueForKey:@"superview"]; - - [subview release]; + if (subview.superview) { + [subview.layer removeFromSuperlayer]; + [subview.superview->_subviews removeObject:subview]; } + + [subview willChangeValueForKey:@"superview"]; + [_subviews addObject:subview]; + subview->_superview = self; + [_layer addSublayer:subview.layer]; + [subview didChangeValueForKey:@"superview"]; if (oldWindow.screen != newWindow.screen) { [subview _didMoveToScreen]; @@ -264,10 +257,6 @@ - (void)addSubview:(UIView *)subview [[NSNotificationCenter defaultCenter] postNotificationName:UIViewDidMoveToSuperviewNotification object:subview]; [self didAddSubview:subview]; - - if ([subview _viewController] && subview->_needsDidAppearOrDisappear) { - [[subview _viewController] viewDidAppear:NO]; - } } } @@ -303,19 +292,24 @@ - (void)sendSubviewToBack:(UIView *)subview } } +- (void)_abortGestureRecognizers +{ + // note - the real UIKit supports multitouch so it only really interruptes the current touch + // and not all of them, but this is easier for now since we don't support that anyway. + UIApplicationInterruptTouchesInView(self); +} + +- (void)_removeFromDeallocatedSuperview +{ + _superview = nil; + [self _abortGestureRecognizers]; +} + - (void)removeFromSuperview { if (_superview) { - [self retain]; - - [[UIApplication sharedApplication] _removeViewFromTouches:self]; - UIWindow *oldWindow = self.window; - - if (_needsDidAppearOrDisappear && [self _viewController]) { - [[self _viewController] viewWillDisappear:NO]; - } - + [_superview willRemoveSubview:self]; [self _willMoveFromWindow:oldWindow toWindow:nil]; [self willMoveToSuperview:nil]; @@ -325,16 +319,13 @@ - (void)removeFromSuperview [_superview->_subviews removeObject:self]; _superview = nil; [self didChangeValueForKey:@"superview"]; - + + [self _abortGestureRecognizers]; + + [[NSNotificationCenter defaultCenter] postNotificationName:UIViewDidMoveToSuperviewNotification object:self]; + [self _didMoveFromWindow:oldWindow toWindow:nil]; [self didMoveToSuperview]; - [[NSNotificationCenter defaultCenter] postNotificationName:UIViewDidMoveToSuperviewNotification object:self]; - - if (_needsDidAppearOrDisappear && [self _viewController]) { - [[self _viewController] viewDidDisappear:NO]; - } - - [self release]; } } @@ -763,9 +754,9 @@ - (void)setOpaque:(BOOL)newO - (void)setBackgroundColor:(UIColor *)newColor { if (_backgroundColor != newColor) { - [_backgroundColor release]; - _backgroundColor = [newColor retain]; + _backgroundColor = newColor; self.opaque = [_backgroundColor _isOpaque]; + [self setNeedsDisplay]; } } @@ -841,10 +832,13 @@ - (void)layoutSubviews - (void)_layoutSubviews { - [self _updateAppearanceIfNeeded]; + const BOOL wereEnabled = [UIView areAnimationsEnabled]; + [UIView setAnimationsEnabled:NO]; + [self _UIAppearanceUpdateIfNeeded]; [[self _viewController] viewWillLayoutSubviews]; [self layoutSubviews]; [[self _viewController] viewDidLayoutSubviews]; + [UIView setAnimationsEnabled:wereEnabled]; } - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event @@ -852,9 +846,24 @@ - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event return CGRectContainsPoint(self.bounds, point); } +- (BOOL)_isAnimatedUserInteractionEnabled +{ + for (UIViewAnimationGroup *group in _animationGroups) { + if (!group.allowUserInteraction) { + for (UIView *animatingView in group.allAnimatingViews) { + if ([self isDescendantOfView:animatingView]) { + return NO; + } + } + } + } + + return YES; +} + - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { - if (self.hidden || !self.userInteractionEnabled || self.alpha < 0.01 || ![self pointInside:point withEvent:event]) { + if (self.hidden || !self.userInteractionEnabled || self.alpha < 0.01 || ![self pointInside:point withEvent:event] || ![self _isAnimatedUserInteractionEnabled]) { return nil; } else { for (UIView *subview in [self.subviews reverseObjectEnumerator]) { @@ -972,54 +981,54 @@ - (NSArray *)gestureRecognizers return [_gestureRecognizers allObjects]; } ++ (void)_beginAnimationsWithOptions:(UIViewAnimationOptions)options +{ + [_animationGroups addObject:[[UIViewAnimationGroup alloc] initWithAnimationOptions:options]]; +} + ++ (void)_setAnimationName:(NSString *)name context:(void *)context +{ + [[_animationGroups lastObject] setName:name]; + [[_animationGroups lastObject] setContext:context]; +} + ++ (void)_setAnimationCompletionBlock:(void (^)(BOOL finished))completion +{ + [(UIViewAnimationGroup *)[_animationGroups lastObject] setCompletionBlock:completion]; +} + ++ (void (^)(BOOL))_animationCompletionBlock +{ + return [(UIViewAnimationGroup *)[_animationGroups lastObject] completionBlock]; +} + ++ (void)_setAnimationTransitionView:(UIView *)view +{ + [[_animationGroups lastObject] setTransitionView:view shouldCache:NO]; +} + ++ (BOOL)_isAnimating +{ + return ([_animationGroups count] != 0); +} + + (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion { - const BOOL ignoreInteractionEvents = !((options & UIViewAnimationOptionAllowUserInteraction) == UIViewAnimationOptionAllowUserInteraction); - const BOOL repeatAnimation = ((options & UIViewAnimationOptionRepeat) == UIViewAnimationOptionRepeat); - const BOOL autoreverseRepeat = ((options & UIViewAnimationOptionAutoreverse) == UIViewAnimationOptionAutoreverse); - const BOOL beginFromCurrentState = ((options & UIViewAnimationOptionBeginFromCurrentState) == UIViewAnimationOptionBeginFromCurrentState); - UIViewAnimationCurve animationCurve; - - if ((options & UIViewAnimationOptionCurveEaseInOut) == UIViewAnimationOptionCurveEaseInOut) { - animationCurve = UIViewAnimationCurveEaseInOut; - } else if ((options & UIViewAnimationOptionCurveEaseIn) == UIViewAnimationOptionCurveEaseIn) { - animationCurve = UIViewAnimationCurveEaseIn; - } else if ((options & UIViewAnimationOptionCurveEaseOut) == UIViewAnimationOptionCurveEaseOut) { - animationCurve = UIViewAnimationCurveEaseOut; - } else { - animationCurve = UIViewAnimationCurveLinear; - } - - // NOTE: As of iOS 5 this is only supposed to block interaction events for the views being animated, not the whole app. - if (ignoreInteractionEvents) { - [[UIApplication sharedApplication] beginIgnoringInteractionEvents]; - } - - UIViewBlockAnimationDelegate *delegate = [[UIViewBlockAnimationDelegate alloc] init]; - delegate.completion = completion; - delegate.ignoreInteractionEvents = ignoreInteractionEvents; - - [UIView beginAnimations:nil context:NULL]; - [UIView setAnimationCurve:animationCurve]; - [UIView setAnimationDelay:delay]; - [UIView setAnimationDuration:duration]; - [UIView setAnimationBeginsFromCurrentState:beginFromCurrentState]; - [UIView setAnimationDelegate:delegate]; // this is retained here - [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:)]; - [UIView setAnimationRepeatCount:(repeatAnimation? FLT_MAX : 0)]; - [UIView setAnimationRepeatAutoreverses:autoreverseRepeat]; + [self _beginAnimationsWithOptions:options | UIViewAnimationOptionTransitionNone]; + [self setAnimationDuration:duration]; + [self setAnimationDelay:delay]; + [self _setAnimationCompletionBlock:completion]; animations(); - [UIView commitAnimations]; - [delegate release]; + [self commitAnimations]; } + (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion { [self animateWithDuration:duration delay:0 - options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionTransitionNone + options:UIViewAnimationOptionCurveEaseInOut animations:animations completion:completion]; } @@ -1029,17 +1038,41 @@ + (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void)) [self animateWithDuration:duration animations:animations completion:NULL]; } -+ (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completio ++ (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion { + [self _beginAnimationsWithOptions:options]; + [self setAnimationDuration:duration]; + [self _setAnimationCompletionBlock:completion]; + [self _setAnimationTransitionView:view]; + + if (animations) { + animations(); + } + + [self commitAnimations]; } + (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^)(BOOL finished))completion { + [self transitionWithView:fromView.superview + duration:duration + options:options + animations:^{ + if (UIViewAnimationOptionIsSet(options, UIViewAnimationOptionShowHideTransitionViews)) { + fromView.hidden = YES; + toView.hidden = NO; + } else { + [fromView.superview addSubview:toView]; + [fromView removeFromSuperview]; + } + } + completion:completion]; } + (void)beginAnimations:(NSString *)animationID context:(void *)context { - [_animationGroups addObject:[UIViewAnimationGroup animationGroupWithName:animationID context:context]]; + [self _beginAnimationsWithOptions:UIViewAnimationCurveEaseInOut]; + [self _setAnimationName:animationID context:context]; } + (void)commitAnimations @@ -1052,52 +1085,74 @@ + (void)commitAnimations + (void)setAnimationBeginsFromCurrentState:(BOOL)beginFromCurrentState { - [[_animationGroups lastObject] setAnimationBeginsFromCurrentState:beginFromCurrentState]; + [[_animationGroups lastObject] setBeginsFromCurrentState:beginFromCurrentState]; } + (void)setAnimationCurve:(UIViewAnimationCurve)curve { - [[_animationGroups lastObject] setAnimationCurve:curve]; + [[_animationGroups lastObject] setCurve:curve]; } + (void)setAnimationDelay:(NSTimeInterval)delay { - [[_animationGroups lastObject] setAnimationDelay:delay]; + [[_animationGroups lastObject] setDelay:delay]; } + (void)setAnimationDelegate:(id)delegate { - [[_animationGroups lastObject] setAnimationDelegate:delegate]; + [[_animationGroups lastObject] setDelegate:delegate]; } + (void)setAnimationDidStopSelector:(SEL)selector { - [[_animationGroups lastObject] setAnimationDidStopSelector:selector]; + [[_animationGroups lastObject] setDidStopSelector:selector]; } + (void)setAnimationDuration:(NSTimeInterval)duration { - [[_animationGroups lastObject] setAnimationDuration:duration]; + [[_animationGroups lastObject] setDuration:duration]; } + (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses { - [[_animationGroups lastObject] setAnimationRepeatAutoreverses:repeatAutoreverses]; + [[_animationGroups lastObject] setRepeatAutoreverses:repeatAutoreverses]; } + (void)setAnimationRepeatCount:(float)repeatCount { - [[_animationGroups lastObject] setAnimationRepeatCount:repeatCount]; + [[_animationGroups lastObject] setRepeatCount:repeatCount]; } + (void)setAnimationWillStartSelector:(SEL)selector { - [[_animationGroups lastObject] setAnimationWillStartSelector:selector]; + [[_animationGroups lastObject] setWillStartSelector:selector]; } + (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache { - [[_animationGroups lastObject] setAnimationTransition:transition forView:view cache:cache]; + [self _setAnimationTransitionView:view]; + + switch (transition) { + case UIViewAnimationTransitionNone: + [[_animationGroups lastObject] setTransition:UIViewAnimationGroupTransitionNone]; + break; + + case UIViewAnimationTransitionFlipFromLeft: + [[_animationGroups lastObject] setTransition:UIViewAnimationGroupTransitionFlipFromLeft]; + break; + + case UIViewAnimationTransitionFlipFromRight: + [[_animationGroups lastObject] setTransition:UIViewAnimationGroupTransitionFlipFromRight]; + break; + + case UIViewAnimationTransitionCurlUp: + [[_animationGroups lastObject] setTransition:UIViewAnimationGroupTransitionCurlUp]; + break; + + case UIViewAnimationTransitionCurlDown: + [[_animationGroups lastObject] setTransition:UIViewAnimationGroupTransitionCurlDown]; + break; + } } + (BOOL)areAnimationsEnabled diff --git a/UIKit/Classes/UIViewAdapter.h b/UIKit/Classes/UIViewAdapter.h index 881dfa23..0a3c9c0f 100644 --- a/UIKit/Classes/UIViewAdapter.h +++ b/UIKit/Classes/UIViewAdapter.h @@ -31,14 +31,7 @@ @class NSView, UINSClipView; -@interface UIViewAdapter : UIScrollView { -@private - UINSClipView *_clipView; - NSView *_view; -} - +@interface UIViewAdapter : UIScrollView - (id)initWithNSView:(NSView *)aNSView; - -@property (nonatomic, retain) NSView *NSView; - +@property (nonatomic, strong) NSView *NSView; @end diff --git a/UIKit/Classes/UIViewAdapter.m b/UIKit/Classes/UIViewAdapter.m index 6e05ce87..9525b1b6 100644 --- a/UIKit/Classes/UIViewAdapter.m +++ b/UIKit/Classes/UIViewAdapter.m @@ -42,7 +42,9 @@ #import -@implementation UIViewAdapter +@implementation UIViewAdapter { + UINSClipView *_clipView; +} @synthesize NSView=_view; #pragma mark - @@ -71,9 +73,6 @@ - (id)initWithNSView:(NSView *)aNSView - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self name:UIViewHiddenDidChangeNotification object:nil]; - [_view release]; - [_clipView release]; - [super dealloc]; } #pragma mark - @@ -83,7 +82,7 @@ - (void)_addNSView { [_clipView scrollToPoint:NSPointFromCGPoint(self.contentOffset)]; - [[self.window.screen UIKitView] addSubview:_clipView]; + [self.window.screen.UIKitView addSubview:_clipView]; // all of these notifications are hacks to detect when views or superviews of this view move or change in ways that require // the actual NSView to get updated. it's not pretty, but I cannot come up with a better way at this point. @@ -106,15 +105,11 @@ - (void)_removeNSView - (void)_updateLayers { [CATransaction begin]; - [CATransaction setValue:(id)kCFBooleanTrue - forKey:kCATransactionDisableActions]; + [CATransaction setAnimationDuration:0]; CALayer *layer = self.layer; CALayer *clipLayer = [_clipView layer]; - // setting these here because I've had bad experiences with NSView changing some layer properties out from under me. - clipLayer.geometryFlipped = YES; - // always make sure it's at the very bottom [layer insertSublayer:clipLayer atIndex:0]; @@ -160,7 +155,7 @@ - (BOOL)_NSViewShouldBeVisible - (void)_updateNSViews { if ([self _NSViewShouldBeVisible]) { - if ([_clipView superview] != [self.window.screen UIKitView]) { + if ([_clipView superview] != self.window.screen.UIKitView) { [self _addNSView]; } @@ -209,8 +204,7 @@ - (void)setNSView:(NSView *)aNSView [self resignFirstResponder]; [self _removeNSView]; - [_view release]; - _view = [aNSView retain]; + _view = aNSView; [_clipView setDocumentView:_view]; [self _updateNSViews]; @@ -257,7 +251,7 @@ - (BOOL)resignFirstResponder const BOOL didResign = [super resignFirstResponder]; if (didResign && [[_view window] firstResponder] == _view) { - [[_view window] makeFirstResponder:[self.window.screen UIKitView]]; + [[_view window] makeFirstResponder:self.window.screen.UIKitView]; } return didResign; diff --git a/UIKit/Classes/UIViewAnimationGroup.h b/UIKit/Classes/UIViewAnimationGroup.h index b9516498..856260db 100644 --- a/UIKit/Classes/UIViewAnimationGroup.h +++ b/UIKit/Classes/UIViewAnimationGroup.h @@ -29,42 +29,42 @@ #import "UIView.h" -@interface UIViewAnimationGroup : NSObject { -@private - NSString *_name; - void *_context; - NSUInteger _waitingAnimations; - BOOL _didSendStartMessage; - NSTimeInterval _animationDelay; - NSTimeInterval _animationDuration; - UIViewAnimationCurve _animationCurve; - id _animationDelegate; - SEL _animationDidStopSelector; - SEL _animationWillStartSelector; - BOOL _animationBeginsFromCurrentState; - BOOL _animationRepeatAutoreverses; - float _animationRepeatCount; - CFTimeInterval _animationBeginTime; - CALayer *_transitionLayer; - UIViewAnimationTransition _transitionType; - BOOL _transitionShouldCache; - NSMutableSet *_animatingViews; -} +typedef NS_ENUM(NSInteger, UIViewAnimationGroupTransition) { + UIViewAnimationGroupTransitionNone, + UIViewAnimationGroupTransitionFlipFromLeft, + UIViewAnimationGroupTransitionFlipFromRight, + UIViewAnimationGroupTransitionCurlUp, + UIViewAnimationGroupTransitionCurlDown, + UIViewAnimationGroupTransitionFlipFromTop, + UIViewAnimationGroupTransitionFlipFromBottom, + UIViewAnimationGroupTransitionCrossDissolve, +}; -+ (id)animationGroupWithName:(NSString *)theName context:(void *)theContext; +extern BOOL UIViewAnimationOptionIsSet(UIViewAnimationOptions options, UIViewAnimationOptions option); + +@interface UIViewAnimationGroup : NSObject + +- (id)initWithAnimationOptions:(UIViewAnimationOptions)options; - (id)actionForView:(UIView *)view forKey:(NSString *)keyPath; +- (void)setTransitionView:(UIView *)view shouldCache:(BOOL)cache; + +- (NSArray *)allAnimatingViews; -- (void)setAnimationBeginsFromCurrentState:(BOOL)beginFromCurrentState; -- (void)setAnimationCurve:(UIViewAnimationCurve)curve; -- (void)setAnimationDelay:(NSTimeInterval)delay; -- (void)setAnimationDelegate:(id)delegate; // retained! (also true of the real UIKit) -- (void)setAnimationDidStopSelector:(SEL)selector; -- (void)setAnimationDuration:(NSTimeInterval)duration; -- (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses; -- (void)setAnimationRepeatCount:(float)repeatCount; -- (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache; -- (void)setAnimationWillStartSelector:(SEL)selector; +@property (nonatomic, copy) NSString *name; +@property (nonatomic, assign) void *context; +@property (nonatomic, copy) void (^completionBlock)(BOOL finished); +@property (nonatomic, assign) BOOL allowUserInteraction; +@property (nonatomic, assign) BOOL beginsFromCurrentState; +@property (nonatomic, assign) UIViewAnimationCurve curve; +@property (nonatomic, assign) NSTimeInterval delay; +@property (nonatomic, strong) id delegate; +@property (nonatomic, assign) SEL didStopSelector; +@property (nonatomic, assign) SEL willStartSelector; +@property (nonatomic, assign) NSTimeInterval duration; +@property (nonatomic, assign) BOOL repeatAutoreverses; +@property (nonatomic, assign) float repeatCount; +@property (nonatomic, assign) UIViewAnimationGroupTransition transition; - (void)commit; diff --git a/UIKit/Classes/UIViewAnimationGroup.m b/UIKit/Classes/UIViewAnimationGroup.m index 01765233..0e1664b5 100644 --- a/UIKit/Classes/UIViewAnimationGroup.m +++ b/UIKit/Classes/UIViewAnimationGroup.m @@ -30,8 +30,11 @@ #import "UIViewAnimationGroup.h" #import #import "UIColor.h" +#import "UIApplication.h" -static CAMediaTimingFunction *CAMediaTimingFunctionFromUIViewAnimationCurve(UIViewAnimationCurve curve) +static NSMutableSet *runningAnimationGroups = nil; + +static inline CAMediaTimingFunction *CAMediaTimingFunctionFromUIViewAnimationCurve(UIViewAnimationCurve curve) { switch (curve) { case UIViewAnimationCurveEaseInOut: return [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; @@ -42,106 +45,161 @@ return nil; } -@implementation UIViewAnimationGroup +BOOL UIViewAnimationOptionIsSet(UIViewAnimationOptions options, UIViewAnimationOptions option) +{ + return ((options & option) == option); +} + +static inline UIViewAnimationOptions UIViewAnimationOptionCurve(UIViewAnimationOptions options) +{ + return (options & (UIViewAnimationOptionCurveEaseInOut + | UIViewAnimationOptionCurveEaseIn + | UIViewAnimationOptionCurveEaseOut + | UIViewAnimationOptionCurveLinear)); +} + +static inline UIViewAnimationOptions UIViewAnimationOptionTransition(UIViewAnimationOptions options) +{ + return (options & (UIViewAnimationOptionTransitionNone + | UIViewAnimationOptionTransitionFlipFromLeft + | UIViewAnimationOptionTransitionFlipFromRight + | UIViewAnimationOptionTransitionCurlUp + | UIViewAnimationOptionTransitionCurlDown + | UIViewAnimationOptionTransitionCrossDissolve + | UIViewAnimationOptionTransitionFlipFromTop + | UIViewAnimationOptionTransitionFlipFromBottom)); +} + +@implementation UIViewAnimationGroup { + NSUInteger _waitingAnimations; + BOOL _didStart; + CFTimeInterval _animationBeginTime; + UIView *_transitionView; + BOOL _transitionShouldCache; + NSMutableSet *_animatingViews; +} + ++ (void)initialize +{ + if (self == [UIViewAnimationGroup class]) { + runningAnimationGroups = [NSMutableSet setWithCapacity:1]; + } +} -- (id)initWithGroupName:(NSString *)theName context:(void *)theContext +- (id)initWithAnimationOptions:(UIViewAnimationOptions)options { if ((self=[super init])) { - _name = [theName copy]; - _context = theContext; _waitingAnimations = 1; - _animationDuration = 0.2; - _animationCurve = UIViewAnimationCurveEaseInOut; - _animationBeginsFromCurrentState = NO; - _animationRepeatAutoreverses = NO; - _animationRepeatCount = 0; _animationBeginTime = CACurrentMediaTime(); - _animatingViews = [[NSMutableSet alloc] initWithCapacity:0]; + _animatingViews = [NSMutableSet setWithCapacity:2]; + + self.duration = 0.2; + + self.repeatCount = UIViewAnimationOptionIsSet(options, UIViewAnimationOptionRepeat)? FLT_MAX : 0; + self.allowUserInteraction = UIViewAnimationOptionIsSet(options, UIViewAnimationOptionAllowUserInteraction); + self.repeatAutoreverses = UIViewAnimationOptionIsSet(options, UIViewAnimationOptionAutoreverse); + self.beginsFromCurrentState = UIViewAnimationOptionIsSet(options, UIViewAnimationOptionBeginFromCurrentState); + + const UIViewAnimationOptions animationCurve = UIViewAnimationOptionCurve(options); + if (animationCurve == UIViewAnimationOptionCurveEaseIn) { + self.curve = UIViewAnimationCurveEaseIn; + } else if (animationCurve == UIViewAnimationOptionCurveEaseOut) { + self.curve = UIViewAnimationCurveEaseOut; + } else if (animationCurve == UIViewAnimationOptionCurveLinear) { + self.curve = UIViewAnimationCurveLinear; + } else { + self.curve = UIViewAnimationCurveEaseInOut; + } + + const UIViewAnimationOptions animationTransition = UIViewAnimationOptionTransition(options); + if (animationTransition == UIViewAnimationOptionTransitionFlipFromLeft) { + self.transition = UIViewAnimationGroupTransitionFlipFromLeft; + } else if (animationTransition == UIViewAnimationOptionTransitionFlipFromRight) { + self.transition = UIViewAnimationGroupTransitionFlipFromRight; + } else if (animationTransition == UIViewAnimationOptionTransitionCurlUp) { + self.transition = UIViewAnimationGroupTransitionCurlUp; + } else if (animationTransition == UIViewAnimationOptionTransitionCurlDown) { + self.transition = UIViewAnimationGroupTransitionCurlDown; + } else if (animationTransition == UIViewAnimationOptionTransitionCrossDissolve) { + self.transition = UIViewAnimationGroupTransitionCrossDissolve; + } else if (animationTransition == UIViewAnimationOptionTransitionFlipFromTop) { + self.transition = UIViewAnimationGroupTransitionFlipFromTop; + } else if (animationTransition == UIViewAnimationOptionTransitionFlipFromBottom) { + self.transition = UIViewAnimationGroupTransitionFlipFromBottom; + } else { + self.transition = UIViewAnimationGroupTransitionNone; + } } return self; } -- (void)dealloc +- (NSArray *)allAnimatingViews { - [_name release]; - [_animationDelegate release]; - [_animatingViews release]; - [super dealloc]; + @synchronized(runningAnimationGroups) { + return [_animatingViews allObjects]; + } } -+ (id)animationGroupWithName:(NSString *)theName context:(void *)theContext +- (void)notifyAnimationsDidStartIfNeeded { - return [[[self alloc] initWithGroupName:theName context:theContext] autorelease]; + if (!_didStart) { + _didStart = YES; + + @synchronized(runningAnimationGroups) { + [runningAnimationGroups addObject:self]; + } + + if ([self.delegate respondsToSelector:self.willStartSelector]) { + typedef void(*WillStartMethod)(id, SEL, NSString *, void *); + WillStartMethod method = (WillStartMethod)[self.delegate methodForSelector:self.willStartSelector]; + method(self.delegate, self.willStartSelector, self.name, self.context); + } + } } - (void)notifyAnimationsDidStopIfNeededUsingStatus:(BOOL)animationsDidFinish { if (_waitingAnimations == 0) { - if ([_animationDelegate respondsToSelector:_animationDidStopSelector]) { - NSMethodSignature *signature = [_animationDelegate methodSignatureForSelector:_animationDidStopSelector]; - NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; - [invocation setSelector:_animationDidStopSelector]; - NSInteger remaining = [signature numberOfArguments] - 2; - + if ([self.delegate respondsToSelector:self.didStopSelector]) { NSNumber *finishedArgument = [NSNumber numberWithBool:animationsDidFinish]; - - if (remaining > 0) { - [invocation setArgument:&_name atIndex:2]; - remaining--; - } - - if (remaining > 0) { - [invocation setArgument:&finishedArgument atIndex:3]; - remaining--; - } - - if (remaining > 0) { - [invocation setArgument:&_context atIndex:4]; - } - - [invocation invokeWithTarget:_animationDelegate]; + typedef void(*DidFinishMethod)(id, SEL, NSString *, NSNumber *, void *); + DidFinishMethod method = (DidFinishMethod)[self.delegate methodForSelector:self.didStopSelector]; + method(self.delegate, self.didStopSelector, self.name, finishedArgument, self.context); + } + + if (self.completionBlock) { + self.completionBlock(animationsDidFinish); + } + + @synchronized(runningAnimationGroups) { + [_animatingViews removeAllObjects]; + [runningAnimationGroups removeObject:self]; } - [_animatingViews removeAllObjects]; } } - (void)animationDidStart:(CAAnimation *)theAnimation { - if (!_didSendStartMessage) { - if ([_animationDelegate respondsToSelector:_animationWillStartSelector]) { - NSMethodSignature *signature = [_animationDelegate methodSignatureForSelector:_animationWillStartSelector]; - NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; - [invocation setSelector:_animationWillStartSelector]; - NSInteger remaining = [signature numberOfArguments] - 2; - - if (remaining > 0) { - [invocation setArgument:&_name atIndex:2]; - remaining--; - } - - if (remaining > 0) { - [invocation setArgument:&_context atIndex:3]; - } - - [invocation invokeWithTarget:_animationDelegate]; - } - _didSendStartMessage = YES; - } + NSAssert([NSThread isMainThread], @"expecting this to be on the main thread"); + + [self notifyAnimationsDidStartIfNeeded]; } - (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag { + NSAssert([NSThread isMainThread], @"expecting this to be on the main thread"); + _waitingAnimations--; [self notifyAnimationsDidStopIfNeededUsingStatus:flag]; } - (CAAnimation *)addAnimation:(CAAnimation *)animation { - animation.timingFunction = CAMediaTimingFunctionFromUIViewAnimationCurve(_animationCurve); - animation.duration = _animationDuration; - animation.beginTime = _animationBeginTime + _animationDelay; - animation.repeatCount = _animationRepeatCount; - animation.autoreverses = _animationRepeatAutoreverses; + animation.timingFunction = CAMediaTimingFunctionFromUIViewAnimationCurve(self.curve); + animation.duration = self.duration; + animation.beginTime = _animationBeginTime + self.delay; + animation.repeatCount = self.repeatCount; + animation.autoreverses = self.repeatAutoreverses; animation.fillMode = kCAFillModeBackwards; animation.delegate = self; animation.removedOnCompletion = YES; @@ -151,83 +209,70 @@ - (CAAnimation *)addAnimation:(CAAnimation *)animation - (id)actionForView:(UIView *)view forKey:(NSString *)keyPath { - [_animatingViews addObject:view]; - CALayer *layer = view.layer; - CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:keyPath]; - animation.fromValue = _animationBeginsFromCurrentState? [layer.presentationLayer valueForKey:keyPath] : [layer valueForKey:keyPath]; - return [self addAnimation:animation]; -} - -- (void)setAnimationBeginsFromCurrentState:(BOOL)beginFromCurrentState -{ - _animationBeginsFromCurrentState = beginFromCurrentState; -} - -- (void)setAnimationCurve:(UIViewAnimationCurve)curve -{ - _animationCurve = curve; -} - -- (void)setAnimationDelay:(NSTimeInterval)delay -{ - _animationDelay = delay; -} - -- (void)setAnimationDelegate:(id)delegate -{ - if (delegate != _animationDelegate) { - [_animationDelegate release]; - _animationDelegate = [delegate retain]; + @synchronized(runningAnimationGroups) { + [_animatingViews addObject:view]; } -} -- (void)setAnimationDidStopSelector:(SEL)selector -{ - _animationDidStopSelector = selector; -} - -- (void)setAnimationDuration:(NSTimeInterval)newDuration -{ - _animationDuration = newDuration; -} - -- (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses -{ - _animationRepeatAutoreverses = repeatAutoreverses; -} - -- (void)setAnimationRepeatCount:(float)repeatCount -{ - _animationRepeatCount = repeatCount; + if (_transitionView && self.transition != UIViewAnimationGroupTransitionNone) { + return nil; + } else { + CALayer *layer = view.layer; + CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:keyPath]; + animation.fromValue = self.beginsFromCurrentState? [layer.presentationLayer valueForKey:keyPath] : [layer valueForKey:keyPath]; + return [self addAnimation:animation]; + } } -- (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache +- (void)setTransitionView:(UIView *)view shouldCache:(BOOL)cache; { - _transitionLayer = view.layer; - _transitionType = transition; + _transitionView = view; _transitionShouldCache = cache; } -- (void)setAnimationWillStartSelector:(SEL)selector -{ - _animationWillStartSelector = selector; -} - - (void)commit { - if (_transitionLayer) { + if (_transitionView && self.transition != UIViewAnimationGroupTransitionNone) { CATransition *trans = [CATransition animation]; - trans.type = kCATransitionMoveIn; - switch (_transitionType) { - case UIViewAnimationTransitionNone: trans.subtype = nil; break; - case UIViewAnimationTransitionCurlUp: trans.subtype = kCATransitionFromTop; break; - case UIViewAnimationTransitionCurlDown: trans.subtype = kCATransitionFromBottom; break; - case UIViewAnimationTransitionFlipFromLeft: trans.subtype = kCATransitionFromLeft; break; - case UIViewAnimationTransitionFlipFromRight: trans.subtype = kCATransitionFromRight; break; + switch (self.transition) { + case UIViewAnimationGroupTransitionFlipFromLeft: + trans.type = kCATransitionPush; + trans.subtype = kCATransitionFromLeft; + break; + + case UIViewAnimationGroupTransitionFlipFromRight: + trans.type = kCATransitionPush; + trans.subtype = kCATransitionFromRight; + break; + + case UIViewAnimationGroupTransitionFlipFromTop: + trans.type = kCATransitionPush; + trans.subtype = kCATransitionFromTop; + break; + + case UIViewAnimationGroupTransitionFlipFromBottom: + trans.type = kCATransitionPush; + trans.subtype = kCATransitionFromBottom; + break; + + case UIViewAnimationGroupTransitionCurlUp: + trans.type = kCATransitionReveal; + trans.subtype = kCATransitionFromTop; + break; + + case UIViewAnimationGroupTransitionCurlDown: + trans.type = kCATransitionReveal; + trans.subtype = kCATransitionFromBottom; + break; + + case UIViewAnimationGroupTransitionCrossDissolve: + default: + trans.type = kCATransitionFade; + break; } - [_transitionLayer addAnimation:[self addAnimation:trans] forKey:kCATransition]; + [_animatingViews addObject:_transitionView]; + [_transitionView.layer addAnimation:[self addAnimation:trans] forKey:kCATransition]; } _waitingAnimations--; diff --git a/UIKit/Classes/UIViewController.h b/UIKit/Classes/UIViewController.h index 87796790..d0fbb7f1 100644 --- a/UIKit/Classes/UIViewController.h +++ b/UIKit/Classes/UIViewController.h @@ -34,43 +34,23 @@ @class UITabBarController; -typedef enum { +typedef NS_ENUM(NSInteger, UIModalPresentationStyle) { UIModalPresentationFullScreen = 0, UIModalPresentationPageSheet, UIModalPresentationFormSheet, UIModalPresentationCurrentContext, -} UIModalPresentationStyle; +}; -typedef enum { +typedef NS_ENUM(NSInteger, UIModalTransitionStyle) { UIModalTransitionStyleCoverVertical = 0, UIModalTransitionStyleFlipHorizontal, UIModalTransitionStyleCrossDissolve, UIModalTransitionStylePartialCurl, -} UIModalTransitionStyle; +}; @class UINavigationItem, UINavigationController, UIBarButtonItem, UISplitViewController; -@interface UIViewController : UIResponder { -@private - UIView *_view; - BOOL _wantsFullScreenLayout; - NSString *_title; - CGSize _contentSizeForViewInPopover; - BOOL _modalInPopover; - UINavigationItem *_navigationItem; - NSArray *_toolbarItems; - UIModalPresentationStyle _modalPresentationStyle; - BOOL _editing; - BOOL _hidesBottomBarWhenPushed; - UIViewController *_parentViewController; - UIViewController *_modalViewController; - UISearchDisplayController *_searchDisplayController; - UIModalTransitionStyle _modalTransitionStyle; - - UITabBarItem *_tabBarItem; - UITabBarController *_tabBarController; -} - +@interface UIViewController : UIResponder - (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle; // won't load a nib no matter what you do! - (BOOL)isViewLoaded; @@ -86,46 +66,70 @@ typedef enum { - (void)viewWillLayoutSubviews; - (void)viewDidLayoutSubviews; +- (void)presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion; +- (void)dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion; + +// these are deprecated on iOS 6 - (void)presentModalViewController:(UIViewController *)modalViewController animated:(BOOL)animated; // works, but not exactly correctly. - (void)dismissModalViewControllerAnimated:(BOOL)animated; // see comments in dismissModalViewController -- (void)didReceiveMemoryWarning; // doesn't do anything and is never called... +- (void)didReceiveMemoryWarning; // is called when UIApplicationDidReceiveMemoryWarningNotification is posted, which is currently only done by private API for.. fun, I guess? - (void)setToolbarItems:(NSArray *)toolbarItems animated:(BOOL)animated; - (void)setEditing:(BOOL)editing animated:(BOOL)animated; -- (UIBarButtonItem *)editButtonItem; // not implemented +- (UIBarButtonItem *)editButtonItem; - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation; - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration; - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration; - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation; +- (BOOL)isMovingFromParentViewController; +- (BOOL)isMovingToParentViewController; +- (BOOL)isBeingPresented; +- (BOOL)isBeingDismissed; + +- (void)addChildViewController:(UIViewController *)childController; +- (void)removeFromParentViewController; +- (BOOL)shouldAutomaticallyForwardRotationMethods; +- (BOOL)shouldAutomaticallyForwardAppearanceMethods; +- (void)transitionFromViewController:(UIViewController *)fromViewController toViewController:(UIViewController *)toViewController duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion; +- (void)beginAppearanceTransition:(BOOL)isAppearing animated:(BOOL)animated; // iOS 6+ +- (void)endAppearanceTransition; // iOS 6+ -@property (nonatomic, readonly, copy) NSString *nibName; // always returns nil -@property (nonatomic, readonly, retain) NSBundle *nibBundle; // always returns nil +- (void)willMoveToParentViewController:(UIViewController *)parent; +- (void)didMoveToParentViewController:(UIViewController *)parent; + +@property (nonatomic, readonly, copy) NSString *nibName; +@property (nonatomic, readonly, retain) NSBundle *nibBundle; @property (nonatomic, retain) UIView *view; -@property (nonatomic, assign) BOOL wantsFullScreenLayout; // doesn't do anything right now +@property (nonatomic, assign) BOOL wantsFullScreenLayout; @property (nonatomic, copy) NSString *title; -@property (nonatomic, readonly) UIInterfaceOrientation interfaceOrientation; // always returns UIInterfaceOrientationLandscapeLeft +@property (nonatomic, readonly) UIInterfaceOrientation interfaceOrientation; @property (nonatomic, readonly, retain) UINavigationItem *navigationItem; @property (nonatomic, retain) NSArray *toolbarItems; @property (nonatomic, getter=isEditing) BOOL editing; @property (nonatomic) BOOL hidesBottomBarWhenPushed; @property (nonatomic, readwrite) CGSize contentSizeForViewInPopover; -@property (nonatomic,readwrite,getter=isModalInPopover) BOOL modalInPopover; +@property (nonatomic, readwrite, getter=isModalInPopover) BOOL modalInPopover; -@property (nonatomic, readonly) UIViewController *modalViewController; @property (nonatomic, assign) UIModalPresentationStyle modalPresentationStyle; -@property (nonatomic, assign) UIModalTransitionStyle modalTransitionStyle; // not used right now +@property (nonatomic, assign) UIModalTransitionStyle modalTransitionStyle; +@property (nonatomic, assign) BOOL definesPresentationContext; +@property (nonatomic, assign) BOOL providesPresentationContextTransitionStyle; @property (nonatomic, readonly) UIViewController *parentViewController; + +@property (nonatomic, readonly) NSArray *childViewControllers; +@property (nonatomic, readonly) UIViewController *presentingViewController; +@property (nonatomic, readonly) UIViewController *presentedViewController; + @property (nonatomic, readonly, retain) UINavigationController *navigationController; @property (nonatomic, readonly, retain) UISplitViewController *splitViewController; -@property (nonatomic, readonly, retain) UISearchDisplayController *searchDisplayController; // stub - -// stubs -@property (nonatomic, retain) UITabBarItem *tabBarItem; @property (nonatomic, readonly, retain) UITabBarController *tabBarController; +@property (nonatomic, readonly, retain) UISearchDisplayController *searchDisplayController; +@property (nonatomic, readonly, retain) UIViewController *modalViewController; +@property (nonatomic, retain) UITabBarItem *tabBarItem; @end diff --git a/UIKit/Classes/UIViewController.m b/UIKit/Classes/UIViewController.m index 6d0ec441..89e09b5a 100644 --- a/UIKit/Classes/UIViewController.m +++ b/UIKit/Classes/UIViewController.m @@ -27,7 +27,7 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#import "UIViewController.h" +#import "UIViewControllerAppKitIntegration.h" #import "UIView+UIPrivate.h" #import "UIScreen.h" #import "UIWindow.h" @@ -40,12 +40,23 @@ #import "UIScreen.h" #import "UITabBarController.h" -@implementation UIViewController -@synthesize view=_view, wantsFullScreenLayout=_wantsFullScreenLayout, title=_title, contentSizeForViewInPopover=_contentSizeForViewInPopover; -@synthesize modalInPopover=_modalInPopover, toolbarItems=_toolbarItems, modalPresentationStyle=_modalPresentationStyle, editing=_editing; -@synthesize modalViewController=_modalViewController, parentViewController=_parentViewController; -@synthesize modalTransitionStyle=_modalTransitionStyle, hidesBottomBarWhenPushed=_hidesBottomBarWhenPushed; -@synthesize searchDisplayController=_searchDisplayController, tabBarItem=_tabBarItem, tabBarController=_tabBarController; +typedef NS_ENUM(NSInteger, _UIViewControllerParentageTransition) { + _UIViewControllerParentageTransitionNone = 0, + _UIViewControllerParentageTransitionToParent, + _UIViewControllerParentageTransitionFromParent, +}; + +@implementation UIViewController { + UIView *_view; + UINavigationItem *_navigationItem; + NSMutableArray *_childViewControllers; + __unsafe_unretained UIViewController *_parentViewController; + + NSUInteger _appearanceTransitionStack; + BOOL _appearanceTransitionIsAnimated; + BOOL _viewIsAppearing; + _UIViewControllerParentageTransition _parentageTransition; +} - (id)init { @@ -57,18 +68,15 @@ - (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle if ((self=[super init])) { _contentSizeForViewInPopover = CGSizeMake(320,1100); _hidesBottomBarWhenPushed = NO; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveMemoryWarning) name:UIApplicationDidReceiveMemoryWarningNotification object:[UIApplication sharedApplication]]; } return self; } - (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidReceiveMemoryWarningNotification object:[UIApplication sharedApplication]]; [_view _setViewController:nil]; - [_modalViewController release]; - [_navigationItem release]; - [_title release]; - [_view release]; - [super dealloc]; } - (NSString *)nibName @@ -86,6 +94,16 @@ - (UIResponder *)nextResponder return _view.superview; } +- (UIViewController *)defaultResponderChildViewController +{ + return nil; +} + +- (UIResponder *)defaultResponder +{ + return nil; +} + - (BOOL)isViewLoaded { return (_view != nil); @@ -96,8 +114,11 @@ - (UIView *)view if ([self isViewLoaded]) { return _view; } else { + const BOOL wereEnabled = [UIView areAnimationsEnabled]; + [UIView setAnimationsEnabled:NO]; [self loadView]; [self viewDidLoad]; + [UIView setAnimationsEnabled:wereEnabled]; return _view; } } @@ -106,15 +127,14 @@ - (void)setView:(UIView *)aView { if (aView != _view) { [_view _setViewController:nil]; - [_view release]; - _view = [aView retain]; + _view = aView; [_view _setViewController:self]; } } - (void)loadView { - self.view = [[[UIView alloc] initWithFrame:CGRectMake(0,0,320,480)] autorelease]; + self.view = [[UIView alloc] initWithFrame:CGRectMake(0,0,320,480)]; } - (void)viewDidLoad @@ -166,16 +186,18 @@ - (UINavigationItem *)navigationItem return _navigationItem; } -- (void)_setParentViewController:(UIViewController *)parentController +- (void)setTitle:(NSString *)title { - _parentViewController = parentController; + if (![_title isEqual:title]) { + _title = [title copy]; + _navigationItem.title = _title; + } } - (void)setToolbarItems:(NSArray *)theToolbarItems animated:(BOOL)animated { - if (_toolbarItems != theToolbarItems) { - [_toolbarItems release]; - _toolbarItems = [theToolbarItems retain]; + if (![_toolbarItems isEqual:theToolbarItems]) { + _toolbarItems = theToolbarItems; [self.navigationController.toolbar setItems:_toolbarItems animated:animated]; } } @@ -201,10 +223,19 @@ - (UIBarButtonItem *)editButtonItem return nil; } +- (void)presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion +{ +} + +- (void)dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion +{ +} + - (void)presentModalViewController:(UIViewController *)modalViewController animated:(BOOL)animated { + /* if (!_modalViewController && _modalViewController != self) { - _modalViewController = [modalViewController retain]; + _modalViewController = modalViewController; [_modalViewController _setParentViewController:self]; UIWindow *window = self.view.window; @@ -221,13 +252,14 @@ - (void)presentModalViewController:(UIViewController *)modalViewController anima selfView.hidden = YES; // I think the real one may actually remove it, which would mean needing to remember the superview, I guess? Not sure... [self viewDidDisappear:animated]; - [_modalViewController viewDidAppear:animated]; } + */ } - (void)dismissModalViewControllerAnimated:(BOOL)animated { + /* // NOTE: This is not implemented entirely correctly - the actual dismissModalViewController is somewhat subtle. // There is supposed to be a stack of modal view controllers that dismiss in a specific way,e tc. // The whole system of related view controllers is not really right - not just with modals, but everything else like @@ -246,13 +278,13 @@ - (void)dismissModalViewControllerAnimated:(BOOL)animated [_modalViewController.view removeFromSuperview]; [_modalViewController _setParentViewController:nil]; - [_modalViewController autorelease]; _modalViewController = nil; [self viewDidAppear:animated]; } else { [self.parentViewController dismissModalViewControllerAnimated:animated]; } + */ } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation @@ -298,4 +330,202 @@ - (NSString *)description return [NSString stringWithFormat:@"<%@: %p; title = %@; view = %@>", [self className], self, self.title, self.view]; } + + + + + +- (BOOL)isMovingFromParentViewController +{ + // Docs don't say anything about being required to call super for -willMoveToParentViewController: and people + // on StackOverflow seem to tell each other they can override the method without calling super. Based on that, + // I have no freakin' idea how this method here is meant to know when to return YES... + + // I'm inclined to think that the docs are just unclear and that -willMoveToParentViewController: and + // -didMoveToParentViewController: must have to do *something* for this to work without ambiguity. + + // Now that I think about it some more, I suspect that it is far better to assume the docs imply you must call + // super when you override a method *unless* it says not to. If that assumption is sound, then in that case it + // suggests that when overriding -willMoveToParentViewController: and -didMoveToParentViewController: you are + // expected to call super anyway, which means I could put some implementation in the base class versions safely. + // Generally docs do tend to say things like, "parent implementation does nothing" when they mean you can skip + // the call to super, and the docs currently say no such thing for -will/didMoveToParentViewController:. + + // In all likely hood, all that would happen if you didn't call super from a -will/didMoveToParentViewController: + // override is that -isMovingFromParentViewController and -isMovingToParentViewController would return the + // wrong answer, and if you never use them, you'll never even notice that bug! + + return (_appearanceTransitionStack > 0) && (_parentageTransition == _UIViewControllerParentageTransitionFromParent); +} + +- (BOOL)isMovingToParentViewController +{ + return (_appearanceTransitionStack > 0) && (_parentageTransition == _UIViewControllerParentageTransitionToParent); +} + +- (BOOL)isBeingPresented +{ + // TODO + return (_appearanceTransitionStack > 0) && (NO); +} + +- (BOOL)isBeingDismissed +{ + // TODO + return (_appearanceTransitionStack > 0) && (NO); +} + +- (UIViewController *)presentingViewController +{ + // TODO + return nil; +} + +- (UIViewController *)presentedViewController +{ + // TODO + return nil; +} + +- (NSArray *)childViewControllers +{ + return [_childViewControllers copy]; +} + +- (void)addChildViewController:(UIViewController *)childController +{ + NSAssert(childController != nil, @"cannot add nil child view controller"); + NSAssert(childController.parentViewController == nil, @"thou shalt have no other parent before me"); + + if (!_childViewControllers) { + _childViewControllers = [NSMutableArray arrayWithCapacity:1]; + } + + [childController willMoveToParentViewController:self]; + [_childViewControllers addObject:childController]; + childController->_parentViewController = self; +} + +- (void)_removeFromParentViewController +{ + if (_parentViewController) { + [_parentViewController->_childViewControllers removeObject:self]; + + if ([_parentViewController->_childViewControllers count] == 0) { + _parentViewController->_childViewControllers = nil; + } + + _parentViewController = nil; + } +} + +- (void)removeFromParentViewController +{ + NSAssert(self.parentViewController != nil, @"view controller has no parent"); + + [self _removeFromParentViewController]; + [self didMoveToParentViewController:nil]; +} + +- (BOOL)shouldAutomaticallyForwardRotationMethods +{ + return YES; +} + +- (BOOL)shouldAutomaticallyForwardAppearanceMethods +{ + return YES; +} + +- (void)transitionFromViewController:(UIViewController *)fromViewController toViewController:(UIViewController *)toViewController duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion +{ + NSAssert(fromViewController.parentViewController == toViewController.parentViewController && fromViewController.parentViewController != nil, @"child controllers must share common parent"); + const BOOL animated = (duration > 0); + + [fromViewController beginAppearanceTransition:NO animated:animated]; + [toViewController beginAppearanceTransition:YES animated:animated]; + + [UIView transitionWithView:self.view + duration:duration + options:options + animations:^{ + if (animations) { + animations(); + } + + [self.view addSubview:toViewController.view]; + } + completion:^(BOOL finished) { + if (completion) { + completion(finished); + } + + [fromViewController.view removeFromSuperview]; + + [fromViewController endAppearanceTransition]; + [toViewController endAppearanceTransition]; + }]; +} + +- (void)beginAppearanceTransition:(BOOL)isAppearing animated:(BOOL)animated +{ + if (_appearanceTransitionStack == 0 || (_appearanceTransitionStack > 0 && _viewIsAppearing != isAppearing)) { + _appearanceTransitionStack = 1; + _appearanceTransitionIsAnimated = animated; + _viewIsAppearing = isAppearing; + + if ([self shouldAutomaticallyForwardAppearanceMethods]) { + for (UIViewController *child in self.childViewControllers) { + if ([child isViewLoaded] && [child.view isDescendantOfView:self.view]) { + [child beginAppearanceTransition:isAppearing animated:animated]; + } + } + } + + if (_viewIsAppearing) { + [self view]; // ensures the view is loaded before viewWillAppear: happens + [self viewWillAppear:_appearanceTransitionIsAnimated]; + } else { + [self viewWillDisappear:_appearanceTransitionIsAnimated]; + } + } else { + _appearanceTransitionStack++; + } +} + +- (void)endAppearanceTransition +{ + if (_appearanceTransitionStack > 0) { + _appearanceTransitionStack--; + + if (_appearanceTransitionStack == 0) { + if ([self shouldAutomaticallyForwardAppearanceMethods]) { + for (UIViewController *child in self.childViewControllers) { + [child endAppearanceTransition]; + } + } + + if (_viewIsAppearing) { + [self viewDidAppear:_appearanceTransitionIsAnimated]; + } else { + [self viewDidDisappear:_appearanceTransitionIsAnimated]; + } + } + } +} + +- (void)willMoveToParentViewController:(UIViewController *)parent +{ + if (parent) { + _parentageTransition = _UIViewControllerParentageTransitionToParent; + } else { + _parentageTransition = _UIViewControllerParentageTransitionFromParent; + } +} + +- (void)didMoveToParentViewController:(UIViewController *)parent +{ + _parentageTransition = _UIViewControllerParentageTransitionNone; +} + @end diff --git a/UIKit/Classes/UIViewControllerAppKitIntegration.h b/UIKit/Classes/UIViewControllerAppKitIntegration.h new file mode 100644 index 00000000..e54dea47 --- /dev/null +++ b/UIKit/Classes/UIViewControllerAppKitIntegration.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2013, The Iconfactory. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of The Iconfactory nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE ICONFACTORY BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "UIViewController.h" + +@interface UIViewController (AppKitIntegration) +// the purpose of this is to more easily support menu actions so the responder chain isn't +// broken all the time and you don't have to add a bunch of -canBecomeFirstResponser and +// -becomeFirstResponder calls in your code just to be able to handle this situation. On OSX +// it's pretty normal to expect that where you click becomes a responder and gets focus, but +// iOS code doesn't typically have such a notion because being a first responder is almost +// always only used for text fields and such. so iOS code will typically resign the first +// responder and leave nothing in it's place, which is perfectly fine most of the time on iOS. +// however on OSX we want to be able to easily handle menu actions that might apply to a whole +// view or something and since Chameleon bridges the responder chains, this is generally easy +// except that there is almost never a first responder to start sending things to! so the idea +// here is that your custom UIViewController subclasses can override these and return whatever +// they want to help things along. + +// since -defaultResponderChildViewController returns nil by default, you will have to manage +// this yourself everywhere along your view controller hierarchy which is sort of annoying, but +// we used a lot of custom child view controllers in our hierarchy, so it is easy to return +// the most logical "primary" child controller for the user at the time, if there is one, or +// nil if reciever is the most logical place to start. you do not need to recursively call +// -defaultResponderChildViewController, instead just return the best controller from the point +// of view of the receiver and Chameleon will walk down the resulting chain until it returns +// nil. when it eventually returns nil, the search stops and then the last receiver is sent +// -defaultResponder to ask for the responder it would like to use to start the chain. if that +// returns nil, then there is effectively no responder chain so the action just gets passed into +// AppKit's responder chain. if there is a responder, we try to deliver the action down the +// responder chain starting from the result of -defaultResponder. if that fails, we fall off the +// end and end up back on AppKit's chain. + +// -defaultResponderChildViewController is first called on the keyWindow's -rootViewController, +// and only if that window doesn't already have an explicit firstResponder (such as if a control +// or something became first responder in the usual way). it then proceeds as described above +// looking for something to use as the start of a responder chain. + +// returns nil by default +- (UIViewController *)defaultResponderChildViewController; + +// returns nil by default +- (UIResponder *)defaultResponder; +@end diff --git a/UIKit/Classes/UIWebView.h b/UIKit/Classes/UIWebView.h index 768934f7..2bf247af 100644 --- a/UIKit/Classes/UIWebView.h +++ b/UIKit/Classes/UIWebView.h @@ -27,10 +27,10 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#import "UIView.h" +#import "UIScrollView.h" #import "UIDataDetectors.h" -enum { +typedef NS_ENUM(NSInteger, UIWebViewNavigationType) { UIWebViewNavigationTypeLinkClicked, UIWebViewNavigationTypeFormSubmitted, UIWebViewNavigationTypeBackForward, @@ -38,9 +38,8 @@ enum { UIWebViewNavigationTypeFormResubmitted, UIWebViewNavigationTypeOther }; -typedef NSUInteger UIWebViewNavigationType; -@class UIWebView, UIViewAdapter, WebView; +@class UIWebView; @protocol UIWebViewDelegate @optional @@ -49,22 +48,7 @@ typedef NSUInteger UIWebViewNavigationType; - (void)webViewDidFinishLoad:(UIWebView *)webView; @end -@interface UIWebView : UIView { -@private - __unsafe_unretained id _delegate; - NSURLRequest *_request; - UIDataDetectorTypes _dataDetectorTypes; - WebView *_webView; - UIViewAdapter *_webViewAdapter; - BOOL _scalesPageToFit; - - struct { - unsigned shouldStartLoadWithRequest : 1; - unsigned didFailLoadWithError : 1; - unsigned didFinishLoad : 1; - } _delegateHas; -} - +@interface UIWebView : UIView - (void)loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL; - (void)loadRequest:(NSURLRequest *)request; - (void)stopLoading; @@ -79,7 +63,7 @@ typedef NSUInteger UIWebViewNavigationType; @property (nonatomic, readonly, getter=canGoBack) BOOL canGoBack; @property (nonatomic, readonly, getter=canGoForward) BOOL canGoForward; @property (nonatomic, assign) BOOL scalesPageToFit; // not implemented -@property (nonatomic, readonly, retain) NSURLRequest *request; +@property (nonatomic, readonly, strong) NSURLRequest *request; @property (nonatomic) UIDataDetectorTypes dataDetectorTypes; - +@property (nonatomic, readonly, strong) UIScrollView *scrollView; // not implemented @end diff --git a/UIKit/Classes/UIWebView.m b/UIKit/Classes/UIWebView.m index df9da91c..261f16ae 100644 --- a/UIKit/Classes/UIWebView.m +++ b/UIKit/Classes/UIWebView.m @@ -31,14 +31,20 @@ #import "UIViewAdapter.h" #import -@implementation UIWebView -@synthesize request=_request, delegate=_delegate, dataDetectorTypes=_dataDetectorTypes, scalesPageToFit=_scalesPageToFit; +@implementation UIWebView { + WebView *_webView; + UIViewAdapter *_webViewAdapter; + + struct { + unsigned shouldStartLoadWithRequest : 1; + unsigned didFailLoadWithError : 1; + unsigned didFinishLoad : 1; + } _delegateHas; +} - (id)initWithFrame:(CGRect)frame { if ((self=[super initWithFrame:frame])) { - _scalesPageToFit = NO; - _webView = [(WebView *)[WebView alloc] initWithFrame:NSRectFromCGRect(self.bounds)]; [_webView setAutoresizingMask:(NSViewWidthSizable|NSViewHeightSizable)]; [_webView setPolicyDelegate:self]; @@ -60,9 +66,6 @@ - (void)dealloc [_webView setPolicyDelegate:nil]; [_webView setFrameLoadDelegate:nil]; [_webView setUIDelegate:nil]; - [_webViewAdapter release]; - [_webView release]; - [super dealloc]; } - (void)layoutSubviews @@ -87,8 +90,7 @@ - (void)loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL - (void)loadRequest:(NSURLRequest *)request { if (request != _request) { - [_request release]; - _request = [request retain]; + _request = request; } [[_webView mainFrame] loadRequest:_request]; @@ -150,6 +152,11 @@ - (id)valueForUndefinedKey:(NSString *)key return nil; } +- (UIScrollView *)scrollView +{ + return nil; +} + #pragma mark - #pragma mark WebView Policy Delegate diff --git a/UIKit/Classes/UIWindow.h b/UIKit/Classes/UIWindow.h index dda30d6a..d3ea7300 100644 --- a/UIKit/Classes/UIWindow.h +++ b/UIKit/Classes/UIWindow.h @@ -43,6 +43,7 @@ extern NSString *const UIKeyboardWillShowNotification; extern NSString *const UIKeyboardDidShowNotification; extern NSString *const UIKeyboardWillHideNotification; extern NSString *const UIKeyboardDidHideNotification; +extern NSString *const UIKeyboardWillChangeFrameNotification; extern NSString *const UIKeyboardFrameBeginUserInfoKey; extern NSString *const UIKeyboardFrameEndUserInfoKey; @@ -54,17 +55,9 @@ extern NSString *const UIKeyboardCenterBeginUserInfoKey; extern NSString *const UIKeyboardCenterEndUserInfoKey; extern NSString *const UIKeyboardBoundsUserInfoKey; - @class UIScreen, UIViewController; -@interface UIWindow : UIView { -@private - UIScreen *_screen; - UIResponder *_firstResponder; - NSUndoManager *_undoManager; - UIViewController *_rootViewController; -} - +@interface UIWindow : UIView - (CGPoint)convertPoint:(CGPoint)toConvert toWindow:(UIWindow *)toWindow; - (CGPoint)convertPoint:(CGPoint)toConvert fromWindow:(UIWindow *)fromWindow; - (CGRect)convertRect:(CGRect)toConvert fromWindow:(UIWindow *)fromWindow; @@ -72,13 +65,20 @@ extern NSString *const UIKeyboardBoundsUserInfoKey; - (void)makeKeyWindow; - (void)makeKeyAndVisible; + - (void)resignKeyWindow; - (void)becomeKeyWindow; + - (void)sendEvent:(UIEvent *)event; +// this property returns YES only if the underlying screen's UIKitView is on the AppKit's key window +// and this UIWindow was made key at some point in the past (and is still key from the point of view +// of the underlying screen) which is of course rather different from the real UIKit. +// this is done because unlike iOS, on OSX the user can change the key window at will at any time and +// we need a way to reconnect key windows when they change. :/ @property (nonatomic, readonly, getter=isKeyWindow) BOOL keyWindow; -@property (nonatomic, retain) UIScreen *screen; -@property (nonatomic, assign) UIWindowLevel windowLevel; -@property (nonatomic,retain) UIViewController *rootViewController; +@property (nonatomic, strong) UIScreen *screen; +@property (nonatomic, assign) UIWindowLevel windowLevel; +@property (nonatomic, strong) UIViewController *rootViewController; @end diff --git a/UIKit/Classes/UIWindow.m b/UIKit/Classes/UIWindow.m index af5f20d4..fa9767b0 100644 --- a/UIKit/Classes/UIWindow.m +++ b/UIKit/Classes/UIWindow.m @@ -31,14 +31,14 @@ #import "UIView+UIPrivate.h" #import "UIScreen+UIPrivate.h" #import "UIScreenAppKitIntegration.h" -#import "UIApplication+UIPrivate.h" -#import "UIEvent.h" +#import "UIApplication.h" #import "UITouch+UIPrivate.h" #import "UIScreenMode.h" #import "UIResponderAppKitIntegration.h" #import "UIViewController.h" -#import "UIGestureRecognizerSubclass.h" #import "UIGestureRecognizer+UIPrivate.h" +#import "UITouchEvent.h" +#import "UIKitView.h" #import #import @@ -55,6 +55,7 @@ NSString *const UIKeyboardDidShowNotification = @"UIKeyboardDidShowNotification"; NSString *const UIKeyboardWillHideNotification = @"UIKeyboardWillHideNotification"; NSString *const UIKeyboardDidHideNotification = @"UIKeyboardDidHideNotification"; +NSString *const UIKeyboardWillChangeFrameNotification = @"UIKeyboardWillChangeFrameNotification"; NSString *const UIKeyboardFrameBeginUserInfoKey = @"UIKeyboardFrameBeginUserInfoKey"; NSString *const UIKeyboardFrameEndUserInfoKey = @"UIKeyboardFrameEndUserInfoKey"; @@ -66,9 +67,10 @@ NSString *const UIKeyboardCenterEndUserInfoKey = @"UIKeyboardCenterEndUserInfoKey"; NSString *const UIKeyboardBoundsUserInfoKey = @"UIKeyboardBoundsUserInfoKey"; - -@implementation UIWindow -@synthesize screen=_screen, rootViewController=_rootViewController; +@implementation UIWindow { + __weak UIResponder *_firstResponder; + NSUndoManager *_undoManager; +} - (id)initWithFrame:(CGRect)theFrame { @@ -77,6 +79,9 @@ - (id)initWithFrame:(CGRect)theFrame [self _makeHidden]; // do this first because before the screen is set, it will prevent any visibility notifications from being sent. self.screen = [UIScreen mainScreen]; self.opaque = NO; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_NSWindowDidBecomeKeyNotification:) name:NSWindowDidBecomeKeyNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_NSWindowDidResignKeyNotification:) name:NSWindowDidResignKeyNotification object:nil]; } return self; } @@ -85,9 +90,6 @@ - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; [self _makeHidden]; // I don't really like this here, but the real UIKit seems to do something like this on window destruction as it sends a notification and we also need to remove it from the app's list of windows - [_screen release]; - [_undoManager release]; - [_rootViewController release]; // since UIView's dealloc is called after this one, it's hard ot say what might happen in there due to all of the subview removal stuff // so it's safer to make sure these things are nil now rather than potential garbage. I don't like how much work UIView's -dealloc is doing @@ -96,7 +98,6 @@ - (void)dealloc _undoManager = nil; _rootViewController = nil; - [super dealloc]; } - (UIResponder *)_firstResponder @@ -138,13 +139,23 @@ - (void)setRootViewController:(UIViewController *)rootViewController { if (rootViewController != _rootViewController) { [self.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; - [_rootViewController release]; - _rootViewController = [rootViewController retain]; - _rootViewController.view.frame = self.bounds; // unsure about this + + const BOOL was = [UIView areAnimationsEnabled]; + [UIView setAnimationsEnabled:NO]; + _rootViewController = rootViewController; + _rootViewController.view.frame = self.bounds; [self addSubview:_rootViewController.view]; + [self layoutIfNeeded]; + [UIView setAnimationsEnabled:was]; } } +- (void)setFrame:(CGRect)frame +{ + [super setFrame:frame]; + _rootViewController.view.frame = self.bounds; +} + - (void)setScreen:(UIScreen *)theScreen { if (theScreen != _screen) { @@ -154,8 +165,7 @@ - (void)setScreen:(UIScreen *)theScreen [self _makeHidden]; [self.layer removeFromSuperlayer]; - [_screen release]; - _screen = [theScreen retain]; + _screen = theScreen; [[_screen _layer] addSublayer:self.layer]; if (!wasHidden) { @@ -232,26 +242,50 @@ - (CGRect)convertRect:(CGRect)toConvert toWindow:(UIWindow *)toWindow return CGRectMake(convertedOrigin.x, convertedOrigin.y, toConvert.size.width, toConvert.size.height); } -- (void)becomeKeyWindow +- (void)makeKeyWindow { - if ([[self _firstResponder] respondsToSelector:@selector(becomeKeyWindow)]) { - [(id)[self _firstResponder] becomeKeyWindow]; + if (!self.isKeyWindow && self.screen) { + // this check is here because if the underlying screen's UIKitView is AppKit's keyWindow, then + // we must resign it because UIKit thinks it's currently the key window, too, so we do that here. + if ([self.screen.keyWindow isKeyWindow]) { + [self.screen.keyWindow resignKeyWindow]; + } + + // now we set the screen's key window to ourself - note that this doesn't really make it the key + // window yet from an external point of view... + [self.screen _setKeyWindow:self]; + + // if it turns out we're now the key window, it means this window is ultimately within a UIKitView + // that's the current AppKit key window, too, so we make it so. if we are NOT the key window, we + // need to try to tell AppKit to make the UIKitView we're on the key window. If that works out, + // we will get a notification and -becomeKeyWindow will be called from there, so we don't have to + // do anything else in here. + if (self.isKeyWindow) { + [self becomeKeyWindow]; + } else { + [[self.screen.UIKitView window] makeFirstResponder:self.screen.UIKitView]; + [[self.screen.UIKitView window] makeKeyWindow]; + } } - [[NSNotificationCenter defaultCenter] postNotificationName:UIWindowDidBecomeKeyNotification object:self]; } -- (void)makeKeyWindow +- (BOOL)isKeyWindow { - if (!self.isKeyWindow) { - [[UIApplication sharedApplication].keyWindow resignKeyWindow]; - [[UIApplication sharedApplication] _setKeyWindow:self]; - [self becomeKeyWindow]; + // only return YES if we have a screen and our screen's UIKitView is on the AppKit key window + + if (self.screen.keyWindow == self) { + return [[self.screen.UIKitView window] isKeyWindow]; } + + return NO; } -- (BOOL)isKeyWindow +- (void)becomeKeyWindow { - return ([UIApplication sharedApplication].keyWindow == self); + if ([[self _firstResponder] respondsToSelector:@selector(becomeKeyWindow)]) { + [(id)[self _firstResponder] becomeKeyWindow]; + } + [[NSNotificationCenter defaultCenter] postNotificationName:UIWindowDidBecomeKeyNotification object:self]; } - (void)resignKeyWindow @@ -259,15 +293,47 @@ - (void)resignKeyWindow if ([[self _firstResponder] respondsToSelector:@selector(resignKeyWindow)]) { [(id)[self _firstResponder] resignKeyWindow]; } + [[NSNotificationCenter defaultCenter] postNotificationName:UIWindowDidResignKeyNotification object:self]; } +- (void)_NSWindowDidBecomeKeyNotification:(NSNotification *)note +{ + NSWindow *nativeWindow = [note object]; + + // when the underlying screen's NSWindow becomes key, we can use the keyWindow property the screen itself + // to know if this UIWindow should become key again now or not. If things match up, we fire off -becomeKeyWindow + // again to let the app know this happened. Normally iOS doesn't run into situations where the user can change + // the key window out from under the app, so this is going to be somewhat unusual UIKit behavior... + if ([[self.screen.UIKitView window] isEqual:nativeWindow]) { + if (self.screen.keyWindow == self) { + [self becomeKeyWindow]; + } + } +} + +- (void)_NSWindowDidResignKeyNotification:(NSNotification *)note +{ + NSWindow *nativeWindow = [note object]; + + // if the resigned key window is the same window that hosts our underlying screen, then we need to resign + // this UIWindow, too. note that it does NOT actually unset the keyWindow property for the UIScreen! + // this is because if the user clicks back in the screen's window, we need a way to reconnect this UIWindow + // as the key window, too, so that's how that is done. + if ([[self.screen.UIKitView window] isEqual:nativeWindow]) { + if (self.screen.keyWindow == self) { + [self resignKeyWindow]; + } + } +} + - (void)_makeHidden { if (!self.hidden) { [super setHidden:YES]; + if (self.screen) { - [[UIApplication sharedApplication] _windowDidBecomeHidden:self]; + [self.screen _removeWindow:self]; [[NSNotificationCenter defaultCenter] postNotificationName:UIWindowDidBecomeHiddenNotification object:self]; } } @@ -277,8 +343,9 @@ - (void)_makeVisible { if (self.hidden) { [super setHidden:NO]; + if (self.screen) { - [[UIApplication sharedApplication] _windowDidBecomeVisible:self]; + [self.screen _addWindow:self]; [[NSNotificationCenter defaultCenter] postNotificationName:UIWindowDidBecomeVisibleNotification object:self]; } } @@ -311,71 +378,159 @@ - (UIWindowLevel)windowLevel - (void)sendEvent:(UIEvent *)event { - if (event.type == UIEventTypeTouches) { - NSSet *touches = [event touchesForWindow:self]; - NSMutableSet *gestureRecognizers = [NSMutableSet setWithCapacity:0]; + if ([event isKindOfClass:[UITouchEvent class]]) { + [self _processTouchEvent:(UITouchEvent *)event]; + } +} - for (UITouch *touch in touches) { - [gestureRecognizers addObjectsFromArray:touch.gestureRecognizers]; +- (void)_processTouchEvent:(UITouchEvent *)event +{ + // we only support a single touch, so there is a *lot* in here that would break or need serious changes + // to properly support mulitouch. I still don't really like how all this works - especially with the + // gesture recognizers, but I've been struggling to come up with a better way for far too long and just + // have to deal with what I've got now. + + // if there's no touch for this window, return immediately + if (event.touch.window != self) { + return; + } + + // normally there'd be no need to retain the view here, but this works around a strange problem I ran into. + // what can happen is, now that UIView's -removeFromSuperview will remove the view from the active touch + // instead of just cancel the touch (which is how I had implemented it previously - which was wrong), the + // situation can arise where, in response to a touch event of some kind, the view may remove itself from its + // superview in some fashion, which means that the handling of the touchesEnded:withEvent: (or whatever) + // methods could somehow result in the view itself being destroyed before the method is even finished running! + // a strong reference here works around this problem since the view is kept alive until we're done with it. + // If someone can figure out some other, better way to fix this without it having to have this hacky-feeling + // stuff here, that'd be cool, but be aware that this is here for a reason and that the problem it prevents is + // somewhat contrived but not uncommon. + UIView *view = event.touch.view; + + // first deliver new touches to all possible gesture recognizers + if (event.touch.phase == UITouchPhaseBegan) { + for (UIView *subview = view; subview != nil; subview = [subview superview]) { + for (UIGestureRecognizer *gesture in subview.gestureRecognizers) { + [gesture _beginTrackingTouch:event.touch withEvent:event]; + } } + } - for (UIGestureRecognizer *recognizer in gestureRecognizers) { - [recognizer _recognizeTouches:touches withEvent:event]; - } + BOOL gestureRecognized = NO; + BOOL possibleGestures = NO; + BOOL delaysTouchesBegan = NO; + BOOL delaysTouchesEnded = NO; + BOOL cancelsTouches = NO; - for (UITouch *touch in touches) { - // normally there'd be no need to retain the view here, but this works around a strange problem I ran into. - // what can happen is, now that UIView's -removeFromSuperview will remove the view from the active touch - // instead of just cancel the touch (which is how I had implemented it previously - which was wrong), the - // situation can arise where, in response to a touch event of some kind, the view may remove itself from its - // superview in some fashion, which means that the handling of the touchesEnded:withEvent: (or whatever) - // methods could somehow result in the view itself being destroyed before the method is even finished running! - // I ran into this in particular with a load more button in Twitterrific which would crash in UIControl's - // touchesEnded: implemention after sending actions to the registered targets (because one of those targets - // ended up removing the button from view and thus reducing its retain count to 0). For some reason, even - // though I attempted to rearrange stuff in UIControl so that actions were always the last thing done, it'd - // still end up crashing when one of the internal methods returned to touchesEnded:, which didn't make sense - // to me because there was no code after that (at the time) and therefore it should just have been unwinding - // the stack to eventually get back here and all should have been okay. I never figured out exactly why that - // crashed in that way, but by putting a retain here it works around this problem and perhaps others that have - // gone so-far unnoticed. Converting to ARC should also work with this solution because there will be a local - // strong reference to the view retainined throughout the rest of this logic and thus the same protection - // against mid-method view destrustion should be provided under ARC. If someone can figure out some other, - // better way to fix this without it having to have this hacky-feeling retain here, that'd be cool, but be - // aware that this is here for a reason and that the problem it prevents is very rare and somewhat contrived. - UIView *view = [touch.view retain]; - - const UITouchPhase phase = touch.phase; - const _UITouchGesture gesture = [touch _gesture]; + // then allow all tracking gesture recognizers to have their way with the touches in this event before + // anything else is done. + for (UIGestureRecognizer *gesture in event.touch.gestureRecognizers) { + [gesture _continueTrackingWithEvent:event]; + + const BOOL recognized = (gesture.state == UIGestureRecognizerStateRecognized || gesture.state == UIGestureRecognizerStateBegan); + const BOOL possible = (gesture.state == UIGestureRecognizerStatePossible); + + gestureRecognized |= recognized; + possibleGestures |= possible; + + if (recognized || possible) { + delaysTouchesBegan |= gesture.delaysTouchesBegan; - if (phase == UITouchPhaseBegan) { - [view touchesBegan:touches withEvent:event]; - } else if (phase == UITouchPhaseMoved) { - [view touchesMoved:touches withEvent:event]; - } else if (phase == UITouchPhaseEnded) { - [view touchesEnded:touches withEvent:event]; - } else if (phase == UITouchPhaseCancelled) { - [view touchesCancelled:touches withEvent:event]; - } else if (phase == _UITouchPhaseDiscreteGesture && gesture == _UITouchDiscreteGestureMouseMove) { - if ([view hitTest:[touch locationInView:view] withEvent:event]) { - [view mouseMoved:[touch _delta] withEvent:event]; + // special case for scroll views so that -delaysContentTouches works somewhat as expected + // likely this is pretty wrong, but it should work well enough for most normal cases, I suspect. + if ([gesture.view isKindOfClass:[UIScrollView class]]) { + UIScrollView *scrollView = (UIScrollView *)gesture.view; + + if ([gesture isEqual:scrollView.panGestureRecognizer] || [gesture isEqual:scrollView.scrollWheelGestureRecognizer]) { + delaysTouchesBegan |= scrollView.delaysContentTouches; } - } else if (phase == _UITouchPhaseDiscreteGesture && gesture == _UITouchDiscreteGestureRightClick) { - [view rightClick:touch withEvent:event]; - } else if ((phase == _UITouchPhaseDiscreteGesture && gesture == _UITouchDiscreteGestureScrollWheel) || - (phase == _UITouchPhaseGestureChanged && gesture == _UITouchGesturePan)) { - [view scrollWheelMoved:[touch _delta] withEvent:event]; } - - NSCursor *newCursor = [view mouseCursorForEvent:event] ?: [NSCursor arrowCursor]; - - if ([NSCursor currentCursor] != newCursor) { - [newCursor set]; + } + + if (recognized) { + delaysTouchesEnded |= gesture.delaysTouchesEnded; + cancelsTouches |= gesture.cancelsTouchesInView; + } + } + + if (event.isDiscreteGesture) { + // this should prevent delivery of the "touches" down the responder chain in roughly the same way a normal non- + // discrete gesture would based on the settings of the in-play gesture recognizers. + if (!gestureRecognized || (gestureRecognized && !cancelsTouches && !delaysTouchesBegan)) { + if (event.touchEventGesture == UITouchEventGestureRightClick) { + [view rightClick:event.touch withEvent:event]; + } else if (event.touchEventGesture == UITouchEventGestureScrollWheel) { + [view scrollWheelMoved:event.translation withEvent:event]; + } else if (event.touchEventGesture == UITouchEventGestureMouseMove) { + [view mouseMoved:event.touch withEvent:event]; + } else if (event.touchEventGesture == UITouchEventGestureMouseEntered) { + [view mouseEntered:event.touch.view withEvent:event]; + } else if (event.touchEventGesture == UITouchEventGestureMouseExited) { + [view mouseExited:event.touch.view withEvent:event]; + } + } + } else { + if (event.touch.phase == UITouchPhaseBegan) { + if ((!gestureRecognized && !possibleGestures) || !delaysTouchesBegan) { + [view touchesBegan:event.allTouches withEvent:event]; + event.touch.wasDeliveredToView = YES; } + } else if (delaysTouchesBegan && gestureRecognized && !event.touch.wasDeliveredToView) { + // if we were delaying touches began and a gesture gets recognized, and we never sent it to the view, + // we need to throw it away and be sure we never send it to the view for the duration of the gesture + // so we do this by marking it both delivered and cancelled without actually sending it to the view. + event.touch.wasDeliveredToView = YES; + event.touch.wasCancelledInView = YES; + } else if (delaysTouchesBegan && !gestureRecognized && !possibleGestures && !event.touch.wasDeliveredToView && event.touch.phase != UITouchPhaseCancelled) { + // need to fake-send a touches began using the cached time and location in the touch + // a followup move or ended or cancelled touch will be sent below if necessary + const NSTimeInterval currentTimestamp = event.touch.timestamp; + const UITouchPhase currentPhase = event.touch.phase; + const CGPoint currentLocation = event.touch.locationOnScreen; - [view release]; + event.touch.timestamp = event.touch.beganPhaseTimestamp; + event.touch.locationOnScreen = event.touch.beganPhaseLocationOnScreen; + event.touch.phase = UITouchPhaseBegan; + + [view touchesBegan:event.allTouches withEvent:event]; + event.touch.wasDeliveredToView = YES; + + event.touch.phase = currentPhase; + event.touch.locationOnScreen = currentLocation; + event.touch.timestamp = currentTimestamp; + } + + if (event.touch.phase != UITouchPhaseBegan && event.touch.wasDeliveredToView && !event.touch.wasCancelledInView) { + if (event.touch.phase == UITouchPhaseCancelled) { + [view touchesCancelled:event.allTouches withEvent:event]; + event.touch.wasCancelledInView = YES; + } else if (gestureRecognized && (cancelsTouches || (event.touch.phase == UITouchPhaseEnded && delaysTouchesEnded))) { + // since we're supposed to cancel touches, mark it cancelled, send it to the view, and + // then change it back to whatever it was because there might be other gesture recognizers + // that are still using the touch for whatever reason and aren't going to expect it suddenly + // cancelled. (technically cancelled touches are, I think, meant to be a last resort.. + // the sort of thing that happens when a phone call comes in or a modal window comes up) + const UITouchPhase currentPhase = event.touch.phase; + + event.touch.phase = UITouchPhaseCancelled; + + [view touchesCancelled:event.allTouches withEvent:event]; + event.touch.wasCancelledInView = YES; + + event.touch.phase = currentPhase; + } else if (event.touch.phase == UITouchPhaseMoved) { + [view touchesMoved:event.allTouches withEvent:event]; + } else if (event.touch.phase == UITouchPhaseEnded) { + [view touchesEnded:event.allTouches withEvent:event]; + } } } + + NSCursor *newCursor = [view mouseCursorForEvent:event] ?: [NSCursor arrowCursor]; + + if ([NSCursor currentCursor] != newCursor) { + [newCursor set]; + } } @end diff --git a/UIKit/UIKit.xcodeproj/project.pbxproj b/UIKit/UIKit.xcodeproj/project.pbxproj index d47a64a1..187ba57a 100644 --- a/UIKit/UIKit.xcodeproj/project.pbxproj +++ b/UIKit/UIKit.xcodeproj/project.pbxproj @@ -7,6 +7,8 @@ objects = { /* Begin PBXBuildFile section */ + 14100F70175FB9C700269BBF /* UINSResponderShim.h in Headers */ = {isa = PBXBuildFile; fileRef = 14100F6E175FB9C700269BBF /* UINSResponderShim.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 14100F71175FB9C700269BBF /* UINSResponderShim.m in Sources */ = {isa = PBXBuildFile; fileRef = 14100F6F175FB9C700269BBF /* UINSResponderShim.m */; }; 1413D21213D72A06004D77E9 /* UIScrollViewAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = 1413D20C13D72A06004D77E9 /* UIScrollViewAnimation.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1413D21313D72A06004D77E9 /* UIScrollViewAnimation.m in Sources */ = {isa = PBXBuildFile; fileRef = 1413D20D13D72A06004D77E9 /* UIScrollViewAnimation.m */; }; 1413D21413D72A06004D77E9 /* UIScrollViewAnimationDeceleration.h in Headers */ = {isa = PBXBuildFile; fileRef = 1413D20E13D72A06004D77E9 /* UIScrollViewAnimationDeceleration.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -20,6 +22,7 @@ 1426A02715701598004C2C9A /* arrow-top@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1426A02215701598004C2C9A /* arrow-top@2x.png */; }; 1426FFDD129ADEA300BD31E5 /* UIControlAction.h in Headers */ = {isa = PBXBuildFile; fileRef = 1426FFDB129ADEA300BD31E5 /* UIControlAction.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1426FFDE129ADEA300BD31E5 /* UIControlAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 1426FFDC129ADEA300BD31E5 /* UIControlAction.m */; }; + 1434E8661770F4570023F2C5 /* UIViewControllerAppKitIntegration.h in Headers */ = {isa = PBXBuildFile; fileRef = 1434E8651770F4570023F2C5 /* UIViewControllerAppKitIntegration.h */; settings = {ATTRIBUTES = (Private, ); }; }; 144156DB1284A22200532FE2 /* UIToolbarButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 144156D91284A22200532FE2 /* UIToolbarButton.h */; settings = {ATTRIBUTES = (Private, ); }; }; 144156DC1284A22200532FE2 /* UIToolbarButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 144156DA1284A22200532FE2 /* UIToolbarButton.m */; }; 1443B06C13E06081001D7EC1 /* UIBackgroundTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 1443B06A13E06081001D7EC1 /* UIBackgroundTask.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -36,16 +39,15 @@ 145335861226F3490005644F /* UICustomNSClipView.m in Sources */ = {isa = PBXBuildFile; fileRef = 145335841226F3490005644F /* UICustomNSClipView.m */; }; 14541DB21360D6F300C1006D /* UIPhotosAlbum.h in Headers */ = {isa = PBXBuildFile; fileRef = 14541DB01360D6F300C1006D /* UIPhotosAlbum.h */; settings = {ATTRIBUTES = (Private, ); }; }; 14541DB31360D6F300C1006D /* UIPhotosAlbum.m in Sources */ = {isa = PBXBuildFile; fileRef = 14541DB11360D6F300C1006D /* UIPhotosAlbum.m */; }; - 145576231541DC560029EF4D /* UIAppearanceInstance.h in Headers */ = {isa = PBXBuildFile; fileRef = 145576221541DC560029EF4D /* UIAppearanceInstance.h */; }; + 145576231541DC560029EF4D /* UIAppearanceInstance.h in Headers */ = {isa = PBXBuildFile; fileRef = 145576221541DC560029EF4D /* UIAppearanceInstance.h */; settings = {ATTRIBUTES = (Private, ); }; }; 145576261541DC830029EF4D /* UIAppearanceInstance.m in Sources */ = {isa = PBXBuildFile; fileRef = 145576251541DC830029EF4D /* UIAppearanceInstance.m */; }; - 1457DD3F128DDE610057A7F9 /* UITransitionView.h in Headers */ = {isa = PBXBuildFile; fileRef = 1457DD3D128DDE610057A7F9 /* UITransitionView.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 1457DD40128DDE610057A7F9 /* UITransitionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1457DD3E128DDE610057A7F9 /* UITransitionView.m */; }; - 145BE31D15754F2400C41D70 /* UIColorRep.h in Headers */ = {isa = PBXBuildFile; fileRef = 145BE31B15754F2400C41D70 /* UIColorRep.h */; }; + 145BE31D15754F2400C41D70 /* UIColorRep.h in Headers */ = {isa = PBXBuildFile; fileRef = 145BE31B15754F2400C41D70 /* UIColorRep.h */; settings = {ATTRIBUTES = (Private, ); }; }; 145BE31E15754F2400C41D70 /* UIColorRep.m in Sources */ = {isa = PBXBuildFile; fileRef = 145BE31C15754F2400C41D70 /* UIColorRep.m */; }; - 145BE3211575523000C41D70 /* UIColor+UIPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 145BE3201575523000C41D70 /* UIColor+UIPrivate.h */; }; + 145BE3211575523000C41D70 /* UIColor+UIPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 145BE3201575523000C41D70 /* UIColor+UIPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 145D0B0517949A6800FB569B /* UINavigationItem+UIPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 145D0B0417949A6800FB569B /* UINavigationItem+UIPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1464960B11FF7AE500ECEC7A /* back-highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = 1464960711FF7AE500ECEC7A /* back-highlighted.png */; }; 1464960C11FF7AE500ECEC7A /* back.png in Resources */ = {isa = PBXBuildFile; fileRef = 1464960811FF7AE500ECEC7A /* back.png */; }; - 14711394156FC83F00251B2E /* UIImageRep.h in Headers */ = {isa = PBXBuildFile; fileRef = 14711392156FC83F00251B2E /* UIImageRep.h */; }; + 14711394156FC83F00251B2E /* UIImageRep.h in Headers */ = {isa = PBXBuildFile; fileRef = 14711392156FC83F00251B2E /* UIImageRep.h */; settings = {ATTRIBUTES = (Private, ); }; }; 14711395156FC83F00251B2E /* UIImageRep.m in Sources */ = {isa = PBXBuildFile; fileRef = 14711393156FC83F00251B2E /* UIImageRep.m */; }; 14805D4112A6B0E80080C4BA /* UINSClipView.h in Headers */ = {isa = PBXBuildFile; fileRef = 14805D3F12A6B0E80080C4BA /* UINSClipView.h */; settings = {ATTRIBUTES = (Private, ); }; }; 14805D4212A6B0E80080C4BA /* UINSClipView.m in Sources */ = {isa = PBXBuildFile; fileRef = 14805D4012A6B0E80080C4BA /* UINSClipView.m */; }; @@ -109,7 +111,7 @@ 1489859F12EE2CFF003D4751 /* UIImagePickerController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1489851912EE2CFE003D4751 /* UIImagePickerController.m */; }; 148985A012EE2CFF003D4751 /* UIImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = 1489851A12EE2CFE003D4751 /* UIImageView.h */; settings = {ATTRIBUTES = (Public, ); }; }; 148985A112EE2CFF003D4751 /* UIImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1489851B12EE2CFE003D4751 /* UIImageView.m */; }; - 148985A212EE2CFF003D4751 /* UIKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 1489851C12EE2CFE003D4751 /* UIKey.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 148985A212EE2CFF003D4751 /* UIKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 1489851C12EE2CFE003D4751 /* UIKey.h */; settings = {ATTRIBUTES = (Private, ); }; }; 148985A312EE2CFF003D4751 /* UIKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 1489851D12EE2CFE003D4751 /* UIKey.m */; }; 148985A412EE2CFF003D4751 /* UIKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 1489851E12EE2CFE003D4751 /* UIKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 148985A512EE2CFF003D4751 /* UIKitView.h in Headers */ = {isa = PBXBuildFile; fileRef = 1489851F12EE2CFE003D4751 /* UIKitView.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -208,7 +210,6 @@ 148DEEA1156E945800E7B8DE /* button@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 148DEE94156E945800E7B8DE /* button@2x.png */; }; 1490AFE01219C31C00774286 /* UIPopoverController+UIPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1490AFDE1219C31C00774286 /* UIPopoverController+UIPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; 149148BC12EE45ED00F7C34E /* UIGestureRecognizerSubclass.h in Headers */ = {isa = PBXBuildFile; fileRef = 149148BA12EE45ED00F7C34E /* UIGestureRecognizerSubclass.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 14A726D21213303400648C9B /* UIApplication+UIPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 14A726AF1213303400648C9B /* UIApplication+UIPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; 14A726D41213303400648C9B /* UIControl+UIPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 14A726B11213303400648C9B /* UIControl+UIPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; 14A726D71213303400648C9B /* UIImage+UIPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 14A726B41213303400648C9B /* UIImage+UIPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; 14A726D81213303400648C9B /* UIImageView+UIPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 14A726B51213303400648C9B /* UIImageView+UIPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -216,10 +217,9 @@ 14A726DC1213303400648C9B /* UITableViewCell+UIPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 14A726B91213303400648C9B /* UITableViewCell+UIPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; 14A726DD1213303400648C9B /* UITouch+UIPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 14A726BA1213303400648C9B /* UITouch+UIPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; 14A726DE1213303400648C9B /* UIView+UIPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 14A726BB1213303400648C9B /* UIView+UIPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 14A726DF1213303400648C9B /* UIViewController+UIPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 14A726BC1213303400648C9B /* UIViewController+UIPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; 14A726E01213303400648C9B /* UIWindow+UIPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 14A726BD1213303400648C9B /* UIWindow+UIPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 14BF16DB12E621EB007DAA01 /* UIViewBlockAnimationDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 14BF16D912E621EB007DAA01 /* UIViewBlockAnimationDelegate.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 14BF16DC12E621EB007DAA01 /* UIViewBlockAnimationDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 14BF16DA12E621EB007DAA01 /* UIViewBlockAnimationDelegate.m */; }; + 14BA42F217554D0200891B6D /* UITouchEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 14BA42F017554D0200891B6D /* UITouchEvent.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 14BA42F317554D0200891B6D /* UITouchEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 14BA42F117554D0200891B6D /* UITouchEvent.m */; }; 14C0715E13CF5A2400B76E35 /* UIAction.h in Headers */ = {isa = PBXBuildFile; fileRef = 14C0715C13CF5A2300B76E35 /* UIAction.h */; settings = {ATTRIBUTES = (Private, ); }; }; 14C0715F13CF5A2400B76E35 /* UIAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 14C0715D13CF5A2300B76E35 /* UIAction.m */; }; 14C0716213CF66B800B76E35 /* UIScrollWheelGestureRecognizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 14C0716013CF66B600B76E35 /* UIScrollWheelGestureRecognizer.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -235,6 +235,8 @@ 14CC843711EFA8BA005988CC /* grabber.png in Resources */ = {isa = PBXBuildFile; fileRef = 14CC842F11EFA8BA005988CC /* grabber.png */; }; 14CC844111EFA901005988CC /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 14CC844011EFA901005988CC /* QuartzCore.framework */; }; 14CC844511EFA91A005988CC /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 14CC844411EFA91A005988CC /* SystemConfiguration.framework */; }; + 14D0601717303DC100C9A7C6 /* UINSApplicationDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 14D0601517303DC100C9A7C6 /* UINSApplicationDelegate.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 14D0601817303DC100C9A7C6 /* UINSApplicationDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 14D0601617303DC100C9A7C6 /* UINSApplicationDelegate.m */; }; 14D796381540A5DA00C02139 /* UIAppearanceProperty.h in Headers */ = {isa = PBXBuildFile; fileRef = 14D796361540A5DA00C02139 /* UIAppearanceProperty.h */; settings = {ATTRIBUTES = (Private, ); }; }; 14D796391540A5DA00C02139 /* UIAppearanceProperty.m in Sources */ = {isa = PBXBuildFile; fileRef = 14D796371540A5DA00C02139 /* UIAppearanceProperty.m */; }; 14D8D941135DE90A00FE639A /* UIInputController.h in Headers */ = {isa = PBXBuildFile; fileRef = 14D8D93F135DE90A00FE639A /* UIInputController.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -243,8 +245,6 @@ 14DD1C361289B4D500DCF231 /* button-highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = 14DD1C341289B4D500DCF231 /* button-highlighted.png */; }; 14DD1C371289B4D500DCF231 /* button.png in Resources */ = {isa = PBXBuildFile; fileRef = 14DD1C351289B4D500DCF231 /* button.png */; }; 14E20663156FE88D0040349D /* UIImageAppKitIntegration.m in Sources */ = {isa = PBXBuildFile; fileRef = 14E20662156FE88D0040349D /* UIImageAppKitIntegration.m */; }; - 14EEF76712DF67CF00EB7D95 /* UIEvent+UIPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 14EEF76512DF67CF00EB7D95 /* UIEvent+UIPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 14EEF7A912DF6D9C00EB7D95 /* UIKey+UIPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 14EEF7A812DF6D9C00EB7D95 /* UIKey+UIPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; 14F0BC0D1288A67F00BA54F9 /* add.png in Resources */ = {isa = PBXBuildFile; fileRef = 14F0BC0B1288A67F00BA54F9 /* add.png */; }; 14F0BC0E1288A67F00BA54F9 /* reply.png in Resources */ = {isa = PBXBuildFile; fileRef = 14F0BC0C1288A67F00BA54F9 /* reply.png */; }; 14F56F3D12664D350045EC82 /* arrow-bottom.png in Resources */ = {isa = PBXBuildFile; fileRef = 14F56F3812664D350045EC82 /* arrow-bottom.png */; }; @@ -273,17 +273,15 @@ 14FDE99C153C9A1800A2D499 /* UIAppearance.h in Headers */ = {isa = PBXBuildFile; fileRef = 14FDE99A153C9A1800A2D499 /* UIAppearance.h */; settings = {ATTRIBUTES = (Public, ); }; }; 14FDE9A5153CAECA00A2D499 /* UIAppearanceProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 14FDE9A3153CAECA00A2D499 /* UIAppearanceProxy.h */; settings = {ATTRIBUTES = (Private, ); }; }; 14FDE9A6153CAECA00A2D499 /* UIAppearanceProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 14FDE9A4153CAECA00A2D499 /* UIAppearanceProxy.m */; }; + 14FE493A171C988B009C7794 /* UITextInput.h in Headers */ = {isa = PBXBuildFile; fileRef = 14FE4939171C988B009C7794 /* UITextInput.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 14FE4941171C9989009C7794 /* UITextInput.m in Sources */ = {isa = PBXBuildFile; fileRef = 14FE4940171C9989009C7794 /* UITextInput.m */; }; 38615C78133A81B900841EEA /* UIFont+UIPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 38615C77133A81B900841EEA /* UIFont+UIPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 38E523B11339680400E041B3 /* UINavigationItem+UIPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 38E523AF1339680400E041B3 /* UINavigationItem+UIPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 38E523B513396B5B00E041B3 /* UINavigationBar+UIPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 38E523B413396B5B00E041B3 /* UINavigationBar+UIPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; 537472D5133ADD4B00EBD5EA /* UIInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = 537472D3133ADD4B00EBD5EA /* UIInterface.h */; settings = {ATTRIBUTES = (Public, ); }; }; 537472D6133ADD4B00EBD5EA /* UIInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 537472D4133ADD4B00EBD5EA /* UIInterface.m */; }; 7011107C133BE0F400C86512 /* UIDatePicker.h in Headers */ = {isa = PBXBuildFile; fileRef = 7011107A133BE0F300C86512 /* UIDatePicker.h */; settings = {ATTRIBUTES = (Public, ); }; }; 7011107D133BE0F400C86512 /* UIDatePicker.m in Sources */ = {isa = PBXBuildFile; fileRef = 7011107B133BE0F300C86512 /* UIDatePicker.m */; }; 7806ED2A133A1D7500273BC6 /* UITabBar.h in Headers */ = {isa = PBXBuildFile; fileRef = 7806ED28133A1D7500273BC6 /* UITabBar.h */; settings = {ATTRIBUTES = (Public, ); }; }; 7806ED2B133A1D7500273BC6 /* UITabBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 7806ED29133A1D7500273BC6 /* UITabBar.m */; }; - 789CF898133A3CD500250AB4 /* NSFetchedResultsController.h in Headers */ = {isa = PBXBuildFile; fileRef = 789CF896133A3CD500250AB4 /* NSFetchedResultsController.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 789CF899133A3CD500250AB4 /* NSFetchedResultsController.m in Sources */ = {isa = PBXBuildFile; fileRef = 789CF897133A3CD500250AB4 /* NSFetchedResultsController.m */; }; 78CB48AC133A9C51008636DA /* UISearchBar.h in Headers */ = {isa = PBXBuildFile; fileRef = 78CB48AA133A9C51008636DA /* UISearchBar.h */; settings = {ATTRIBUTES = (Public, ); }; }; 78CB48AD133A9C51008636DA /* UISearchBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 78CB48AB133A9C51008636DA /* UISearchBar.m */; }; 78CB48B0133AA536008636DA /* UITabBarItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 78CB48AE133AA535008636DA /* UITabBarItem.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -303,6 +301,8 @@ 0867D69BFE84028FC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; 0867D6A5FE840307C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; + 14100F6E175FB9C700269BBF /* UINSResponderShim.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UINSResponderShim.h; sourceTree = ""; }; + 14100F6F175FB9C700269BBF /* UINSResponderShim.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UINSResponderShim.m; sourceTree = ""; }; 1413D20C13D72A06004D77E9 /* UIScrollViewAnimation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIScrollViewAnimation.h; sourceTree = ""; }; 1413D20D13D72A06004D77E9 /* UIScrollViewAnimation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIScrollViewAnimation.m; sourceTree = ""; }; 1413D20E13D72A06004D77E9 /* UIScrollViewAnimationDeceleration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIScrollViewAnimationDeceleration.h; sourceTree = ""; }; @@ -316,6 +316,7 @@ 1426A02215701598004C2C9A /* arrow-top@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = " arrow-top@2x.png"; path = "Resources/ arrow-top@2x.png"; sourceTree = ""; }; 1426FFDB129ADEA300BD31E5 /* UIControlAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIControlAction.h; sourceTree = ""; }; 1426FFDC129ADEA300BD31E5 /* UIControlAction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIControlAction.m; sourceTree = ""; }; + 1434E8651770F4570023F2C5 /* UIViewControllerAppKitIntegration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIViewControllerAppKitIntegration.h; sourceTree = ""; }; 144156D91284A22200532FE2 /* UIToolbarButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIToolbarButton.h; sourceTree = ""; }; 144156DA1284A22200532FE2 /* UIToolbarButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIToolbarButton.m; sourceTree = ""; }; 1443B06A13E06081001D7EC1 /* UIBackgroundTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIBackgroundTask.h; sourceTree = ""; }; @@ -334,11 +335,10 @@ 14541DB11360D6F300C1006D /* UIPhotosAlbum.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIPhotosAlbum.m; sourceTree = ""; }; 145576221541DC560029EF4D /* UIAppearanceInstance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIAppearanceInstance.h; sourceTree = ""; }; 145576251541DC830029EF4D /* UIAppearanceInstance.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIAppearanceInstance.m; sourceTree = ""; }; - 1457DD3D128DDE610057A7F9 /* UITransitionView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UITransitionView.h; sourceTree = ""; }; - 1457DD3E128DDE610057A7F9 /* UITransitionView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UITransitionView.m; sourceTree = ""; }; 145BE31B15754F2400C41D70 /* UIColorRep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIColorRep.h; sourceTree = ""; }; 145BE31C15754F2400C41D70 /* UIColorRep.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIColorRep.m; sourceTree = ""; }; 145BE3201575523000C41D70 /* UIColor+UIPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIColor+UIPrivate.h"; sourceTree = ""; }; + 145D0B0417949A6800FB569B /* UINavigationItem+UIPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UINavigationItem+UIPrivate.h"; sourceTree = ""; }; 1464960711FF7AE500ECEC7A /* back-highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = " back-highlighted.png"; path = "Resources/ back-highlighted.png"; sourceTree = ""; }; 1464960811FF7AE500ECEC7A /* back.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = " back.png"; path = "Resources/ back.png"; sourceTree = ""; }; 14711392156FC83F00251B2E /* UIImageRep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIImageRep.h; sourceTree = ""; }; @@ -504,7 +504,6 @@ 148DEE94156E945800E7B8DE /* button@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = " button@2x.png"; path = "Resources/ button@2x.png"; sourceTree = ""; }; 1490AFDE1219C31C00774286 /* UIPopoverController+UIPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIPopoverController+UIPrivate.h"; sourceTree = ""; }; 149148BA12EE45ED00F7C34E /* UIGestureRecognizerSubclass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIGestureRecognizerSubclass.h; sourceTree = ""; }; - 14A726AF1213303400648C9B /* UIApplication+UIPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIApplication+UIPrivate.h"; sourceTree = ""; }; 14A726B11213303400648C9B /* UIControl+UIPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIControl+UIPrivate.h"; sourceTree = ""; }; 14A726B41213303400648C9B /* UIImage+UIPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+UIPrivate.h"; sourceTree = ""; }; 14A726B51213303400648C9B /* UIImageView+UIPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImageView+UIPrivate.h"; sourceTree = ""; }; @@ -512,10 +511,9 @@ 14A726B91213303400648C9B /* UITableViewCell+UIPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UITableViewCell+UIPrivate.h"; sourceTree = ""; }; 14A726BA1213303400648C9B /* UITouch+UIPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UITouch+UIPrivate.h"; sourceTree = ""; }; 14A726BB1213303400648C9B /* UIView+UIPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+UIPrivate.h"; sourceTree = ""; }; - 14A726BC1213303400648C9B /* UIViewController+UIPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIViewController+UIPrivate.h"; sourceTree = ""; }; 14A726BD1213303400648C9B /* UIWindow+UIPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIWindow+UIPrivate.h"; sourceTree = ""; }; - 14BF16D912E621EB007DAA01 /* UIViewBlockAnimationDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIViewBlockAnimationDelegate.h; sourceTree = ""; }; - 14BF16DA12E621EB007DAA01 /* UIViewBlockAnimationDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIViewBlockAnimationDelegate.m; sourceTree = ""; }; + 14BA42F017554D0200891B6D /* UITouchEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UITouchEvent.h; sourceTree = ""; }; + 14BA42F117554D0200891B6D /* UITouchEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UITouchEvent.m; sourceTree = ""; }; 14C0715C13CF5A2300B76E35 /* UIAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIAction.h; sourceTree = ""; }; 14C0715D13CF5A2300B76E35 /* UIAction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIAction.m; sourceTree = ""; }; 14C0716013CF66B600B76E35 /* UIScrollWheelGestureRecognizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIScrollWheelGestureRecognizer.h; sourceTree = ""; }; @@ -531,6 +529,8 @@ 14CC842F11EFA8BA005988CC /* grabber.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = " grabber.png"; path = "Resources/ grabber.png"; sourceTree = ""; }; 14CC844011EFA901005988CC /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 14CC844411EFA91A005988CC /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; + 14D0601517303DC100C9A7C6 /* UINSApplicationDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UINSApplicationDelegate.h; sourceTree = ""; }; + 14D0601617303DC100C9A7C6 /* UINSApplicationDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UINSApplicationDelegate.m; sourceTree = ""; }; 14D796361540A5DA00C02139 /* UIAppearanceProperty.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIAppearanceProperty.h; sourceTree = ""; }; 14D796371540A5DA00C02139 /* UIAppearanceProperty.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIAppearanceProperty.m; sourceTree = ""; }; 14D8D93F135DE90A00FE639A /* UIInputController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIInputController.h; sourceTree = ""; }; @@ -539,8 +539,6 @@ 14DD1C341289B4D500DCF231 /* button-highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = " button-highlighted.png"; path = "Resources/ button-highlighted.png"; sourceTree = ""; }; 14DD1C351289B4D500DCF231 /* button.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = " button.png"; path = "Resources/ button.png"; sourceTree = ""; }; 14E20662156FE88D0040349D /* UIImageAppKitIntegration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIImageAppKitIntegration.m; sourceTree = ""; }; - 14EEF76512DF67CF00EB7D95 /* UIEvent+UIPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIEvent+UIPrivate.h"; sourceTree = ""; }; - 14EEF7A812DF6D9C00EB7D95 /* UIKey+UIPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIKey+UIPrivate.h"; sourceTree = ""; }; 14F0BC0B1288A67F00BA54F9 /* add.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = " add.png"; path = "Resources/ add.png"; sourceTree = ""; }; 14F0BC0C1288A67F00BA54F9 /* reply.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = " reply.png"; path = "Resources/ reply.png"; sourceTree = ""; }; 14F56F3812664D350045EC82 /* arrow-bottom.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = " arrow-bottom.png"; path = "Resources/ arrow-bottom.png"; sourceTree = ""; }; @@ -569,18 +567,16 @@ 14FDE99A153C9A1800A2D499 /* UIAppearance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIAppearance.h; sourceTree = ""; }; 14FDE9A3153CAECA00A2D499 /* UIAppearanceProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIAppearanceProxy.h; sourceTree = ""; }; 14FDE9A4153CAECA00A2D499 /* UIAppearanceProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIAppearanceProxy.m; sourceTree = ""; }; + 14FE4939171C988B009C7794 /* UITextInput.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UITextInput.h; sourceTree = ""; }; + 14FE4940171C9989009C7794 /* UITextInput.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UITextInput.m; sourceTree = ""; }; 32DBCF5E0370ADEE00C91783 /* UIKit_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIKit_Prefix.pch; sourceTree = ""; }; 38615C77133A81B900841EEA /* UIFont+UIPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIFont+UIPrivate.h"; sourceTree = ""; }; - 38E523AF1339680400E041B3 /* UINavigationItem+UIPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UINavigationItem+UIPrivate.h"; sourceTree = ""; }; - 38E523B413396B5B00E041B3 /* UINavigationBar+UIPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UINavigationBar+UIPrivate.h"; sourceTree = ""; }; 537472D3133ADD4B00EBD5EA /* UIInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIInterface.h; sourceTree = ""; }; 537472D4133ADD4B00EBD5EA /* UIInterface.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIInterface.m; sourceTree = ""; }; 7011107A133BE0F300C86512 /* UIDatePicker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIDatePicker.h; sourceTree = ""; }; 7011107B133BE0F300C86512 /* UIDatePicker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIDatePicker.m; sourceTree = ""; }; 7806ED28133A1D7500273BC6 /* UITabBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UITabBar.h; sourceTree = ""; }; 7806ED29133A1D7500273BC6 /* UITabBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UITabBar.m; sourceTree = ""; }; - 789CF896133A3CD500250AB4 /* NSFetchedResultsController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSFetchedResultsController.h; sourceTree = ""; }; - 789CF897133A3CD500250AB4 /* NSFetchedResultsController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSFetchedResultsController.m; sourceTree = ""; }; 78CB48AA133A9C51008636DA /* UISearchBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UISearchBar.h; sourceTree = ""; }; 78CB48AB133A9C51008636DA /* UISearchBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UISearchBar.m; sourceTree = ""; }; 78CB48AE133AA535008636DA /* UITabBarItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UITabBarItem.h; sourceTree = ""; }; @@ -695,8 +691,6 @@ isa = PBXGroup; children = ( 148984E412EE2CFE003D4751 /* AppKitIntegration.h */, - 789CF896133A3CD500250AB4 /* NSFetchedResultsController.h */, - 789CF897133A3CD500250AB4 /* NSFetchedResultsController.m */, 148984E512EE2CFE003D4751 /* NSIndexPath+UITableView.h */, 148984E612EE2CFE003D4751 /* NSIndexPath+UITableView.m */, 148984E712EE2CFE003D4751 /* UIAcceleration.h */, @@ -759,8 +753,6 @@ 1489851B12EE2CFE003D4751 /* UIImageView.m */, 537472D3133ADD4B00EBD5EA /* UIInterface.h */, 537472D4133ADD4B00EBD5EA /* UIInterface.m */, - 1489851C12EE2CFE003D4751 /* UIKey.h */, - 1489851D12EE2CFE003D4751 /* UIKey.m */, 1489851E12EE2CFE003D4751 /* UIKit.h */, 1489851F12EE2CFE003D4751 /* UIKitView.h */, 1489852012EE2CFE003D4751 /* UIKitView.m */, @@ -842,6 +834,8 @@ 1489855612EE2CFE003D4751 /* UITapGestureRecognizer.m */, 1489855712EE2CFE003D4751 /* UITextField.h */, 1489855812EE2CFE003D4751 /* UITextField.m */, + 14FE4939171C988B009C7794 /* UITextInput.h */, + 14FE4940171C9989009C7794 /* UITextInput.m */, 1489855912EE2CFE003D4751 /* UITextInputTraits.h */, 1489855A12EE2CFE003D4751 /* UITextView.h */, 1489855B12EE2CFE003D4751 /* UITextView.m */, @@ -855,6 +849,7 @@ 1489856312EE2CFE003D4751 /* UIViewAdapter.m */, 1489856412EE2CFE003D4751 /* UIViewController.h */, 1489856512EE2CFE003D4751 /* UIViewController.m */, + 1434E8651770F4570023F2C5 /* UIViewControllerAppKitIntegration.h */, 1489856612EE2CFE003D4751 /* UIWebView.h */, 1489856712EE2CFE003D4751 /* UIWebView.m */, 1489856812EE2CFE003D4751 /* UIWindow.h */, @@ -890,10 +885,16 @@ 14711393156FC83F00251B2E /* UIImageRep.m */, 14D8D93F135DE90A00FE639A /* UIInputController.h */, 14D8D940135DE90A00FE639A /* UIInputController.m */, + 1489851C12EE2CFE003D4751 /* UIKey.h */, + 1489851D12EE2CFE003D4751 /* UIKey.m */, 14FA8C47121DA4A000C4264B /* UINinePartImage.h */, 14FA8C48121DA4A000C4264B /* UINinePartImage.m */, + 14D0601517303DC100C9A7C6 /* UINSApplicationDelegate.h */, + 14D0601617303DC100C9A7C6 /* UINSApplicationDelegate.m */, 14805D3F12A6B0E80080C4BA /* UINSClipView.h */, 14805D4012A6B0E80080C4BA /* UINSClipView.m */, + 14100F6E175FB9C700269BBF /* UINSResponderShim.h */, + 14100F6F175FB9C700269BBF /* UINSResponderShim.m */, 14541DB01360D6F300C1006D /* UIPhotosAlbum.h */, 14541DB11360D6F300C1006D /* UIPhotosAlbum.m */, 14CB384312689907003334AD /* UIPopoverNSWindow.h */, @@ -924,12 +925,10 @@ 14FA8C58121DA4A000C4264B /* UIThreePartImage.m */, 144156D91284A22200532FE2 /* UIToolbarButton.h */, 144156DA1284A22200532FE2 /* UIToolbarButton.m */, - 1457DD3D128DDE610057A7F9 /* UITransitionView.h */, - 1457DD3E128DDE610057A7F9 /* UITransitionView.m */, + 14BA42F017554D0200891B6D /* UITouchEvent.h */, + 14BA42F117554D0200891B6D /* UITouchEvent.m */, 14FA8C59121DA4A000C4264B /* UIViewAnimationGroup.h */, 14FA8C5A121DA4A000C4264B /* UIViewAnimationGroup.m */, - 14BF16D912E621EB007DAA01 /* UIViewBlockAnimationDelegate.h */, - 14BF16DA12E621EB007DAA01 /* UIViewBlockAnimationDelegate.m */, 14FA8C5B121DA4A000C4264B /* UIViewLayoutManager.h */, 14FA8C5C121DA4A000C4264B /* UIViewLayoutManager.m */, ); @@ -940,18 +939,14 @@ 14FA8C44121DA47500C4264B /* Private Categories */ = { isa = PBXGroup; children = ( - 14A726AF1213303400648C9B /* UIApplication+UIPrivate.h */, 145BE3201575523000C41D70 /* UIColor+UIPrivate.h */, 14A726B11213303400648C9B /* UIControl+UIPrivate.h */, - 14EEF76512DF67CF00EB7D95 /* UIEvent+UIPrivate.h */, 38615C77133A81B900841EEA /* UIFont+UIPrivate.h */, 148984A312EE278D003D4751 /* UIGestureRecognizer+UIPrivate.h */, 14A726B41213303400648C9B /* UIImage+UIPrivate.h */, 14DD1C271289B3C900DCF231 /* UIImage+UIPrivate.m */, 14A726B51213303400648C9B /* UIImageView+UIPrivate.h */, - 14EEF7A812DF6D9C00EB7D95 /* UIKey+UIPrivate.h */, - 38E523B413396B5B00E041B3 /* UINavigationBar+UIPrivate.h */, - 38E523AF1339680400E041B3 /* UINavigationItem+UIPrivate.h */, + 145D0B0417949A6800FB569B /* UINavigationItem+UIPrivate.h */, 1490AFDE1219C31C00774286 /* UIPopoverController+UIPrivate.h */, 14A726B71213303400648C9B /* UIScreen+UIPrivate.h */, 1443DF23121F0D5A00E07C4A /* UIScreenMode+UIPrivate.h */, @@ -959,7 +954,6 @@ 14A726B91213303400648C9B /* UITableViewCell+UIPrivate.h */, 14A726BA1213303400648C9B /* UITouch+UIPrivate.h */, 14A726BB1213303400648C9B /* UIView+UIPrivate.h */, - 14A726BC1213303400648C9B /* UIViewController+UIPrivate.h */, 14A726BD1213303400648C9B /* UIWindow+UIPrivate.h */, ); name = "Private Categories"; @@ -981,12 +975,10 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 789CF898133A3CD500250AB4 /* NSFetchedResultsController.h in Headers */, 78CB48D9133AB922008636DA /* UISlider.h in Headers */, 78CB48B4133AA8AF008636DA /* UISegmentedControl.h in Headers */, 14CC840611EFA8AF005988CC /* UIRoundedRectButton.h in Headers */, 78CB48BC133AADD0008636DA /* UIPickerView.h in Headers */, - 14A726D21213303400648C9B /* UIApplication+UIPrivate.h in Headers */, 14A726D41213303400648C9B /* UIControl+UIPrivate.h in Headers */, 14A726D71213303400648C9B /* UIImage+UIPrivate.h in Headers */, 14A726D81213303400648C9B /* UIImageView+UIPrivate.h in Headers */, @@ -994,7 +986,6 @@ 14A726DC1213303400648C9B /* UITableViewCell+UIPrivate.h in Headers */, 14A726DD1213303400648C9B /* UITouch+UIPrivate.h in Headers */, 14A726DE1213303400648C9B /* UIView+UIPrivate.h in Headers */, - 14A726DF1213303400648C9B /* UIViewController+UIPrivate.h in Headers */, 78CB48B0133AA536008636DA /* UITabBarItem.h in Headers */, 14A726E01213303400648C9B /* UIWindow+UIPrivate.h in Headers */, 78D533DD133A9434006F17CA /* UISearchDisplayController.h in Headers */, @@ -1032,7 +1023,6 @@ 1489859D12EE2CFF003D4751 /* UIImageAppKitIntegration.h in Headers */, 1489859E12EE2CFF003D4751 /* UIImagePickerController.h in Headers */, 148985A012EE2CFF003D4751 /* UIImageView.h in Headers */, - 148985A212EE2CFF003D4751 /* UIKey.h in Headers */, 148985A412EE2CFF003D4751 /* UIKit.h in Headers */, 148985A512EE2CFF003D4751 /* UIKitView.h in Headers */, 148985A712EE2CFF003D4751 /* UILabel.h in Headers */, @@ -1058,24 +1048,20 @@ 14F56F4412664D430045EC82 /* UIPopoverView.h in Headers */, 14CB384512689907003334AD /* UIPopoverNSWindow.h in Headers */, 14CB384912689949003334AD /* UIPopoverOverlayNSView.h in Headers */, - 1457DD3F128DDE610057A7F9 /* UITransitionView.h in Headers */, 14805F5A12A6E2AE0080C4BA /* UIScrollView+UIPrivate.h in Headers */, - 14EEF76712DF67CF00EB7D95 /* UIEvent+UIPrivate.h in Headers */, - 14EEF7A912DF6D9C00EB7D95 /* UIKey+UIPrivate.h in Headers */, - 14BF16DB12E621EB007DAA01 /* UIViewBlockAnimationDelegate.h in Headers */, 148984A512EE278D003D4751 /* UIGestureRecognizer+UIPrivate.h in Headers */, - 38E523B11339680400E041B3 /* UINavigationItem+UIPrivate.h in Headers */, 14805D4112A6B0E80080C4BA /* UINSClipView.h in Headers */, 144156DB1284A22200532FE2 /* UIToolbarButton.h in Headers */, 1426FFDD129ADEA300BD31E5 /* UIControlAction.h in Headers */, 14C0716213CF66B800B76E35 /* UIScrollWheelGestureRecognizer.h in Headers */, - 38E523B513396B5B00E041B3 /* UINavigationBar+UIPrivate.h in Headers */, + 14FE493A171C988B009C7794 /* UITextInput.h in Headers */, 14FDE99C153C9A1800A2D499 /* UIAppearance.h in Headers */, 38615C78133A81B900841EEA /* UIFont+UIPrivate.h in Headers */, 148985B312EE2CFF003D4751 /* UINavigationItem.h in Headers */, 148985B512EE2CFF003D4751 /* UINibLoading.h in Headers */, 148985B712EE2CFF003D4751 /* UIPageControl.h in Headers */, 148985B912EE2CFF003D4751 /* UIPasteboard.h in Headers */, + 148985A212EE2CFF003D4751 /* UIKey.h in Headers */, 148985BB12EE2CFF003D4751 /* UIPinchGestureRecognizer.h in Headers */, 148985BD12EE2CFF003D4751 /* UIPopoverController.h in Headers */, 148985BF12EE2CFF003D4751 /* UIProgressView.h in Headers */, @@ -1116,12 +1102,17 @@ 14D8D941135DE90A00FE639A /* UIInputController.h in Headers */, 14541DB21360D6F300C1006D /* UIPhotosAlbum.h in Headers */, 14C0715E13CF5A2400B76E35 /* UIAction.h in Headers */, - 14FDE9A5153CAECA00A2D499 /* UIAppearanceProxy.h in Headers */, - 14D796381540A5DA00C02139 /* UIAppearanceProperty.h in Headers */, 145576231541DC560029EF4D /* UIAppearanceInstance.h in Headers */, 14711394156FC83F00251B2E /* UIImageRep.h in Headers */, 145BE31D15754F2400C41D70 /* UIColorRep.h in Headers */, 145BE3211575523000C41D70 /* UIColor+UIPrivate.h in Headers */, + 14D0601717303DC100C9A7C6 /* UINSApplicationDelegate.h in Headers */, + 14BA42F217554D0200891B6D /* UITouchEvent.h in Headers */, + 14100F70175FB9C700269BBF /* UINSResponderShim.h in Headers */, + 1434E8661770F4570023F2C5 /* UIViewControllerAppKitIntegration.h in Headers */, + 145D0B0517949A6800FB569B /* UINavigationItem+UIPrivate.h in Headers */, + 14FDE9A5153CAECA00A2D499 /* UIAppearanceProxy.h in Headers */, + 14D796381540A5DA00C02139 /* UIAppearanceProperty.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1153,7 +1144,7 @@ 0867D690FE84028FC02AAC07 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0460; + LastUpgradeCheck = 0510; }; buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "UIKit" */; compatibilityVersion = "Xcode 3.2"; @@ -1222,7 +1213,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 789CF899133A3CD500250AB4 /* NSFetchedResultsController.m in Sources */, 78CB48B1133AA536008636DA /* UITabBarItem.m in Sources */, 78CB48AD133A9C51008636DA /* UISearchBar.m in Sources */, 14CC840711EFA8AF005988CC /* UIRoundedRectButton.m in Sources */, @@ -1243,10 +1233,8 @@ 14CB384A12689949003334AD /* UIPopoverOverlayNSView.m in Sources */, 144156DC1284A22200532FE2 /* UIToolbarButton.m in Sources */, 14DD1C281289B3C900DCF231 /* UIImage+UIPrivate.m in Sources */, - 1457DD40128DDE610057A7F9 /* UITransitionView.m in Sources */, 1426FFDE129ADEA300BD31E5 /* UIControlAction.m in Sources */, 14805D4212A6B0E80080C4BA /* UINSClipView.m in Sources */, - 14BF16DC12E621EB007DAA01 /* UIViewBlockAnimationDelegate.m in Sources */, 1489856C12EE2CFF003D4751 /* NSIndexPath+UITableView.m in Sources */, 1489856E12EE2CFF003D4751 /* UIAcceleration.m in Sources */, 1489857012EE2CFF003D4751 /* UIAccelerometer.m in Sources */, @@ -1333,6 +1321,10 @@ 14711395156FC83F00251B2E /* UIImageRep.m in Sources */, 14E20663156FE88D0040349D /* UIImageAppKitIntegration.m in Sources */, 145BE31E15754F2400C41D70 /* UIColorRep.m in Sources */, + 14FE4941171C9989009C7794 /* UITextInput.m in Sources */, + 14D0601817303DC100C9A7C6 /* UINSApplicationDelegate.m in Sources */, + 14BA42F317554D0200891B6D /* UITouchEvent.m in Sources */, + 14100F71175FB9C700269BBF /* UINSResponderShim.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1343,6 +1335,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ENABLE_OBJC_ARC = YES; COPY_PHASE_STRIP = NO; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; @@ -1356,7 +1349,6 @@ INSTALL_PATH = "@executable_path/../Frameworks"; PRODUCT_NAME = UIKit; SYMROOT = ../build; - VALID_ARCHS = "i386 x86_64"; WRAPPER_EXTENSION = framework; }; name = Debug; @@ -1365,6 +1357,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ENABLE_OBJC_ARC = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; @@ -1376,7 +1369,6 @@ INSTALL_PATH = "@executable_path/../Frameworks"; PRODUCT_NAME = UIKit; SYMROOT = ../build; - VALID_ARCHS = "i386 x86_64"; WRAPPER_EXTENSION = framework; }; name = Release; @@ -1384,13 +1376,12 @@ 1DEB91B208733DA50010E9CD /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_OPTIMIZATION_LEVEL = 0; GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.6; + MACOSX_DEPLOYMENT_TARGET = 10.7; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; }; @@ -1399,13 +1390,12 @@ 1DEB91B308733DA50010E9CD /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - CODE_SIGN_IDENTITY = "3rd Party Mac Developer Application"; + CODE_SIGN_IDENTITY = "Developer ID Application: The Iconfactory"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.6; + MACOSX_DEPLOYMENT_TARGET = 10.7; PROVISIONING_PROFILE = ""; SDKROOT = macosx; }; diff --git a/UIKit/UIKit.xcodeproj/project.xcworkspace/xcshareddata/UIKit.xccheckout b/UIKit/UIKit.xcodeproj/project.xcworkspace/xcshareddata/UIKit.xccheckout new file mode 100644 index 00000000..76973da2 --- /dev/null +++ b/UIKit/UIKit.xcodeproj/project.xcworkspace/xcshareddata/UIKit.xccheckout @@ -0,0 +1,50 @@ + + + + + IDESourceControlProjectFavoriteDictionaryKey + + IDESourceControlProjectIdentifier + DDACB42D-640A-4EF9-AE4D-A20276EBFE16 + IDESourceControlProjectName + UIKit + IDESourceControlProjectOriginsDictionary + + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + svn://dev.iconfactory.net/Projects/Software/UIKit/trunk + + IDESourceControlProjectPath + UIKit/UIKit.xcodeproj/project.xcworkspace + IDESourceControlProjectRelativeInstallPathDictionary + + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + ../../.. + + IDESourceControlProjectRepositoryRootDictionary + + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + svn://dev.iconfactory.net/Projects/Software + + IDESourceControlProjectURL + svn://dev.iconfactory.net/Projects/Software/UIKit/trunk/UIKit/UIKit.xcodeproj + IDESourceControlProjectVersion + 110 + IDESourceControlProjectWCCIdentifier + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + IDESourceControlProjectWCConfigurations + + + IDESourceControlRepositoryBranchesRelativeLocationKey + UIKit/branches + IDESourceControlRepositoryExtensionIdentifierKey + public.vcs.subversion + IDESourceControlRepositoryTrunkRelativeLocationKey + UIKit/trunk + IDESourceControlWCCIdentifierKey + 4D4CCC13-43EF-4EE0-831F-37E84AFA83EA + IDESourceControlWCCName + UIKit + + + + diff --git a/UIKit/UIKit_Prefix.pch b/UIKit/UIKit_Prefix.pch index 73ffda54..a9ca302e 100644 --- a/UIKit/UIKit_Prefix.pch +++ b/UIKit/UIKit_Prefix.pch @@ -30,13 +30,3 @@ #ifdef __OBJC__ #import #endif - -// If ARC is not enabled, declare empty ARC directives to supress compiler errors -#ifndef __has_feature - #define __has_feature(x) 0 // Compatibility with non-clang compilers. -#endif - -#if !__has_feature(objc_arc) - #define __unsafe_unretained - #define __bridge -#endif